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/tray_caps_lock.h" 6 7 #include "ash/caps_lock_delegate.h" 8 #include "ash/metrics/user_metrics_recorder.h" 9 #include "ash/shell.h" 10 #include "ash/system/tray/actionable_view.h" 11 #include "ash/system/tray/fixed_sized_image_view.h" 12 #include "ash/system/tray/system_tray_notifier.h" 13 #include "ash/system/tray/tray_constants.h" 14 #include "grit/ash_resources.h" 15 #include "grit/ash_strings.h" 16 #include "ui/base/accessibility/accessible_view_state.h" 17 #include "ui/base/resource/resource_bundle.h" 18 #include "ui/gfx/image/image.h" 19 #include "ui/views/controls/image_view.h" 20 #include "ui/views/controls/label.h" 21 #include "ui/views/layout/box_layout.h" 22 #include "ui/views/widget/widget.h" 23 24 namespace ash { 25 namespace internal { 26 27 class CapsLockDefaultView : public ActionableView { 28 public: 29 CapsLockDefaultView() 30 : text_label_(new views::Label), 31 shortcut_label_(new views::Label) { 32 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 33 kTrayPopupPaddingHorizontal, 34 0, 35 kTrayPopupPaddingBetweenItems)); 36 37 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 38 FixedSizedImageView* image = 39 new FixedSizedImageView(0, kTrayPopupItemHeight); 40 image->SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK). 41 ToImageSkia()); 42 AddChildView(image); 43 44 text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 45 AddChildView(text_label_); 46 47 shortcut_label_->SetEnabled(false); 48 AddChildView(shortcut_label_); 49 } 50 51 virtual ~CapsLockDefaultView() {} 52 53 // Updates the label text and the shortcut text. 54 void Update(bool caps_lock_enabled, bool search_mapped_to_caps_lock) { 55 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 56 const int text_string_id = caps_lock_enabled ? 57 IDS_ASH_STATUS_TRAY_CAPS_LOCK_ENABLED : 58 IDS_ASH_STATUS_TRAY_CAPS_LOCK_DISABLED; 59 text_label_->SetText(bundle.GetLocalizedString(text_string_id)); 60 61 int shortcut_string_id = 0; 62 if (caps_lock_enabled) { 63 shortcut_string_id = search_mapped_to_caps_lock ? 64 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_SEARCH_OR_SHIFT : 65 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_ALT_SEARCH_OR_SHIFT; 66 } else { 67 shortcut_string_id = search_mapped_to_caps_lock ? 68 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_SEARCH : 69 IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_ALT_SEARCH; 70 } 71 shortcut_label_->SetText(bundle.GetLocalizedString(shortcut_string_id)); 72 73 Layout(); 74 } 75 76 private: 77 // Overridden from views::View: 78 virtual void Layout() OVERRIDE { 79 views::View::Layout(); 80 81 // Align the shortcut text with the right end 82 const int old_x = shortcut_label_->x(); 83 const int new_x = 84 width() - shortcut_label_->width() - kTrayPopupPaddingHorizontal; 85 shortcut_label_->SetX(new_x); 86 const gfx::Size text_size = text_label_->size(); 87 text_label_->SetSize(gfx::Size(text_size.width() + new_x - old_x, 88 text_size.height())); 89 } 90 91 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE { 92 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; 93 state->name = text_label_->text(); 94 } 95 96 // Overridden from ActionableView: 97 virtual bool PerformAction(const ui::Event& event) OVERRIDE { 98 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 99 Shell::GetInstance()->caps_lock_delegate()->IsCapsLockEnabled() ? 100 ash::UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK : 101 ash::UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK); 102 Shell::GetInstance()->caps_lock_delegate()->ToggleCapsLock(); 103 return true; 104 } 105 106 views::Label* text_label_; 107 views::Label* shortcut_label_; 108 109 DISALLOW_COPY_AND_ASSIGN(CapsLockDefaultView); 110 }; 111 112 TrayCapsLock::TrayCapsLock(SystemTray* system_tray) 113 : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_CAPS_LOCK), 114 default_(NULL), 115 detailed_(NULL), 116 search_mapped_to_caps_lock_(false), 117 caps_lock_enabled_( 118 Shell::GetInstance()->caps_lock_delegate()->IsCapsLockEnabled()), 119 message_shown_(false) { 120 Shell::GetInstance()->system_tray_notifier()->AddCapsLockObserver(this); 121 } 122 123 TrayCapsLock::~TrayCapsLock() { 124 Shell::GetInstance()->system_tray_notifier()->RemoveCapsLockObserver(this); 125 } 126 127 bool TrayCapsLock::GetInitialVisibility() { 128 return Shell::GetInstance()->caps_lock_delegate()->IsCapsLockEnabled(); 129 } 130 131 views::View* TrayCapsLock::CreateDefaultView(user::LoginStatus status) { 132 if (!caps_lock_enabled_) 133 return NULL; 134 DCHECK(default_ == NULL); 135 default_ = new CapsLockDefaultView; 136 default_->Update(caps_lock_enabled_, search_mapped_to_caps_lock_); 137 return default_; 138 } 139 140 views::View* TrayCapsLock::CreateDetailedView(user::LoginStatus status) { 141 DCHECK(detailed_ == NULL); 142 detailed_ = new views::View; 143 144 detailed_->SetLayoutManager(new 145 views::BoxLayout(views::BoxLayout::kHorizontal, 146 kTrayPopupPaddingHorizontal, 10, kTrayPopupPaddingBetweenItems)); 147 148 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 149 views::ImageView* image = new views::ImageView; 150 image->SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK). 151 ToImageSkia()); 152 153 detailed_->AddChildView(image); 154 155 const int string_id = search_mapped_to_caps_lock_ ? 156 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH : 157 IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH; 158 views::Label* label = new views::Label(bundle.GetLocalizedString(string_id)); 159 label->SetMultiLine(true); 160 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 161 detailed_->AddChildView(label); 162 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 163 ash::UMA_STATUS_AREA_CAPS_LOCK_DETAILED); 164 165 return detailed_; 166 } 167 168 void TrayCapsLock::DestroyDefaultView() { 169 default_ = NULL; 170 } 171 172 void TrayCapsLock::DestroyDetailedView() { 173 detailed_ = NULL; 174 } 175 176 void TrayCapsLock::OnCapsLockChanged(bool enabled, 177 bool search_mapped_to_caps_lock) { 178 if (tray_view()) 179 tray_view()->SetVisible(enabled); 180 181 caps_lock_enabled_ = enabled; 182 search_mapped_to_caps_lock_ = search_mapped_to_caps_lock; 183 184 if (default_) { 185 default_->Update(enabled, search_mapped_to_caps_lock); 186 } else { 187 if (enabled) { 188 if (!message_shown_) { 189 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 190 ash::UMA_STATUS_AREA_CAPS_LOCK_POPUP); 191 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); 192 message_shown_ = true; 193 } 194 } else if (detailed_) { 195 detailed_->GetWidget()->Close(); 196 } 197 } 198 } 199 200 } // namespace internal 201 } // namespace ash 202