普通文本  |  223行  |  7.29 KB

// 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