diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-07 22:36:24 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-07 22:36:24 +0000 |
commit | deb87c8535c2a5bd04152b6f2d2540c5c00bb9f3 (patch) | |
tree | 57245451d98b2dc2d22b9457b6bceec175fb8c6f | |
parent | 694c0ca50612fc4e2d44ceb210beb9c5a9ad26e1 (diff) | |
download | chromium_src-deb87c8535c2a5bd04152b6f2d2540c5c00bb9f3.zip chromium_src-deb87c8535c2a5bd04152b6f2d2540c5c00bb9f3.tar.gz chromium_src-deb87c8535c2a5bd04152b6f2d2540c5c00bb9f3.tar.bz2 |
Pull a BrowserActionView out of BrowserActionContainer. Also
rename the button to BrowserActionButton.
This should make adding animation to the badge easier.
Review URL: http://codereview.chromium.org/268002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28330 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/views/browser_actions_container.cc | 288 | ||||
-rw-r--r-- | chrome/browser/views/browser_actions_container.h | 17 | ||||
-rw-r--r-- | chrome/common/extensions/extension_action.h | 12 |
3 files changed, 166 insertions, 151 deletions
diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 6d77e32..9fdd2fd 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -36,21 +36,22 @@ static const int kHorizontalPadding = 4; static const int kControlVertOffset = 6; //////////////////////////////////////////////////////////////////////////////// -// BrowserActionImageView +// BrowserActionButton -// The BrowserActionImageView is a specialization of the TextButton class. +// The BrowserActionButton is a specialization of the MenuButton class. // It acts on a ExtensionAction, in this case a BrowserAction and handles // loading the image for the button asynchronously on the file thread to -class BrowserActionImageView : public views::MenuButton, - public views::ButtonListener, - public ImageLoadingTracker::Observer, - public NotificationObserver { +class BrowserActionButton : public views::MenuButton, + public views::ButtonListener, + public ImageLoadingTracker::Observer, + public NotificationObserver { public: - BrowserActionImageView(ExtensionAction* browser_action, - Extension* extension, - BrowserActionsContainer* panel); - ~BrowserActionImageView(); + BrowserActionButton(ExtensionAction* browser_action, + Extension* extension, + BrowserActionsContainer* panel); + ~BrowserActionButton(); + const ExtensionAction& browser_action() const { return *browser_action_; } ExtensionActionState* browser_action_state() { return browser_action_state_; } // Overridden from views::ButtonListener: @@ -82,8 +83,6 @@ class BrowserActionImageView : public views::MenuButton, virtual void PopupDidShow(); virtual void PopupDidHide(); - const ExtensionAction& browser_action() const { return *browser_action_; } - private: // Called to update the display to match the browser action's state. void OnStateUpdated(); @@ -108,10 +107,10 @@ class BrowserActionImageView : public views::MenuButton, NotificationRegistrar registrar_; - DISALLOW_COPY_AND_ASSIGN(BrowserActionImageView); + DISALLOW_COPY_AND_ASSIGN(BrowserActionButton); }; -BrowserActionImageView::BrowserActionImageView( +BrowserActionButton::BrowserActionButton( ExtensionAction* browser_action, Extension* extension, BrowserActionsContainer* panel) : MenuButton(this, L"", NULL, false), @@ -138,19 +137,19 @@ BrowserActionImageView::BrowserActionImageView( Source<ExtensionAction>(browser_action_)); } -BrowserActionImageView::~BrowserActionImageView() { +BrowserActionButton::~BrowserActionButton() { if (tracker_) { tracker_->StopTrackingImageLoad(); tracker_ = NULL; // The tracker object will be deleted when we return. } } -void BrowserActionImageView::ButtonPressed( +void BrowserActionButton::ButtonPressed( views::Button* sender, const views::Event& event) { panel_->OnBrowserActionExecuted(this); } -void BrowserActionImageView::OnImageLoaded(SkBitmap* image, size_t index) { +void BrowserActionButton::OnImageLoaded(SkBitmap* image, size_t index) { DCHECK(index < browser_action_icons_.size()); browser_action_icons_[index] = *image; if (index == browser_action_icons_.size() - 1) { @@ -159,19 +158,19 @@ void BrowserActionImageView::OnImageLoaded(SkBitmap* image, size_t index) { } } -void BrowserActionImageView::OnStateUpdated() { +void BrowserActionButton::OnStateUpdated() { SkBitmap* image = browser_action_state_->icon(); if (!image) image = &browser_action_icons_[browser_action_state_->icon_index()]; SetIcon(*image); SetTooltipText(ASCIIToWide(browser_action_state_->title())); panel_->OnBrowserActionVisibilityChanged(); - SchedulePaint(); + GetParent()->SchedulePaint(); } -void BrowserActionImageView::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { +void BrowserActionButton::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED) { OnStateUpdated(); } else { @@ -179,11 +178,11 @@ void BrowserActionImageView::Observe(NotificationType type, } } -bool BrowserActionImageView::IsPopup() { +bool BrowserActionButton::IsPopup() { return browser_action_->is_popup(); } -bool BrowserActionImageView::Activate() { +bool BrowserActionButton::Activate() { if (IsPopup()) { panel_->OnBrowserActionExecuted(this); @@ -199,14 +198,14 @@ bool BrowserActionImageView::Activate() { return true; } -bool BrowserActionImageView::OnMousePressed(const views::MouseEvent& e) { +bool BrowserActionButton::OnMousePressed(const views::MouseEvent& e) { if (IsPopup()) return MenuButton::OnMousePressed(e); return TextButton::OnMousePressed(e); } -void BrowserActionImageView::OnMouseReleased(const views::MouseEvent& e, - bool canceled) { +void BrowserActionButton::OnMouseReleased(const views::MouseEvent& e, + bool canceled) { if (IsPopup()) { // TODO(erikkay) this never actually gets called (probably because of the // loss of focus). @@ -216,29 +215,149 @@ void BrowserActionImageView::OnMouseReleased(const views::MouseEvent& e, } } -bool BrowserActionImageView::OnKeyReleased(const views::KeyEvent& e) { +bool BrowserActionButton::OnKeyReleased(const views::KeyEvent& e) { if (IsPopup()) return MenuButton::OnKeyReleased(e); return TextButton::OnKeyReleased(e); } -void BrowserActionImageView::OnMouseExited(const views::MouseEvent& e) { +void BrowserActionButton::OnMouseExited(const views::MouseEvent& e) { if (IsPopup()) MenuButton::OnMouseExited(e); else TextButton::OnMouseExited(e); } -void BrowserActionImageView::PopupDidShow() { +void BrowserActionButton::PopupDidShow() { SetState(views::CustomButton::BS_PUSHED); menu_visible_ = true; } -void BrowserActionImageView::PopupDidHide() { +void BrowserActionButton::PopupDidHide() { SetState(views::CustomButton::BS_NORMAL); menu_visible_ = false; } + +//////////////////////////////////////////////////////////////////////////////// +// BrowserActionView +// A single section in the browser action container. This contains the actual +// BrowserActionButton, as well as the logic to paint the badge. + +class BrowserActionView : public views::View { + public: + BrowserActionView(ExtensionAction* browser_action, Extension* extension, + BrowserActionsContainer* panel); + + private: + virtual void Layout(); + + // Override PaintChildren so that we can paint the badge on top of children. + virtual void PaintChildren(gfx::Canvas* canvas); + + // The button this view contains. + BrowserActionButton* button_; +}; + +BrowserActionView::BrowserActionView(ExtensionAction* browser_action, + Extension* extension, + BrowserActionsContainer* panel) { + button_ = new BrowserActionButton(browser_action, extension, panel); + AddChildView(button_); +} + +void BrowserActionView::Layout() { + button_->SetBounds(0, kControlVertOffset, width(), + height() - 2 * kControlVertOffset); +} + +void BrowserActionView::PaintChildren(gfx::Canvas* canvas) { + View::PaintChildren(canvas); + + const std::string& text = button_->browser_action_state()->badge_text(); + if (text.empty()) + return; + + const int kTextSize = 8; + const int kBottomMargin = 5; + 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((width() - badge_width) / 2); + rect.fRight = rect.fLeft + SkIntToScalar(badge_width); + } else { + rect.fRight = SkIntToScalar(width()); + rect.fLeft = rect.fRight - badge_width; + } + + SkPaint rect_paint; + rect_paint.setStyle(SkPaint::kFill_Style); + rect_paint.setAntiAlias(true); + rect_paint.setColor( + button_->browser_action_state()->badge_background_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(); +} + + //////////////////////////////////////////////////////////////////////////////// // BrowserActionsContainer @@ -282,8 +401,8 @@ void BrowserActionsContainer::RefreshBrowserActionViews() { // Only show browser actions that have an icon. if (browser_actions[i]->icon_paths().size() > 0) { - BrowserActionImageView* view = - new BrowserActionImageView(browser_actions[i], extension, this); + BrowserActionView* view = + new BrowserActionView(browser_actions[i], extension, this); browser_action_views_.push_back(view); AddChildView(view); } @@ -316,7 +435,7 @@ void BrowserActionsContainer::HidePopup() { } void BrowserActionsContainer::OnBrowserActionExecuted( - BrowserActionImageView* button) { + BrowserActionButton* button) { const ExtensionAction& browser_action = button->browser_action(); // Popups just display. No notification to the extension. @@ -363,10 +482,9 @@ gfx::Size BrowserActionsContainer::GetPreferredSize() { void BrowserActionsContainer::Layout() { for (size_t i = 0; i < browser_action_views_.size(); ++i) { - BrowserActionImageView* view = browser_action_views_[i]; + BrowserActionView* view = browser_action_views_[i]; int x = kHorizontalPadding + i * kIconSize; - view->SetBounds(x, kControlVertOffset, kIconSize, - height() - (2 * kControlVertOffset)); + view->SetBounds(x, 0, kIconSize, height()); } } @@ -404,99 +522,3 @@ void BrowserActionsContainer::BubbleLostFocus(BrowserBubble* bubble) { MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(&BrowserActionsContainer::HidePopup)); } - -void BrowserActionsContainer::PaintChildren(gfx::Canvas* canvas) { - View::PaintChildren(canvas); - - for (size_t i = 0; i < browser_action_views_.size(); ++i) { - BrowserActionImageView* view = browser_action_views_[i]; - const std::string& text = view->browser_action_state()->badge_text(); - SkColor* color = view->browser_action_state()->badge_background_color(); - - if (!text.empty()) - PaintBadge(canvas, browser_action_views_[i], *color, text); - } -} - -void BrowserActionsContainer::PaintBadge(gfx::Canvas* canvas, - BrowserActionImageView* 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 dc77d38..76e8101 100644 --- a/chrome/browser/views/browser_actions_container.h +++ b/chrome/browser/views/browser_actions_container.h @@ -13,7 +13,8 @@ #include "chrome/common/notification_registrar.h" #include "views/view.h" -class BrowserActionImageView; +class BrowserActionButton; +class BrowserActionView; class ExtensionAction; class ExtensionPopup; class Profile; @@ -45,7 +46,7 @@ class BrowserActionsContainer : public views::View, void OnBrowserActionVisibilityChanged(); // Called when the user clicks on the browser action icon. - void OnBrowserActionExecuted(BrowserActionImageView* button); + void OnBrowserActionExecuted(BrowserActionButton* button); // Overridden from views::View: virtual gfx::Size GetPreferredSize(); @@ -67,16 +68,8 @@ class BrowserActionsContainer : public views::View, // Hide the current popup. void HidePopup(); - // 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, BrowserActionImageView* button, - const SkColor& badge_color, - const std::string& text); - // The vector of browser actions (icons/image buttons for each action). - std::vector<BrowserActionImageView*> browser_action_views_; + std::vector<BrowserActionView*> browser_action_views_; NotificationRegistrar registrar_; @@ -90,7 +83,7 @@ class BrowserActionsContainer : public views::View, // The button that triggered the current popup (just a reference to a button // from browser_action_views_). - BrowserActionImageView* popup_button_; + BrowserActionButton* popup_button_; ScopedRunnableMethodFactory<BrowserActionsContainer> task_factory_; diff --git a/chrome/common/extensions/extension_action.h b/chrome/common/extensions/extension_action.h index 31f256f..74c22d9 100644 --- a/chrome/common/extensions/extension_action.h +++ b/chrome/common/extensions/extension_action.h @@ -91,7 +91,7 @@ class ExtensionActionState { public: ExtensionActionState(std::string title, int icon_index) : title_(title), icon_index_(icon_index), - badge_background_color_(new SkColor(SkColorSetARGB(255, 218, 0, 24))) { + badge_background_color_(SkColorSetARGB(255, 218, 0, 24)) { } const std::string& title() const { return title_; } @@ -102,11 +102,11 @@ class ExtensionActionState { badge_text_ = badge_text; } - SkColor* badge_background_color() const { - return badge_background_color_.get(); + SkColor badge_background_color() const { + return badge_background_color_; } - void set_badge_background_color(const SkColor& badge_background_color) { - badge_background_color_.reset(new SkColor(badge_background_color)); + void set_badge_background_color(SkColor badge_background_color) { + badge_background_color_ = badge_background_color; } int icon_index() const { return icon_index_; } @@ -129,7 +129,7 @@ class ExtensionActionState { std::string badge_text_; // The background color for the badge. - scoped_ptr<SkColor> badge_background_color_; + SkColor badge_background_color_; DISALLOW_COPY_AND_ASSIGN(ExtensionActionState); }; |