diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-01 20:33:33 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-01 20:33:33 +0000 |
commit | a16ffcfb2e25a0467cebf342850c40ac0cfa7b65 (patch) | |
tree | 7433fb2d2bd902a143e272fa9c5dca85ec01e4a5 | |
parent | 4356c7ed525ae5845534a269f9cdda9203898995 (diff) | |
download | chromium_src-a16ffcfb2e25a0467cebf342850c40ac0cfa7b65.zip chromium_src-a16ffcfb2e25a0467cebf342850c40ac0cfa7b65.tar.gz chromium_src-a16ffcfb2e25a0467cebf342850c40ac0cfa7b65.tar.bz2 |
First cut at badge implementation. Right now it just uses static
data. A subsequent change will hook it up to the extension APIs.
See http://dl.getdropbox.com/u/124107/badges.png for a picture
of what this looks like.
BUG=23268
Review URL: http://codereview.chromium.org/259004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27761 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | app/resources/app_resources.grd | 5 | ||||
-rwxr-xr-x | app/resources/browser_action_badge_center.png | bin | 0 -> 2827 bytes | |||
-rwxr-xr-x | app/resources/browser_action_badge_left.png | bin | 0 -> 2873 bytes | |||
-rwxr-xr-x | app/resources/browser_action_badge_right.png | bin | 0 -> 2873 bytes | |||
-rw-r--r-- | chrome/app/theme/theme_resources.grd | 2 | ||||
-rw-r--r-- | chrome/browser/views/browser_actions_container.cc | 116 | ||||
-rw-r--r-- | chrome/browser/views/browser_actions_container.h | 8 | ||||
-rw-r--r-- | chrome/browser/views/toolbar_view.cc | 2 |
8 files changed, 129 insertions, 4 deletions
diff --git a/app/resources/app_resources.grd b/app/resources/app_resources.grd index 9bf6b54..7f62b8e 100644 --- a/app/resources/app_resources.grd +++ b/app/resources/app_resources.grd @@ -111,6 +111,11 @@ <include name="IDR_MENU_DROPARROW" file="menu_droparrow.png" type="BINDATA" /> <include name="IDR_MENU_CHECK" file="menu_check.png" type="BINDATA" /> <include name="IDR_MENU_ARROW" file="menu_arrow.png" type="BINDATA" /> + + <!-- Extension browser action badge --> + <include name="IDR_BROWSER_ACTION_BADGE_LEFT" file="browser_action_badge_left.png" type="BINDATA" /> + <include name="IDR_BROWSER_ACTION_BADGE_RIGHT" file="browser_action_badge_right.png" type="BINDATA" /> + <include name="IDR_BROWSER_ACTION_BADGE_CENTER" file="browser_action_badge_center.png" type="BINDATA" /> <include name="IDR_GLEN" file="linux_close_glen.png" type="BINDATA" /> </includes> diff --git a/app/resources/browser_action_badge_center.png b/app/resources/browser_action_badge_center.png Binary files differnew file mode 100755 index 0000000..289d5ef --- /dev/null +++ b/app/resources/browser_action_badge_center.png diff --git a/app/resources/browser_action_badge_left.png b/app/resources/browser_action_badge_left.png Binary files differnew file mode 100755 index 0000000..bb7581d --- /dev/null +++ b/app/resources/browser_action_badge_left.png diff --git a/app/resources/browser_action_badge_right.png b/app/resources/browser_action_badge_right.png Binary files differnew file mode 100755 index 0000000..b5fd5e3 --- /dev/null +++ b/app/resources/browser_action_badge_right.png diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 65f8cbc..b985c35 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -315,7 +315,7 @@ <include name="IDR_RESTORE_BUTTON_MASK" file="restore_button_mask.png" type="BINDATA" /> <include name="IDR_MINIMIZE_BUTTON_MASK" file="minimize_button_mask.png" type="BINDATA" /> <include name="IDR_MAXIMIZE_BUTTON_MASK" file="maximize_button_mask.png" type="BINDATA" /> - + <if expr="pp_ifdef('_google_chrome')"> <include name="IDR_ABOUT_BACKGROUND" file="google_chrome/about_background.png" type="BINDATA" /> <include name="IDR_ABOUT_BACKGROUND_RTL" file="google_chrome/about_background_rtl.png" type="BINDATA" /> diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index bae129f..f25b0fc 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -4,6 +4,8 @@ #include "chrome/browser/views/browser_actions_container.h" +#include "app/gfx/canvas.h" +#include "app/resource_bundle.h" #include "base/stl_util-inl.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extensions_service.h" @@ -14,15 +16,23 @@ #include "chrome/common/extensions/extension_action.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" +#include "grit/app_resources.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/effects/SkGradientShader.h" #include "views/controls/button/text_button.h" // The size of the icon for page actions. -static const int kIconSize = 30; +static const int kIconSize = 29; // The padding between the browser actions and the omnibox/page menu. static const int kHorizontalPadding = 4; +// This is the same value from toolbar.cc. We position the browser actions +// container flush with the edges of the toolbar as a special case so that we +// can draw the badge outside the visual bounds of the contianer. +static const int kControlVertOffset = 6; + //////////////////////////////////////////////////////////////////////////////// // BrowserActionImageView @@ -54,6 +64,9 @@ class BrowserActionImageView : public views::TextButton, // Called to update the display to match the browser action's state. void OnStateUpdated(); + // Override painting to implement the badge. + virtual void Paint(gfx::Canvas* canvas); + // The browser action this view represents. The ExtensionAction is not owned // by this class. ExtensionAction* browser_action_; @@ -220,7 +233,8 @@ void BrowserActionsContainer::Layout() { for (size_t i = 0; i < browser_action_views_.size(); ++i) { views::TextButton* view = browser_action_views_[i]; int x = kHorizontalPadding + i * kIconSize; - view->SetBounds(x, (height() - kIconSize) / 2, kIconSize, kIconSize); + view->SetBounds(x, kControlVertOffset, kIconSize, + height() - (2 * kControlVertOffset)); } } @@ -235,3 +249,101 @@ void BrowserActionsContainer::Observe(NotificationType type, NOTREACHED() << L"Received unexpected notification"; } } + +void BrowserActionsContainer::PaintChildren(gfx::Canvas* canvas) { + View::PaintChildren(canvas); + + // TODO(aa): Hook this up to the API to feed the badge color and text + // dynamically. + std::string text; + for (size_t i = 0; i < browser_action_views_.size(); ++i) { + if (i > 0) { + text += IntToString(i); + PaintBadge(canvas, browser_action_views_[i], + SkColorSetARGB(255, 218, 0, 24), text); + } + } +} + +void BrowserActionsContainer::PaintBadge(gfx::Canvas* canvas, + views::TextButton* view, + const SkColor& badge_color, + const std::string& text) { + const int kTextSize = 8; + const int kBottomMargin = 6; + const int kPadding = 2; + const int kBadgeHeight = 11; + const int kMaxTextWidth = 23; + const int kCenterAlignThreshold = 20; // at than width, we center align + + canvas->save(); + + SkTypeface* typeface = SkTypeface::CreateFromName("Arial", SkTypeface::kBold); + SkPaint text_paint; + text_paint.setAntiAlias(true); + text_paint.setColor(SkColorSetARGB(255, 255, 255, 255)); + text_paint.setFakeBoldText(true); + text_paint.setTextAlign(SkPaint::kLeft_Align); + text_paint.setTextSize(SkIntToScalar(kTextSize)); + text_paint.setTypeface(typeface); + + // Calculate text width. We clamp it to a max size. + SkScalar text_width = text_paint.measureText(text.c_str(), text.size()); + text_width = SkIntToScalar( + std::min(kMaxTextWidth, SkScalarFloor(text_width))); + + // Cacluate badge size. It is clamped to a min width just because it looks + // silly if it is too skinny. + int badge_width = SkScalarFloor(text_width) + kPadding * 2; + badge_width = std::max(kBadgeHeight, badge_width); + + // Paint the badge background color in the right location. It is usually + // right-aligned, but it can also be center-aligned if it is large. + SkRect rect; + rect.fBottom = SkIntToScalar(height() - kBottomMargin); + rect.fTop = rect.fBottom - SkIntToScalar(kBadgeHeight); + if (badge_width >= kCenterAlignThreshold) { + rect.fLeft = SkIntToScalar(view->bounds().x() + + (view->bounds().width() - badge_width) / 2); + rect.fRight = rect.fLeft + SkIntToScalar(badge_width); + } else { + rect.fRight = SkIntToScalar(view->bounds().right()); + rect.fLeft = rect.fRight - badge_width; + } + + SkPaint rect_paint; + rect_paint.setStyle(SkPaint::kFill_Style); + rect_paint.setAntiAlias(true); + rect_paint.setColor(badge_color); + canvas->drawRoundRect(rect, SkIntToScalar(2), SkIntToScalar(2), rect_paint); + + // Overlay the gradient. It is stretchy, so we do this in three parts. + ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); + SkBitmap* gradient_left = resource_bundle.GetBitmapNamed( + IDR_BROWSER_ACTION_BADGE_LEFT); + SkBitmap* gradient_right = resource_bundle.GetBitmapNamed( + IDR_BROWSER_ACTION_BADGE_RIGHT); + SkBitmap* gradient_center = resource_bundle.GetBitmapNamed( + IDR_BROWSER_ACTION_BADGE_CENTER); + + canvas->drawBitmap(*gradient_left, rect.fLeft, rect.fTop); + canvas->TileImageInt(*gradient_center, + SkScalarFloor(rect.fLeft) + gradient_left->width(), + SkScalarFloor(rect.fTop), + SkScalarFloor(rect.width()) - gradient_left->width() - + gradient_right->width(), + SkScalarFloor(rect.height())); + canvas->drawBitmap(*gradient_right, + rect.fRight - SkIntToScalar(gradient_right->width()), rect.fTop); + + // Finally, draw the text centered within the badge. We set a clip in case the + // text was too large. + rect.fLeft += kPadding; + rect.fRight -= kPadding; + canvas->clipRect(rect); + canvas->drawText(text.c_str(), text.size(), + rect.fLeft + (rect.width() - text_width) / 2, + rect.fTop + kTextSize + 1, + text_paint); + canvas->restore(); +} diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h index fd83437..3f1e93f6 100644 --- a/chrome/browser/views/browser_actions_container.h +++ b/chrome/browser/views/browser_actions_container.h @@ -55,6 +55,14 @@ class BrowserActionsContainer : public views::View, const NotificationDetails& details); private: + // We override PaintChildren so that we can paint the badges on top of them. + virtual void PaintChildren(gfx::Canvas* canvas); + + // Paints an individual badge. + virtual void PaintBadge(gfx::Canvas* canvas, views::TextButton* button, + const SkColor& badge_color, + const std::string& text); + // The vector of browser actions (icons/image buttons for each action). std::vector<views::TextButton*> browser_action_views_; diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index aeb13c3..dbc6fda 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -539,7 +539,7 @@ void ToolbarView::Layout() { } browser_actions_->SetBounds( - next_menu_x, child_y, browser_actions_width, child_height); + next_menu_x, 0, browser_actions_width, height()); next_menu_x += browser_actions_width; page_menu_->SetBounds(next_menu_x, child_y, page_menu_width, child_height); |