tray_caps_lock.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 26namespace ash { 27namespace { 28 29bool 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 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::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 130TrayCapsLock::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 142TrayCapsLock::~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 149void 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 171bool TrayCapsLock::GetInitialVisibility() { 172 return CapsLockIsEnabled(); 173} 174 175views::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 184views::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 213void TrayCapsLock::DestroyDefaultView() { 214 default_ = NULL; 215} 216 217void TrayCapsLock::DestroyDetailedView() { 218 detailed_ = NULL; 219} 220 221} // namespace ash 222