Home | History | Annotate | Download | only in system
      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