OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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. | |
4 | |
5 #include "ash/sticky_keys/sticky_keys_overlay.h" | |
6 | |
7 #include "ash/shell.h" | |
8 #include "ash/shell_window_ids.h" | |
9 #include "ash/sticky_keys/sticky_keys_controller.h" | |
10 #include "base/strings/string_util.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "grit/ash_strings.h" | |
13 #include "ui/base/l10n/l10n_util.h" | |
14 #include "ui/compositor/scoped_layer_animation_settings.h" | |
15 #include "ui/gfx/canvas.h" | |
16 #include "ui/gfx/font_list.h" | |
17 #include "ui/views/border.h" | |
18 #include "ui/views/controls/label.h" | |
19 #include "ui/views/layout/box_layout.h" | |
20 #include "ui/views/view.h" | |
21 #include "ui/views/widget/widget.h" | |
22 #include "ui/views/widget/widget_delegate.h" | |
23 | |
24 namespace ash { | |
25 | |
26 namespace { | |
27 | |
28 // Horizontal offset of the overlay from the top left of the screen. | |
29 const int kHorizontalOverlayOffset = 18; | |
30 | |
31 // Vertical offset of the overlay from the top left of the screen. | |
32 const int kVerticalOverlayOffset = 18; | |
33 | |
34 // Spacing between overlay contents and border. | |
35 const int kHorizontalBorderSpacing = 9; | |
36 const int kVerticalBorderSpacing = 4; | |
37 | |
38 // Spacing between modifier key labels. | |
39 const int kKeyLabelSpacing = 7; | |
40 | |
41 // Duration of slide animation when overlay is shown or hidden. | |
42 const int kSlideAnimationDurationMs = 100; | |
43 | |
44 } | |
45 | |
46 /////////////////////////////////////////////////////////////////////////////// | |
47 // StickyKeyOverlayLabel | |
48 class StickyKeyOverlayLabel : public views::Label { | |
49 public: | |
50 explicit StickyKeyOverlayLabel(const std::string& key_name); | |
51 | |
52 virtual ~StickyKeyOverlayLabel(); | |
53 | |
54 void SetKeyState(StickyKeyState state); | |
55 | |
56 StickyKeyState state() { return state_; } | |
James Cook
2014/01/15 22:53:53
nit: const, and usually we put these above the Set
Tim Song
2014/01/16 00:01:59
Done.
| |
57 | |
58 private: | |
59 virtual void PaintText(gfx::Canvas* canvas, | |
James Cook
2014/01/15 22:53:53
nit: comment what class you are overriding, like "
Tim Song
2014/01/16 00:01:59
Done.
| |
60 const base::string16& text, | |
61 const gfx::Rect& text_bounds, | |
62 int flags) OVERRIDE; | |
63 | |
64 StickyKeyState state_; | |
65 | |
66 DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel); | |
67 }; | |
68 | |
69 StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name) | |
70 : state_(STICKY_KEY_STATE_DISABLED) { | |
71 SetText(base::UTF8ToUTF16(key_name)); | |
72 SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
73 SetFontList( | |
74 font_list().DeriveFontListWithSize(18)); | |
75 SetAutoColorReadabilityEnabled(false); | |
76 SetFocusable(false); | |
77 SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF)); | |
78 SetDisabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF)); | |
79 set_border(views::Border::CreateEmptyBorder(0, 0, 0, 0)); | |
James Cook
2014/01/15 22:53:53
I'm a bit confused -- this adds an empty, zero-wid
Tim Song
2014/01/16 00:01:59
Done. I wanted to ensure the insets to be zero, bu
| |
80 } | |
81 | |
82 StickyKeyOverlayLabel::~StickyKeyOverlayLabel() { | |
83 } | |
84 | |
85 void StickyKeyOverlayLabel::SetKeyState(StickyKeyState state) { | |
86 state_ = state; | |
87 SkColor label_color; | |
88 int style; | |
89 switch (state) { | |
90 case STICKY_KEY_STATE_ENABLED: | |
91 style = gfx::Font::NORMAL; | |
92 label_color = SkColorSetA(enabled_color(), 0xFF); | |
93 break; | |
94 case STICKY_KEY_STATE_LOCKED: | |
95 style = gfx::Font::UNDERLINE; | |
96 label_color = SkColorSetA(enabled_color(), 0xFF); | |
97 break; | |
98 default: | |
99 style = gfx::Font::NORMAL; | |
100 label_color = SkColorSetA(enabled_color(), 0x80); | |
101 } | |
102 | |
103 SetEnabledColor(label_color); | |
104 SetDisabledColor(label_color); | |
105 SetFontList(font_list().DeriveFontListWithSizeDeltaAndStyle(0, style)); | |
106 } | |
107 | |
108 void StickyKeyOverlayLabel::PaintText(gfx::Canvas* canvas, | |
109 const base::string16& text, | |
110 const gfx::Rect& text_bounds, | |
111 int flags) { | |
112 views::Label::PaintText(canvas, | |
113 text, | |
114 text_bounds, | |
115 flags | gfx::Canvas::NO_SUBPIXEL_RENDERING); | |
116 } | |
117 | |
118 | |
119 /////////////////////////////////////////////////////////////////////////////// | |
120 // StickyKeyOverlayLabel | |
121 class StickyKeysOverlayView : public views::WidgetDelegateView { | |
122 public: | |
123 StickyKeysOverlayView(); | |
124 | |
125 virtual ~StickyKeysOverlayView(); | |
126 | |
127 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; | |
James Cook
2014/01/15 22:53:53
nit: comment what you are overriding
Tim Song
2014/01/16 00:01:59
Done.
| |
128 | |
129 void SetKeyState(StickyKeyModifier modifier, StickyKeyState state); | |
130 | |
131 StickyKeyState GetKeyState(StickyKeyModifier modifier); | |
132 | |
133 private: | |
134 void AddKeyLabel(StickyKeyModifier modifier, const std::string& key_label); | |
135 | |
136 typedef std::map<StickyKeyModifier, StickyKeyOverlayLabel*> ModifierLabelMap; | |
137 ModifierLabelMap modifier_label_map_; | |
138 | |
139 DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView); | |
140 }; | |
141 | |
142 StickyKeysOverlayView::StickyKeysOverlayView() { | |
143 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, | |
144 kHorizontalBorderSpacing, | |
145 kVerticalBorderSpacing, | |
146 kKeyLabelSpacing)); | |
147 AddKeyLabel(STICKY_KEY_CONTROL, | |
148 l10n_util::GetStringUTF8(IDS_ASH_STICKY_KEY_CONTROL)); | |
149 AddKeyLabel(STICKY_KEY_ALT, | |
150 l10n_util::GetStringUTF8(IDS_ASH_STICKY_KEY_ALT)); | |
151 AddKeyLabel(STICKY_KEY_SHIFT, | |
152 l10n_util::GetStringUTF8(IDS_ASH_STICKY_KEY_SHIFT)); | |
153 } | |
154 | |
155 StickyKeysOverlayView::~StickyKeysOverlayView() {} | |
156 | |
157 void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) { | |
158 SkPaint paint; | |
159 paint.setStyle(SkPaint::kFill_Style); | |
160 paint.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55)); | |
161 canvas->DrawRoundRect(GetLocalBounds(), 2, paint); | |
162 views::WidgetDelegateView::OnPaint(canvas); | |
163 } | |
164 | |
165 void StickyKeysOverlayView::SetKeyState(StickyKeyModifier modifier, | |
166 StickyKeyState state) { | |
167 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier); | |
168 DCHECK(it != modifier_label_map_.end()); | |
169 if (it != modifier_label_map_.end()) { | |
170 StickyKeyOverlayLabel* label = it->second; | |
171 label->SetKeyState(state); | |
172 } | |
173 } | |
174 | |
175 StickyKeyState StickyKeysOverlayView::GetKeyState(StickyKeyModifier modifier) { | |
176 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier); | |
177 DCHECK(it != modifier_label_map_.end()); | |
178 return it->second->state(); | |
179 } | |
180 | |
181 void StickyKeysOverlayView::AddKeyLabel(StickyKeyModifier modifier, | |
182 const std::string& key_label) { | |
183 StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label); | |
184 AddChildView(label); | |
185 modifier_label_map_[modifier] = label; | |
186 } | |
187 | |
188 /////////////////////////////////////////////////////////////////////////////// | |
189 // StickyKeysOverlay | |
190 StickyKeysOverlay::StickyKeysOverlay() | |
191 : is_showing_(false), | |
192 overlay_view_(new StickyKeysOverlayView) { | |
193 widget_size_ = overlay_view_->GetPreferredSize(); | |
194 | |
195 views::Widget::InitParams params; | |
196 params.type = views::Widget::InitParams::TYPE_POPUP; | |
197 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
198 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
199 params.accept_events = false; | |
200 params.can_activate = false; | |
201 params.keep_on_top = true; | |
202 params.remove_standard_frame = true; | |
203 params.delegate = overlay_view_; | |
204 params.bounds = gfx::Rect(gfx::Point(0, 0), widget_size_); | |
205 params.parent = Shell::GetContainer( | |
206 Shell::GetTargetRootWindow(), | |
207 internal::kShellWindowId_OverlayContainer); | |
208 overlay_widget_.reset(new views::Widget); | |
209 overlay_widget_->Init(params); | |
210 overlay_widget_->SetVisibilityChangedAnimationsEnabled(false); | |
211 overlay_widget_->SetContentsView(overlay_view_); | |
212 overlay_widget_->GetNativeView()->SetName("StickyKeysOverlay"); | |
213 | |
214 overlay_widget_->GetLayer()->SetTransform(CalculateOverlayTransform()); | |
215 } | |
216 | |
217 StickyKeysOverlay::~StickyKeysOverlay() {} | |
218 | |
219 void StickyKeysOverlay::Show(bool visible) { | |
220 if (is_showing_ == visible) | |
221 return; | |
222 | |
223 is_showing_ = visible; | |
224 if (is_showing_) | |
225 overlay_widget_->Show(); | |
226 | |
227 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator(); | |
228 if (animator) | |
James Cook
2014/01/15 22:53:53
Is animator ever null? I don't think so, and prob
Tim Song
2014/01/16 00:01:59
Done.
| |
229 animator->AddObserver(this); | |
230 | |
231 ui::ScopedLayerAnimationSettings settings(animator); | |
232 settings.SetPreemptionStrategy( | |
233 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
234 settings.SetTweenType(gfx::Tween::EASE_IN_OUT); | |
James Cook
2014/01/15 22:53:53
You might want to use EASE_OUT here, or EASE_OUT a
Tim Song
2014/01/16 00:01:59
Done. The mock is using the CSS animation transiti
| |
235 settings.SetTransitionDuration( | |
236 base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs)); | |
237 | |
238 overlay_widget_->GetLayer()->SetTransform(CalculateOverlayTransform()); | |
239 } | |
240 | |
241 void StickyKeysOverlay::SetModifierKeyState(StickyKeyModifier modifier, | |
242 StickyKeyState state) { | |
243 overlay_view_->SetKeyState(modifier, state); | |
244 } | |
245 | |
246 StickyKeyState StickyKeysOverlay::GetModifierKeyState( | |
247 StickyKeyModifier modifier) { | |
248 return overlay_view_->GetKeyState(modifier); | |
249 } | |
250 | |
251 gfx::Transform StickyKeysOverlay::CalculateOverlayTransform() { | |
James Cook
2014/01/15 22:53:53
This doesn't seem quite right. It looks like the w
Tim Song
2014/01/16 00:01:59
Done. What about the hidden case? Is it okay to le
James Cook
2014/01/16 00:46:20
I think we generally set it back to the identity t
Tim Song
2014/01/16 01:59:45
Done. The widget bounds is now updated whenever we
| |
252 gfx::Transform transform; | |
253 if (is_showing_) | |
254 transform.Translate(kHorizontalBorderSpacing, kVerticalBorderSpacing); | |
255 else | |
256 transform.Translate(-widget_size_.width(), kVerticalBorderSpacing); | |
257 return transform; | |
258 } | |
259 | |
260 void StickyKeysOverlay::OnLayerAnimationEnded( | |
261 ui::LayerAnimationSequence* sequence) { | |
262 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator(); | |
263 if (animator) | |
264 animator->RemoveObserver(this); | |
265 if (!is_showing_) | |
266 overlay_widget_->Hide(); | |
267 } | |
268 | |
269 void StickyKeysOverlay::OnLayerAnimationAborted( | |
270 ui::LayerAnimationSequence* sequence) { | |
271 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator(); | |
272 if (animator) | |
273 animator->RemoveObserver(this); | |
274 overlay_widget_->GetLayer()->SetTransform(CalculateOverlayTransform()); | |
275 } | |
276 | |
277 void StickyKeysOverlay::OnLayerAnimationScheduled( | |
278 ui::LayerAnimationSequence* sequence) { | |
279 } | |
280 | |
281 } // ash | |
James Cook
2014/01/15 22:53:53
"namespace ash"
Tim Song
2014/01/16 00:01:59
Done.
| |
OLD | NEW |