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