1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/touch/touch_observer_hud.h"
7 #include "ash/shell_window_ids.h"
8 #include "base/stringprintf.h"
9 #include "base/utf_string_conversions.h"
10 #include "third_party/skia/include/core/SkPath.h"
11 #include "third_party/skia/include/core/SkXfermode.h"
12 #include "ui/base/events/event.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/gfx/display.h"
15 #include "ui/gfx/rect.h"
16 #include "ui/gfx/screen.h"
17 #include "ui/gfx/size.h"
18 #include "ui/views/background.h"
19 #include "ui/views/controls/label.h"
20 #include "ui/views/layout/box_layout.h"
21 #include "ui/views/widget/widget.h"
26 const int kMaxPaths
= 15;
27 const int kScale
= 10;
28 const int kColors
[] = {
29 static_cast<int>(SK_ColorYELLOW
),
30 static_cast<int>(SK_ColorGREEN
),
31 static_cast<int>(SK_ColorRED
),
32 static_cast<int>(SK_ColorBLUE
),
33 static_cast<int>(SK_ColorMAGENTA
),
34 static_cast<int>(SK_ColorCYAN
),
35 static_cast<int>(SK_ColorWHITE
),
36 static_cast<int>(SK_ColorBLACK
)
39 class TouchHudCanvas
: public views::View
{
41 explicit TouchHudCanvas(TouchObserverHUD
* owner
)
45 gfx::Display display
= Shell::GetScreen()->GetPrimaryDisplay();
46 gfx::Rect bounds
= display
.bounds();
47 size_
.set_width(bounds
.width() / kScale
);
48 size_
.set_height(bounds
.height() / kScale
);
51 virtual ~TouchHudCanvas() {}
53 void Start(int id
, const gfx::Point
& point
) {
54 paths_
[path_index_
].reset();
55 paths_
[path_index_
].moveTo(SkIntToScalar(point
.x() / kScale
),
56 SkIntToScalar(point
.y() / kScale
));
57 colors_
[path_index_
] = kColors
[color_index_
];
58 color_index_
= (color_index_
+ 1) % arraysize(kColors
);
60 touch_id_to_path_
[id
] = path_index_
;
61 path_index_
= (path_index_
+ 1) % kMaxPaths
;
65 void Update(int id
, gfx::Point
& to
) {
67 int path_id
= touch_id_to_path_
[id
];
68 SkScalar x
= SkIntToScalar(to
.x() / kScale
);
69 SkScalar y
= SkIntToScalar(to
.y() / kScale
);
70 if (!paths_
[path_id
].getLastPt(&last
) || x
!= last
.x() || y
!= last
.y())
71 paths_
[path_id
].lineTo(x
, y
);
76 // Overridden from views::View.
77 virtual gfx::Size
GetPreferredSize() OVERRIDE
{
81 virtual void OnPaint(gfx::Canvas
* canvas
) OVERRIDE
{
82 canvas
->DrawColor(SK_ColorBLACK
, SkXfermode::kClear_Mode
);
83 canvas
->DrawColor(SkColorSetARGB(25, 0, 0, 0));
86 paint
.setStrokeWidth(SkIntToScalar(2));
87 paint
.setStyle(SkPaint::kStroke_Style
);
88 for (size_t i
= 0; i
< arraysize(paths_
); ++i
) {
89 if (paths_
[i
].countPoints() == 0)
91 paint
.setColor(colors_
[i
]);
92 if (paths_
[i
].countPoints() == 1) {
93 SkPoint point
= paths_
[i
].getPoint(0);
94 canvas
->sk_canvas()->drawPoint(point
.x(), point
.y(), paint
);
96 canvas
->DrawPath(paths_
[i
], paint
);
101 TouchObserverHUD
* owner_
;
102 SkPath paths_
[kMaxPaths
];
103 SkColor colors_
[kMaxPaths
];
108 std::map
<int, int> touch_id_to_path_
;
112 DISALLOW_COPY_AND_ASSIGN(TouchHudCanvas
);
115 TouchObserverHUD::TouchObserverHUD() {
116 views::View
* content
= new views::View
;
117 content
->SetLayoutManager(new views::BoxLayout(
118 views::BoxLayout::kVertical
, 0, 0, 0));
120 canvas_
= new TouchHudCanvas(this);
121 content
->AddChildView(canvas_
);
122 for (int i
= 0; i
< kMaxTouchPoints
; ++i
) {
123 touch_status_
[i
] = ui::ET_UNKNOWN
;
124 touch_labels_
[i
] = new views::Label
;
125 touch_labels_
[i
]->SetBackgroundColor(SkColorSetARGB(0, 255, 255, 255));
126 touch_labels_
[i
]->SetShadowColors(SK_ColorWHITE
,
128 touch_labels_
[i
]->SetShadowOffset(1, 1);
129 touch_labels_
[i
]->SetVisible(false);
130 content
->AddChildView(touch_labels_
[i
]);
133 widget_
= new views::Widget();
134 views::Widget::InitParams
135 params(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
136 params
.transparent
= true;
137 params
.can_activate
= false;
138 params
.accept_events
= false;
139 params
.bounds
= gfx::Rect(content
->GetPreferredSize());
140 params
.parent
= Shell::GetContainer(
141 Shell::GetPrimaryRootWindow(),
142 internal::kShellWindowId_OverlayContainer
);
143 widget_
->Init(params
);
144 widget_
->SetContentsView(content
);
145 widget_
->StackAtTop();
148 // The TouchObserverHUD's lifetime is always more than |widget_|. The
149 // |widget_| is unset from the OnWidgetClosing callback.
150 widget_
->AddObserver(this);
153 TouchObserverHUD::~TouchObserverHUD() {
154 // The widget should have already been destroyed.
158 void TouchObserverHUD::UpdateTouchPointLabel(int index
) {
159 const char* status
= NULL
;
160 switch (touch_status_
[index
]) {
164 case ui::ET_TOUCH_PRESSED
:
167 case ui::ET_TOUCH_MOVED
:
170 case ui::ET_TOUCH_RELEASED
:
173 case ui::ET_TOUCH_CANCELLED
:
180 std::string string
= base::StringPrintf("%2d: %s %s",
181 index
, status
, touch_positions_
[index
].ToString().c_str());
182 touch_labels_
[index
]->SetText(UTF8ToUTF16(string
));
185 void TouchObserverHUD::OnTouchEvent(ui::TouchEvent
* event
) {
186 if (event
->touch_id() >= kMaxTouchPoints
)
189 if (event
->type() != ui::ET_TOUCH_CANCELLED
)
190 touch_positions_
[event
->touch_id()] = event
->root_location();
191 if (event
->type() == ui::ET_TOUCH_PRESSED
)
192 canvas_
->Start(event
->touch_id(), touch_positions_
[event
->touch_id()]);
194 canvas_
->Update(event
->touch_id(), touch_positions_
[event
->touch_id()]);
195 touch_status_
[event
->touch_id()] = event
->type();
196 touch_labels_
[event
->touch_id()]->SetVisible(true);
197 UpdateTouchPointLabel(event
->touch_id());
199 widget_
->SetSize(widget_
->GetContentsView()->GetPreferredSize());
202 void TouchObserverHUD::OnWidgetClosing(views::Widget
* widget
) {
203 DCHECK_EQ(widget
, widget_
);
207 } // namespace internal