// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ash/system/chromeos/tray_caps_lock.h" #include "ash/metrics/user_metrics_recorder.h" #include "ash/shell.h" #include "ash/system/tray/actionable_view.h" #include "ash/system/tray/fixed_sized_image_view.h" #include "ash/system/tray/system_tray_delegate.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/tray/tray_constants.h" #include "base/sys_info.h" #include "chromeos/ime/ime_keyboard.h" #include "chromeos/ime/input_method_manager.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/accessibility/ax_view_state.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/image/image.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/widget.h" namespace ash { namespace { bool CapsLockIsEnabled() { chromeos::input_method::InputMethodManager* ime = chromeos::input_method::InputMethodManager::Get(); return (ime && ime->GetImeKeyboard()) ? ime->GetImeKeyboard()->CapsLockIsEnabled() : false; } } class CapsLockDefaultView : public ActionableView { public: CapsLockDefaultView() : text_label_(new views::Label), shortcut_label_(new views::Label) { SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingBetweenItems)); ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); FixedSizedImageView* image = new FixedSizedImageView(0, kTrayPopupItemHeight); image->SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK). ToImageSkia()); AddChildView(image); text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); AddChildView(text_label_); shortcut_label_->SetEnabled(false); AddChildView(shortcut_label_); } virtual ~CapsLockDefaultView() {} // Updates the label text and the shortcut text. void Update(bool caps_lock_enabled) { ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); const int text_string_id = caps_lock_enabled ? IDS_ASH_STATUS_TRAY_CAPS_LOCK_ENABLED : IDS_ASH_STATUS_TRAY_CAPS_LOCK_DISABLED; text_label_->SetText(bundle.GetLocalizedString(text_string_id)); int shortcut_string_id = 0; bool search_mapped_to_caps_lock = Shell::GetInstance()-> system_tray_delegate()->IsSearchKeyMappedToCapsLock(); if (caps_lock_enabled) { shortcut_string_id = search_mapped_to_caps_lock ? IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_SEARCH_OR_SHIFT : IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_ALT_SEARCH_OR_SHIFT; } else { shortcut_string_id = search_mapped_to_caps_lock ? IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_SEARCH : IDS_ASH_STATUS_TRAY_CAPS_LOCK_SHORTCUT_ALT_SEARCH; } shortcut_label_->SetText(bundle.GetLocalizedString(shortcut_string_id)); Layout(); } private: // Overridden from views::View: virtual void Layout() OVERRIDE { views::View::Layout(); // Align the shortcut text with the right end const int old_x = shortcut_label_->x(); const int new_x = width() - shortcut_label_->width() - kTrayPopupPaddingHorizontal; shortcut_label_->SetX(new_x); const gfx::Size text_size = text_label_->size(); text_label_->SetSize(gfx::Size(text_size.width() + new_x - old_x, text_size.height())); } virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE { state->role = ui::AX_ROLE_BUTTON; state->name = text_label_->text(); } // Overridden from ActionableView: virtual bool PerformAction(const ui::Event& event) OVERRIDE { chromeos::input_method::ImeKeyboard* keyboard = chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard(); if (keyboard) { Shell::GetInstance()->metrics()->RecordUserMetricsAction( keyboard->CapsLockIsEnabled() ? ash::UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK : ash::UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK); keyboard->SetCapsLockEnabled(!keyboard->CapsLockIsEnabled()); } return true; } views::Label* text_label_; views::Label* shortcut_label_; DISALLOW_COPY_AND_ASSIGN(CapsLockDefaultView); }; TrayCapsLock::TrayCapsLock(SystemTray* system_tray) : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_CAPS_LOCK), default_(NULL), detailed_(NULL), caps_lock_enabled_(CapsLockIsEnabled()), message_shown_(false) { chromeos::input_method::InputMethodManager* ime = chromeos::input_method::InputMethodManager::Get(); if (ime && ime->GetImeKeyboard()) ime->GetImeKeyboard()->AddObserver(this); } TrayCapsLock::~TrayCapsLock() { chromeos::input_method::InputMethodManager* ime = chromeos::input_method::InputMethodManager::Get(); if (ime && ime->GetImeKeyboard()) ime->GetImeKeyboard()->RemoveObserver(this); } void TrayCapsLock::OnCapsLockChanged(bool enabled) { caps_lock_enabled_ = enabled; if (tray_view()) tray_view()->SetVisible(caps_lock_enabled_); if (default_) { default_->Update(caps_lock_enabled_); } else { if (caps_lock_enabled_) { if (!message_shown_) { Shell::GetInstance()->metrics()->RecordUserMetricsAction( ash::UMA_STATUS_AREA_CAPS_LOCK_POPUP); PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); message_shown_ = true; } } else if (detailed_) { detailed_->GetWidget()->Close(); } } } bool TrayCapsLock::GetInitialVisibility() { return CapsLockIsEnabled(); } views::View* TrayCapsLock::CreateDefaultView(user::LoginStatus status) { if (!caps_lock_enabled_) return NULL; DCHECK(default_ == NULL); default_ = new CapsLockDefaultView; default_->Update(caps_lock_enabled_); return default_; } views::View* TrayCapsLock::CreateDetailedView(user::LoginStatus status) { DCHECK(detailed_ == NULL); detailed_ = new views::View; detailed_->SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kTrayPopupPaddingHorizontal, 10, kTrayPopupPaddingBetweenItems)); ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); views::ImageView* image = new views::ImageView; image->SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAPS_LOCK_DARK). ToImageSkia()); detailed_->AddChildView(image); const int string_id = Shell::GetInstance()->system_tray_delegate()-> IsSearchKeyMappedToCapsLock() ? IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH : IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH; views::Label* label = new views::Label(bundle.GetLocalizedString(string_id)); label->SetMultiLine(true); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); detailed_->AddChildView(label); Shell::GetInstance()->metrics()->RecordUserMetricsAction( ash::UMA_STATUS_AREA_CAPS_LOCK_DETAILED); return detailed_; } void TrayCapsLock::DestroyDefaultView() { default_ = NULL; } void TrayCapsLock::DestroyDetailedView() { detailed_ = NULL; } } // namespace ash