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/system/chromeos/tray_caps_lock.h"
7 #include "ash/metrics/user_metrics_recorder.h"
9 #include "ash/system/tray/actionable_view.h"
10 #include "ash/system/tray/fixed_sized_image_view.h"
11 #include "ash/system/tray/system_tray_notifier.h"
12 #include "ash/system/tray/tray_constants.h"
13 #include "base/sys_info.h"
14 #include "chromeos/ime/ime_keyboard.h"
15 #include "chromeos/ime/input_method_manager.h"
16 #include "grit/ash_resources.h"
17 #include "grit/ash_strings.h"
18 #include "ui/accessibility/ax_view_state.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/gfx/image/image.h"
21 #include "ui/views/controls/image_view.h"
22 #include "ui/views/controls/label.h"
23 #include "ui/views/layout/box_layout.h"
24 #include "ui/views/widget/widget.h"
29 bool CapsLockIsEnabled() {
30 chromeos::input_method::InputMethodManager
* ime
=
31 chromeos::input_method::InputMethodManager::Get();
32 return (ime
&& ime
->GetImeKeyboard())
33 ? ime
->GetImeKeyboard()->CapsLockIsEnabled()
39 class CapsLockDefaultView
: public ActionableView
{
42 : text_label_(new views::Label
),
43 shortcut_label_(new views::Label
) {
44 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal
,
45 kTrayPopupPaddingHorizontal
,
47 kTrayPopupPaddingBetweenItems
));
49 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
50 FixedSizedImageView
* image
=
51 new FixedSizedImageView(0, kTrayPopupItemHeight
);
52 image
->SetImage(bundle
.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK
).
56 text_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
57 AddChildView(text_label_
);
59 shortcut_label_
->SetEnabled(false);
60 AddChildView(shortcut_label_
);
63 virtual ~CapsLockDefaultView() {}
65 // Updates the label text and the shortcut text.
66 void Update(bool caps_lock_enabled
) {
67 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
68 const int text_string_id
= caps_lock_enabled
?
69 IDS_ASH_STATUS_TRAY_CAPS_LOCK_ENABLED
:
70 IDS_ASH_STATUS_TRAY_CAPS_LOCK_DISABLED
;
71 text_label_
->SetText(bundle
.GetLocalizedString(text_string_id
));
73 int shortcut_string_id
= 0;
74 bool search_mapped_to_caps_lock
= Shell::GetInstance()->
75 system_tray_delegate()->IsSearchKeyMappedToCapsLock();
76 if (caps_lock_enabled
) {
77 shortcut_string_id
= search_mapped_to_caps_lock
?
78 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_SEARCH_OR_SHIFT
:
79 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_ALT_SEARCH_OR_SHIFT
;
81 shortcut_string_id
= search_mapped_to_caps_lock
?
82 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_SEARCH
:
83 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_ALT_SEARCH
;
85 shortcut_label_
->SetText(bundle
.GetLocalizedString(shortcut_string_id
));
91 // Overridden from views::View:
92 virtual void Layout() OVERRIDE
{
93 views::View::Layout();
95 // Align the shortcut text with the right end
96 const int old_x
= shortcut_label_
->x();
98 width() - shortcut_label_
->width() - kTrayPopupPaddingHorizontal
;
99 shortcut_label_
->SetX(new_x
);
100 const gfx::Size text_size
= text_label_
->size();
101 text_label_
->SetSize(gfx::Size(text_size
.width() + new_x
- old_x
,
102 text_size
.height()));
105 virtual void GetAccessibleState(ui::AXViewState
* state
) OVERRIDE
{
106 state
->role
= ui::AX_ROLE_BUTTON
;
107 state
->name
= text_label_
->text();
110 // Overridden from ActionableView:
111 virtual bool PerformAction(const ui::Event
& event
) OVERRIDE
{
112 chromeos::input_method::ImeKeyboard
* keyboard
=
113 chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
114 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
115 keyboard
->CapsLockIsEnabled() ?
116 ash::UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK
:
117 ash::UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK
);
118 keyboard
->SetCapsLockEnabled(!keyboard
->CapsLockIsEnabled());
122 views::Label
* text_label_
;
123 views::Label
* shortcut_label_
;
125 DISALLOW_COPY_AND_ASSIGN(CapsLockDefaultView
);
128 TrayCapsLock::TrayCapsLock(SystemTray
* system_tray
)
129 : TrayImageItem(system_tray
, IDR_AURA_UBER_TRAY_CAPS_LOCK
),
132 caps_lock_enabled_(CapsLockIsEnabled()),
133 message_shown_(false) {
134 // Since keyboard handling differs between ChromeOS and Linux we need to
135 // use different observers depending on the two platforms.
136 if (base::SysInfo::IsRunningOnChromeOS()) {
137 chromeos::input_method::ImeKeyboard
* keyboard
=
138 chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
139 keyboard
->AddObserver(this);
141 Shell::GetInstance()->PrependPreTargetHandler(this);
145 TrayCapsLock::~TrayCapsLock() {
146 // Since keyboard handling differs between ChromeOS and Linux we need to
147 // use different observers depending on the two platforms.
148 if (base::SysInfo::IsRunningOnChromeOS()) {
149 chromeos::input_method::ImeKeyboard
* keyboard
=
150 chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
151 keyboard
->RemoveObserver(this);
153 Shell::GetInstance()->RemovePreTargetHandler(this);
157 void TrayCapsLock::OnCapsLockChanged(bool enabled
) {
158 caps_lock_enabled_
= enabled
;
161 tray_view()->SetVisible(caps_lock_enabled_
);
164 default_
->Update(caps_lock_enabled_
);
166 if (caps_lock_enabled_
) {
167 if (!message_shown_
) {
168 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
169 ash::UMA_STATUS_AREA_CAPS_LOCK_POPUP
);
170 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds
, false);
171 message_shown_
= true;
173 } else if (detailed_
) {
174 detailed_
->GetWidget()->Close();
179 void TrayCapsLock::OnKeyEvent(ui::KeyEvent
* key
) {
180 if (key
->type() == ui::ET_KEY_PRESSED
&& key
->key_code() == ui::VKEY_CAPITAL
)
181 OnCapsLockChanged(!caps_lock_enabled_
);
184 bool TrayCapsLock::GetInitialVisibility() {
185 return CapsLockIsEnabled();
188 views::View
* TrayCapsLock::CreateDefaultView(user::LoginStatus status
) {
189 if (!caps_lock_enabled_
)
191 DCHECK(default_
== NULL
);
192 default_
= new CapsLockDefaultView
;
193 default_
->Update(caps_lock_enabled_
);
197 views::View
* TrayCapsLock::CreateDetailedView(user::LoginStatus status
) {
198 DCHECK(detailed_
== NULL
);
199 detailed_
= new views::View
;
201 detailed_
->SetLayoutManager(new
202 views::BoxLayout(views::BoxLayout::kHorizontal
,
203 kTrayPopupPaddingHorizontal
, 10, kTrayPopupPaddingBetweenItems
));
205 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
206 views::ImageView
* image
= new views::ImageView
;
207 image
->SetImage(bundle
.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK
).
210 detailed_
->AddChildView(image
);
212 const int string_id
= Shell::GetInstance()->system_tray_delegate()->
213 IsSearchKeyMappedToCapsLock() ?
214 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH
:
215 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH
;
216 views::Label
* label
= new views::Label(bundle
.GetLocalizedString(string_id
));
217 label
->SetMultiLine(true);
218 label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
219 detailed_
->AddChildView(label
);
220 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
221 ash::UMA_STATUS_AREA_CAPS_LOCK_DETAILED
);
226 void TrayCapsLock::DestroyDefaultView() {
230 void TrayCapsLock::DestroyDetailedView() {