tray_caps_lock.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 "chromeos/ime/input_method_manager.h" 14#include "chromeos/ime/xkeyboard.h" 15#include "grit/ash_resources.h" 16#include "grit/ash_strings.h" 17#include "ui/accessibility/ax_view_state.h" 18#include "ui/base/resource/resource_bundle.h" 19#include "ui/gfx/image/image.h" 20#include "ui/views/controls/image_view.h" 21#include "ui/views/controls/label.h" 22#include "ui/views/layout/box_layout.h" 23#include "ui/views/widget/widget.h" 24 25namespace ash { 26namespace internal { 27 28namespace { 29 30bool CapsLockIsEnabled() { 31 chromeos::input_method::InputMethodManager* ime = 32 chromeos::input_method::InputMethodManager::Get(); 33 return (ime && ime->GetXKeyboard()) ? ime->GetXKeyboard()->CapsLockIsEnabled() 34 : false; 35} 36 37} 38 39class CapsLockDefaultView : public ActionableView { 40 public: 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 63 virtual ~CapsLockDefaultView() {} 64 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)); 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: 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 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: 111 virtual bool PerformAction(const ui::Event& event) OVERRIDE { 112 chromeos::input_method::XKeyboard* xkeyboard = 113 chromeos::input_method::InputMethodManager::Get()->GetXKeyboard(); 114 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 115 xkeyboard->CapsLockIsEnabled() ? 116 ash::UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK : 117 ash::UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK); 118 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled()); 119 return true; 120 } 121 122 views::Label* text_label_; 123 views::Label* shortcut_label_; 124 125 DISALLOW_COPY_AND_ASSIGN(CapsLockDefaultView); 126}; 127 128TrayCapsLock::TrayCapsLock(SystemTray* system_tray) 129 : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_CAPS_LOCK), 130 default_(NULL), 131 detailed_(NULL), 132 caps_lock_enabled_(CapsLockIsEnabled()), 133 message_shown_(false) { 134 // Make sure the event is processed by this before the IME. 135 Shell::GetInstance()->PrependPreTargetHandler(this); 136} 137 138TrayCapsLock::~TrayCapsLock() { 139 Shell::GetInstance()->RemovePreTargetHandler(this); 140} 141 142void TrayCapsLock::OnCapsLockChanged(bool enabled) { 143 if (tray_view()) 144 tray_view()->SetVisible(enabled); 145 146 caps_lock_enabled_ = enabled; 147 148 if (default_) { 149 default_->Update(enabled); 150 } else { 151 if (enabled) { 152 if (!message_shown_) { 153 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 154 ash::UMA_STATUS_AREA_CAPS_LOCK_POPUP); 155 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); 156 message_shown_ = true; 157 } 158 } else if (detailed_) { 159 detailed_->GetWidget()->Close(); 160 } 161 } 162} 163 164void TrayCapsLock::OnKeyEvent(ui::KeyEvent* key) { 165 if (key->type() == ui::ET_KEY_PRESSED && key->key_code() == ui::VKEY_CAPITAL) 166 OnCapsLockChanged(!caps_lock_enabled_); 167} 168 169bool TrayCapsLock::GetInitialVisibility() { 170 return CapsLockIsEnabled(); 171} 172 173views::View* TrayCapsLock::CreateDefaultView(user::LoginStatus status) { 174 if (!caps_lock_enabled_) 175 return NULL; 176 DCHECK(default_ == NULL); 177 default_ = new CapsLockDefaultView; 178 default_->Update(caps_lock_enabled_); 179 return default_; 180} 181 182views::View* TrayCapsLock::CreateDetailedView(user::LoginStatus status) { 183 DCHECK(detailed_ == NULL); 184 detailed_ = new views::View; 185 186 detailed_->SetLayoutManager(new 187 views::BoxLayout(views::BoxLayout::kHorizontal, 188 kTrayPopupPaddingHorizontal, 10, kTrayPopupPaddingBetweenItems)); 189 190 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 191 views::ImageView* image = new views::ImageView; 192 image->SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK). 193 ToImageSkia()); 194 195 detailed_->AddChildView(image); 196 197 const int string_id = Shell::GetInstance()->system_tray_delegate()-> 198 IsSearchKeyMappedToCapsLock() ? 199 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH : 200 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH; 201 views::Label* label = new views::Label(bundle.GetLocalizedString(string_id)); 202 label->SetMultiLine(true); 203 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 204 detailed_->AddChildView(label); 205 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 206 ash::UMA_STATUS_AREA_CAPS_LOCK_DETAILED); 207 208 return detailed_; 209} 210 211void TrayCapsLock::DestroyDefaultView() { 212 default_ = NULL; 213} 214 215void TrayCapsLock::DestroyDetailedView() { 216 detailed_ = NULL; 217} 218 219} // namespace internal 220} // namespace ash 221