• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ash/system/chromeos/tray_caps_lock.h"
6 
7 #include "ash/metrics/user_metrics_recorder.h"
8 #include "ash/shell.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"
25 
26 namespace ash {
27 namespace {
28 
CapsLockIsEnabled()29 bool CapsLockIsEnabled() {
30   chromeos::input_method::InputMethodManager* ime =
31       chromeos::input_method::InputMethodManager::Get();
32   return (ime && ime->GetImeKeyboard())
33              ? ime->GetImeKeyboard()->CapsLockIsEnabled()
34              : false;
35 }
36 
37 }
38 
39 class CapsLockDefaultView : public ActionableView {
40  public:
CapsLockDefaultView()41   CapsLockDefaultView()
42       : text_label_(new views::Label),
43         shortcut_label_(new views::Label) {
44     SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
45                                           kTrayPopupPaddingHorizontal,
46                                           0,
47                                           kTrayPopupPaddingBetweenItems));
48 
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).
53         ToImageSkia());
54     AddChildView(image);
55 
56     text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
57     AddChildView(text_label_);
58 
59     shortcut_label_->SetEnabled(false);
60     AddChildView(shortcut_label_);
61   }
62 
~CapsLockDefaultView()63   virtual ~CapsLockDefaultView() {}
64 
65   // Updates the label text and the shortcut text.
Update(bool caps_lock_enabled)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));
72 
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;
80     } else {
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;
84     }
85     shortcut_label_->SetText(bundle.GetLocalizedString(shortcut_string_id));
86 
87     Layout();
88   }
89 
90  private:
91   // Overridden from views::View:
Layout()92   virtual void Layout() OVERRIDE {
93     views::View::Layout();
94 
95     // Align the shortcut text with the right end
96     const int old_x = shortcut_label_->x();
97     const int new_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()));
103   }
104 
GetAccessibleState(ui::AXViewState * state)105   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
106     state->role = ui::AX_ROLE_BUTTON;
107     state->name = text_label_->text();
108   }
109 
110   // Overridden from ActionableView:
PerformAction(const ui::Event & event)111   virtual bool PerformAction(const ui::Event& event) OVERRIDE {
112     chromeos::input_method::ImeKeyboard* keyboard =
113         chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
114     if (keyboard) {
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());
120     }
121     return true;
122   }
123 
124   views::Label* text_label_;
125   views::Label* shortcut_label_;
126 
127   DISALLOW_COPY_AND_ASSIGN(CapsLockDefaultView);
128 };
129 
TrayCapsLock(SystemTray * system_tray)130 TrayCapsLock::TrayCapsLock(SystemTray* system_tray)
131     : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_CAPS_LOCK),
132       default_(NULL),
133       detailed_(NULL),
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);
140 }
141 
~TrayCapsLock()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);
147 }
148 
OnCapsLockChanged(bool enabled)149 void TrayCapsLock::OnCapsLockChanged(bool enabled) {
150   caps_lock_enabled_ = enabled;
151 
152   if (tray_view())
153     tray_view()->SetVisible(caps_lock_enabled_);
154 
155   if (default_) {
156     default_->Update(caps_lock_enabled_);
157   } else {
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;
164       }
165     } else if (detailed_) {
166       detailed_->GetWidget()->Close();
167     }
168   }
169 }
170 
GetInitialVisibility()171 bool TrayCapsLock::GetInitialVisibility() {
172   return CapsLockIsEnabled();
173 }
174 
CreateDefaultView(user::LoginStatus status)175 views::View* TrayCapsLock::CreateDefaultView(user::LoginStatus status) {
176   if (!caps_lock_enabled_)
177     return NULL;
178   DCHECK(default_ == NULL);
179   default_ = new CapsLockDefaultView;
180   default_->Update(caps_lock_enabled_);
181   return default_;
182 }
183 
CreateDetailedView(user::LoginStatus status)184 views::View* TrayCapsLock::CreateDetailedView(user::LoginStatus status) {
185   DCHECK(detailed_ == NULL);
186   detailed_ = new views::View;
187 
188   detailed_->SetLayoutManager(new
189       views::BoxLayout(views::BoxLayout::kHorizontal,
190       kTrayPopupPaddingHorizontal, 10, kTrayPopupPaddingBetweenItems));
191 
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).
195       ToImageSkia());
196 
197   detailed_->AddChildView(image);
198 
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);
209 
210   return detailed_;
211 }
212 
DestroyDefaultView()213 void TrayCapsLock::DestroyDefaultView() {
214   default_ = NULL;
215 }
216 
DestroyDetailedView()217 void TrayCapsLock::DestroyDetailedView() {
218   detailed_ = NULL;
219 }
220 
221 }  // namespace ash
222