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();
115 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
116 keyboard->CapsLockIsEnabled() ?
117 ash::UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK :
118 ash::UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK);
119 keyboard->SetCapsLockEnabled(!keyboard->CapsLockIsEnabled());
124 views::Label* text_label_;
125 views::Label* shortcut_label_;
127 DISALLOW_COPY_AND_ASSIGN(CapsLockDefaultView);
130 TrayCapsLock::TrayCapsLock(SystemTray* system_tray)
131 : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_CAPS_LOCK),
134 caps_lock_enabled_(CapsLockIsEnabled()),
135 message_shown_(false) {
136 chromeos::input_method::InputMethodManager* ime =
137 chromeos::input_method::InputMethodManager::Get();
138 if (ime && ime->GetImeKeyboard())
139 ime->GetImeKeyboard()->AddObserver(this);
142 TrayCapsLock::~TrayCapsLock() {
143 chromeos::input_method::InputMethodManager* ime =
144 chromeos::input_method::InputMethodManager::Get();
145 if (ime && ime->GetImeKeyboard())
146 ime->GetImeKeyboard()->RemoveObserver(this);
149 void TrayCapsLock::OnCapsLockChanged(bool enabled) {
150 caps_lock_enabled_ = enabled;
153 tray_view()->SetVisible(caps_lock_enabled_);
156 default_->Update(caps_lock_enabled_);
158 if (caps_lock_enabled_) {
159 if (!message_shown_) {
160 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
161 ash::UMA_STATUS_AREA_CAPS_LOCK_POPUP);
162 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
163 message_shown_ = true;
165 } else if (detailed_) {
166 detailed_->GetWidget()->Close();
171 bool TrayCapsLock::GetInitialVisibility() {
172 return CapsLockIsEnabled();
175 views::View* TrayCapsLock::CreateDefaultView(user::LoginStatus status) {
176 if (!caps_lock_enabled_)
178 DCHECK(default_ == NULL);
179 default_ = new CapsLockDefaultView;
180 default_->Update(caps_lock_enabled_);
184 views::View* TrayCapsLock::CreateDetailedView(user::LoginStatus status) {
185 DCHECK(detailed_ == NULL);
186 detailed_ = new views::View;
188 detailed_->SetLayoutManager(new
189 views::BoxLayout(views::BoxLayout::kHorizontal,
190 kTrayPopupPaddingHorizontal, 10, kTrayPopupPaddingBetweenItems));
192 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
193 views::ImageView* image = new views::ImageView;
194 image->SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK).
197 detailed_->AddChildView(image);
199 const int string_id = Shell::GetInstance()->system_tray_delegate()->
200 IsSearchKeyMappedToCapsLock() ?
201 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH :
202 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH;
203 views::Label* label = new views::Label(bundle.GetLocalizedString(string_id));
204 label->SetMultiLine(true);
205 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
206 detailed_->AddChildView(label);
207 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
208 ash::UMA_STATUS_AREA_CAPS_LOCK_DETAILED);
213 void TrayCapsLock::DestroyDefaultView() {
217 void TrayCapsLock::DestroyDetailedView() {