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