Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / sticky_keys / sticky_keys_overlay.cc
blob5b239f7afb621314e8b95e3527cbfadc5ea61913
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.
5 #include "ash/sticky_keys/sticky_keys_overlay.h"
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/base/resource/resource_bundle.h"
15 #include "ui/compositor/scoped_layer_animation_settings.h"
16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/font_list.h"
18 #include "ui/views/border.h"
19 #include "ui/views/controls/label.h"
20 #include "ui/views/layout/box_layout.h"
21 #include "ui/views/view.h"
22 #include "ui/views/widget/widget.h"
23 #include "ui/views/widget/widget_delegate.h"
25 namespace ash {
27 namespace {
29 // Horizontal offset of the overlay from the top left of the screen.
30 const int kHorizontalOverlayOffset = 18;
32 // Vertical offset of the overlay from the top left of the screen.
33 const int kVerticalOverlayOffset = 18;
35 // Font style used for modifier key labels.
36 const ui::ResourceBundle::FontStyle kKeyLabelFontStyle =
37 ui::ResourceBundle::LargeFont;
39 // Duration of slide animation when overlay is shown or hidden.
40 const int kSlideAnimationDurationMs = 100;
44 ///////////////////////////////////////////////////////////////////////////////
45 // StickyKeyOverlayLabel
46 class StickyKeyOverlayLabel : public views::Label {
47 public:
48 explicit StickyKeyOverlayLabel(const std::string& key_name);
50 virtual ~StickyKeyOverlayLabel();
52 StickyKeyState state() const { return state_; }
54 void SetKeyState(StickyKeyState state);
56 private:
57 StickyKeyState state_;
59 DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel);
62 StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name)
63 : state_(STICKY_KEY_STATE_DISABLED) {
64 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
66 SetText(base::UTF8ToUTF16(key_name));
67 SetHorizontalAlignment(gfx::ALIGN_LEFT);
68 SetFontList(rb->GetFontList(kKeyLabelFontStyle));
69 SetAutoColorReadabilityEnabled(false);
70 SetFocusable(false);
71 SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
72 SetDisabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
73 SetSubpixelRenderingEnabled(false);
76 StickyKeyOverlayLabel::~StickyKeyOverlayLabel() {
79 void StickyKeyOverlayLabel::SetKeyState(StickyKeyState state) {
80 state_ = state;
81 SkColor label_color;
82 int style;
83 switch (state) {
84 case STICKY_KEY_STATE_ENABLED:
85 style = gfx::Font::NORMAL;
86 label_color = SkColorSetA(enabled_color(), 0xFF);
87 break;
88 case STICKY_KEY_STATE_LOCKED:
89 style = gfx::Font::UNDERLINE;
90 label_color = SkColorSetA(enabled_color(), 0xFF);
91 break;
92 default:
93 style = gfx::Font::NORMAL;
94 label_color = SkColorSetA(enabled_color(), 0x80);
97 SetEnabledColor(label_color);
98 SetDisabledColor(label_color);
99 SetFontList(font_list().DeriveWithStyle(style));
102 ///////////////////////////////////////////////////////////////////////////////
103 // StickyKeysOverlayView
104 class StickyKeysOverlayView : public views::WidgetDelegateView {
105 public:
106 StickyKeysOverlayView();
108 virtual ~StickyKeysOverlayView();
110 // views::WidgetDelegateView overrides:
111 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
113 void SetKeyState(ui::EventFlags modifier, StickyKeyState state);
115 StickyKeyState GetKeyState(ui::EventFlags modifier);
117 void SetModifierVisible(ui::EventFlags modifier, bool visible);
118 bool GetModifierVisible(ui::EventFlags modifier);
120 private:
121 void AddKeyLabel(ui::EventFlags modifier, const std::string& key_label);
123 typedef std::map<ui::EventFlags, StickyKeyOverlayLabel*> ModifierLabelMap;
124 ModifierLabelMap modifier_label_map_;
126 DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView);
129 StickyKeysOverlayView::StickyKeysOverlayView() {
130 const gfx::Font& font =
131 ui::ResourceBundle::GetSharedInstance().GetFont(kKeyLabelFontStyle);
132 int font_size = font.GetFontSize();
133 int font_padding = font.GetHeight() - font.GetBaseline();
135 // Text should have a margin of 0.5 times the font size on each side, so
136 // the spacing between two labels will be the same as the font size.
137 int horizontal_spacing = font_size / 2;
138 int vertical_spacing = font_size / 2 - font_padding;
139 int child_spacing = font_size - 2 * font_padding;
141 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
142 horizontal_spacing,
143 vertical_spacing,
144 child_spacing));
145 AddKeyLabel(ui::EF_CONTROL_DOWN,
146 l10n_util::GetStringUTF8(IDS_ASH_CONTROL_KEY));
147 AddKeyLabel(ui::EF_ALT_DOWN,
148 l10n_util::GetStringUTF8(IDS_ASH_ALT_KEY));
149 AddKeyLabel(ui::EF_SHIFT_DOWN,
150 l10n_util::GetStringUTF8(IDS_ASH_SHIFT_KEY));
151 AddKeyLabel(ui::EF_ALTGR_DOWN,
152 l10n_util::GetStringUTF8(IDS_ASH_ALTGR_KEY));
153 AddKeyLabel(ui::EF_MOD3_DOWN,
154 l10n_util::GetStringUTF8(IDS_ASH_MOD3_KEY));
157 StickyKeysOverlayView::~StickyKeysOverlayView() {}
159 void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) {
160 SkPaint paint;
161 paint.setStyle(SkPaint::kFill_Style);
162 paint.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55));
163 canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
164 views::WidgetDelegateView::OnPaint(canvas);
167 void StickyKeysOverlayView::SetKeyState(ui::EventFlags modifier,
168 StickyKeyState state) {
169 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
170 DCHECK(it != modifier_label_map_.end());
171 if (it != modifier_label_map_.end()) {
172 StickyKeyOverlayLabel* label = it->second;
173 label->SetKeyState(state);
177 StickyKeyState StickyKeysOverlayView::GetKeyState(ui::EventFlags modifier) {
178 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
179 DCHECK(it != modifier_label_map_.end());
180 return it->second->state();
183 void StickyKeysOverlayView::SetModifierVisible(ui::EventFlags modifier,
184 bool visible) {
185 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
186 DCHECK(it != modifier_label_map_.end());
187 it->second->SetVisible(visible);
190 bool StickyKeysOverlayView::GetModifierVisible(ui::EventFlags modifier) {
191 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
192 DCHECK(it != modifier_label_map_.end());
193 return it->second->visible();
196 void StickyKeysOverlayView::AddKeyLabel(ui::EventFlags modifier,
197 const std::string& key_label) {
198 StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
199 AddChildView(label);
200 modifier_label_map_[modifier] = label;
203 ///////////////////////////////////////////////////////////////////////////////
204 // StickyKeysOverlay
205 StickyKeysOverlay::StickyKeysOverlay()
206 : is_visible_(false),
207 overlay_view_(new StickyKeysOverlayView),
208 widget_size_(overlay_view_->GetPreferredSize()) {
209 views::Widget::InitParams params;
210 params.type = views::Widget::InitParams::TYPE_POPUP;
211 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
212 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
213 params.accept_events = false;
214 params.keep_on_top = true;
215 params.remove_standard_frame = true;
216 params.delegate = overlay_view_;
217 params.bounds = CalculateOverlayBounds();
218 params.parent = Shell::GetContainer(Shell::GetTargetRootWindow(),
219 kShellWindowId_OverlayContainer);
220 overlay_widget_.reset(new views::Widget);
221 overlay_widget_->Init(params);
222 overlay_widget_->SetVisibilityChangedAnimationsEnabled(false);
223 overlay_widget_->SetContentsView(overlay_view_);
224 overlay_widget_->GetNativeView()->SetName("StickyKeysOverlay");
227 StickyKeysOverlay::~StickyKeysOverlay() {}
229 void StickyKeysOverlay::Show(bool visible) {
230 if (is_visible_ == visible)
231 return;
233 is_visible_ = visible;
234 if (is_visible_)
235 overlay_widget_->Show();
236 overlay_widget_->SetBounds(CalculateOverlayBounds());
238 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
239 animator->AddObserver(this);
241 // Ensure transform is correct before beginning animation.
242 if (!animator->is_animating()) {
243 int sign = is_visible_ ? -1 : 1;
244 gfx::Transform transform;
245 transform.Translate(
246 sign * (widget_size_.width() + kHorizontalOverlayOffset), 0);
247 overlay_widget_->GetLayer()->SetTransform(transform);
250 ui::ScopedLayerAnimationSettings settings(animator);
251 settings.SetPreemptionStrategy(
252 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
253 settings.SetTweenType(visible ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
254 settings.SetTransitionDuration(
255 base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
257 overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
260 void StickyKeysOverlay::SetModifierVisible(ui::EventFlags modifier,
261 bool visible) {
262 overlay_view_->SetModifierVisible(modifier, visible);
263 widget_size_ = overlay_view_->GetPreferredSize();
266 bool StickyKeysOverlay::GetModifierVisible(ui::EventFlags modifier) {
267 return overlay_view_->GetModifierVisible(modifier);
270 void StickyKeysOverlay::SetModifierKeyState(ui::EventFlags modifier,
271 StickyKeyState state) {
272 overlay_view_->SetKeyState(modifier, state);
275 StickyKeyState StickyKeysOverlay::GetModifierKeyState(
276 ui::EventFlags modifier) {
277 return overlay_view_->GetKeyState(modifier);
280 gfx::Rect StickyKeysOverlay::CalculateOverlayBounds() {
281 int x = is_visible_ ? kHorizontalOverlayOffset : -widget_size_.width();
282 return gfx::Rect(gfx::Point(x, kVerticalOverlayOffset), widget_size_);
285 void StickyKeysOverlay::OnLayerAnimationEnded(
286 ui::LayerAnimationSequence* sequence) {
287 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
288 if (animator)
289 animator->RemoveObserver(this);
290 if (!is_visible_)
291 overlay_widget_->Hide();
294 void StickyKeysOverlay::OnLayerAnimationAborted(
295 ui::LayerAnimationSequence* sequence) {
296 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
297 if (animator)
298 animator->RemoveObserver(this);
301 void StickyKeysOverlay::OnLayerAnimationScheduled(
302 ui::LayerAnimationSequence* sequence) {
305 } // namespace ash