summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/status/caps_lock_menu_button.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/chromeos/status/caps_lock_menu_button.cc')
-rw-r--r--chrome/browser/chromeos/status/caps_lock_menu_button.cc168
1 files changed, 159 insertions, 9 deletions
diff --git a/chrome/browser/chromeos/status/caps_lock_menu_button.cc b/chrome/browser/chromeos/status/caps_lock_menu_button.cc
index 9b32dbc..a4a8c6c 100644
--- a/chrome/browser/chromeos/status/caps_lock_menu_button.cc
+++ b/chrome/browser/chromeos/status/caps_lock_menu_button.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/input_method/xkeyboard.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
@@ -15,9 +16,26 @@
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/font.h"
+#include "views/controls/menu/menu_item_view.h"
+#include "views/controls/menu/menu_runner.h"
+#include "views/controls/menu/submenu_view.h"
+#include "views/widget/widget.h"
namespace {
+// Spacing between lines of text.
+const int kSpacing = 3;
+// Width and height of the image.
+const int kImageWidth = 22, kImageHeight = 21;
+// Constants for status displayed when user clicks button.
+// Padding around status.
+const int kPadLeftX = 10, kPadRightX = 10, kPadY = 5;
+// Padding between image and text.
+const int kTextPadX = 10;
+
// Returns PrefService object associated with |host|.
PrefService* GetPrefService(chromeos::StatusAreaHost* host) {
if (host->GetProfile())
@@ -29,19 +47,108 @@ PrefService* GetPrefService(chromeos::StatusAreaHost* host) {
namespace chromeos {
+class CapsLockMenuButton::StatusView : public View {
+ public:
+ explicit StatusView(CapsLockMenuButton* menu_button)
+ : menu_button_(menu_button),
+ font_(ResourceBundle::GetSharedInstance().GetFont(
+ ResourceBundle::BaseFont)) {
+ }
+
+ virtual ~StatusView() {
+ }
+
+ gfx::Size GetPreferredSize() {
+ // TODO(yusukes): For better string localization, we should use either
+ // IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SHIFT_KEYS or
+ // IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SEARCH here instead of just
+ // concatenating IDS_STATUSBAR_CAPS_LOCK_ENABLED and GetText(). Find a good
+ // way to break the long text into lines and stop concatenating strings.
+ const string16 first_line_text = l10n_util::GetStringUTF16(
+ IDS_STATUSBAR_CAPS_LOCK_ENABLED);
+ const string16 second_line_text = menu_button_->GetText();
+
+ int first_line_width = 0;
+ int second_line_width = 0;
+ int height = 0;
+ gfx::CanvasSkia::SizeStringInt(
+ first_line_text, font_, &first_line_width, &height, 0);
+ gfx::CanvasSkia::SizeStringInt(
+ second_line_text, font_, &second_line_width, &height, 0);
+
+ const gfx::Size size = gfx::Size(
+ kPadLeftX + kImageWidth + kTextPadX + kPadRightX +
+ std::max(first_line_width, second_line_width),
+ (2 * kPadY) +
+ std::max(kImageHeight, kSpacing + (2 * font_.GetHeight())));
+ return size;
+ }
+
+ void Update() {
+ PreferredSizeChanged();
+ // Force a paint even if the size didn't change.
+ SchedulePaint();
+ }
+
+ protected:
+ void OnPaint(gfx::Canvas* canvas) {
+ SkBitmap* image =
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_CAPS_LOCK_ICON);
+ const int image_x = kPadLeftX;
+ const int image_y = (height() - image->height()) / 2;
+ canvas->DrawBitmapInt(*image, image_x, image_y);
+
+ const string16 first_line_text = l10n_util::GetStringUTF16(
+ IDS_STATUSBAR_CAPS_LOCK_ENABLED);
+ const string16 second_line_text = menu_button_->GetText();
+
+ const int text_height = font_.GetHeight();
+ const int text_x = image_x + kImageWidth + kTextPadX;
+ const int first_line_text_y =
+ (height() - (kSpacing + (2 * text_height))) / 2;
+ const int second_line_text_y = first_line_text_y + text_height + kSpacing;
+ canvas->DrawStringInt(first_line_text, font_, SK_ColorBLACK,
+ text_x, first_line_text_y,
+ width() - text_x, text_height,
+ gfx::Canvas::TEXT_ALIGN_LEFT);
+ canvas->DrawStringInt(second_line_text, font_, SK_ColorBLACK,
+ text_x, second_line_text_y,
+ width() - text_x, text_height,
+ gfx::Canvas::TEXT_ALIGN_LEFT);
+ }
+
+ bool OnMousePressed(const views::MouseEvent& event) {
+ return true;
+ }
+
+ void OnMouseReleased(const views::MouseEvent& event) {
+ if (event.IsLeftMouseButton()) {
+ DCHECK(menu_button_->menu_runner_.get());
+ menu_button_->menu_runner_->Cancel();
+ }
+ }
+
+ private:
+ CapsLockMenuButton* menu_button_;
+ gfx::Font font_;
+
+ DISALLOW_COPY_AND_ASSIGN(StatusView);
+};
+
////////////////////////////////////////////////////////////////////////////////
// CapsLockMenuButton
CapsLockMenuButton::CapsLockMenuButton(StatusAreaHost* host)
: StatusAreaButton(host, this),
- prefs_(GetPrefService(host)) {
+ prefs_(GetPrefService(host)),
+ status_(NULL) {
if (prefs_)
remap_search_key_to_.Init(
prefs::kLanguageXkbRemapSearchKeyTo, prefs_, this);
SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
IDR_STATUSBAR_CAPS_LOCK));
- UpdateTooltip();
+ UpdateAccessibleName();
UpdateUIFromCurrentCapsLock(input_method::XKeyboard::CapsLockIsEnabled());
if (SystemKeyEventListener::GetInstance())
SystemKeyEventListener::GetInstance()->AddCapsLockObserver(this);
@@ -62,9 +169,41 @@ void CapsLockMenuButton::OnLocaleChanged() {
////////////////////////////////////////////////////////////////////////////////
// views::ViewMenuDelegate implementation:
-void CapsLockMenuButton::RunMenu(views::View* unused_source,
- const gfx::Point& pt) {
- // This button is just an indicator, and therefore does not have a menu.
+string16 CapsLockMenuButton::GetLabel(int id) const {
+ return string16();
+}
+
+bool CapsLockMenuButton::IsCommandEnabled(int id) const {
+ return false;
+}
+
+void CapsLockMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
+ static const int kDummyCommandId = 1000;
+
+ views::MenuItemView* menu = new views::MenuItemView(this);
+ // MenuRunner takes ownership of |menu|.
+ menu_runner_.reset(new views::MenuRunner(menu));
+ views::MenuItemView* submenu = menu->AppendMenuItem(
+ kDummyCommandId,
+ L"",
+ views::MenuItemView::NORMAL);
+ status_ = new CapsLockMenuButton::StatusView(this);
+ submenu->AddChildView(status_);
+ menu->CreateSubmenu()->set_resize_open_menu(true);
+ menu->SetMargins(0, 0);
+ submenu->SetMargins(0, 0);
+ menu->ChildrenChanged();
+
+ gfx::Point screen_location;
+ views::View::ConvertPointToScreen(source, &screen_location);
+ gfx::Rect bounds(screen_location, source->size());
+ if (menu_runner_->RunMenuAt(
+ source->GetWidget()->GetTopLevelWidget(), this, bounds,
+ views::MenuItemView::TOPRIGHT, views::MenuRunner::HAS_MNEMONICS) ==
+ views::MenuRunner::MENU_DELETED)
+ return;
+ status_ = NULL;
+ menu_runner_.reset(NULL);
}
////////////////////////////////////////////////////////////////////////////////
@@ -81,19 +220,30 @@ void CapsLockMenuButton::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
if (type == chrome::NOTIFICATION_PREF_CHANGED)
- UpdateTooltip();
+ UpdateAccessibleName();
}
-void CapsLockMenuButton::UpdateTooltip() {
- int id = IDS_STATUSBAR_CAPS_LOCK_ENABLED;
+void CapsLockMenuButton::UpdateAccessibleName() {
+ int id = IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SHIFT_KEYS;
if (prefs_ && (remap_search_key_to_.GetValue() == input_method::kCapsLockKey))
id = IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SEARCH;
- SetTooltipText(l10n_util::GetStringUTF16(id));
SetAccessibleName(l10n_util::GetStringUTF16(id));
}
+string16 CapsLockMenuButton::GetText() const {
+ int id = IDS_STATUSBAR_PRESS_SHIFT_KEYS;
+ if (prefs_ && (remap_search_key_to_.GetValue() == input_method::kCapsLockKey))
+ id = IDS_STATUSBAR_PRESS_SEARCH;
+ return l10n_util::GetStringUTF16(id);
+}
+
void CapsLockMenuButton::UpdateUIFromCurrentCapsLock(bool enabled) {
SetVisible(enabled);
+ SchedulePaint();
+ if (enabled && status_)
+ status_->Update();
+ if (!enabled && menu_runner_.get())
+ menu_runner_->Cancel();
}
} // namespace chromeos