diff options
author | johnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-05 00:51:58 +0000 |
---|---|---|
committer | johnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-05 00:51:58 +0000 |
commit | bd76fc2bcef23c62e570bdb67d782f4811a5f92d (patch) | |
tree | 0ece71dd45e5abe72bce4ecc9f12c1055238b3a2 | |
parent | 103c215374c596425c599483053f69805720da71 (diff) | |
download | chromium_src-bd76fc2bcef23c62e570bdb67d782f4811a5f92d.zip chromium_src-bd76fc2bcef23c62e570bdb67d782f4811a5f92d.tar.gz chromium_src-bd76fc2bcef23c62e570bdb67d782f4811a5f92d.tar.bz2 |
Spruce up the notification UI to much more closely match the mocks, including a new stylesheet from Glen for text+icon notifications, and little icons for the buttons.
Part of the CL includes new features for TextButton class to control icon placement and appearance on hover.
BUG=none
TEST=notifications
Review URL: http://codereview.chromium.org/450045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33899 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-x | chrome/app/theme/balloon_close.png | bin | 0 -> 379 bytes | |||
-rwxr-xr-x | chrome/app/theme/balloon_close_hover.png | bin | 0 -> 373 bytes | |||
-rw-r--r-- | chrome/app/theme/balloon_frame.png | bin | 285 -> 301 bytes | |||
-rwxr-xr-x | chrome/app/theme/balloon_options_arrow.png | bin | 0 -> 236 bytes | |||
-rwxr-xr-x | chrome/app/theme/balloon_options_arrow_hover.png | bin | 0 -> 238 bytes | |||
-rw-r--r-- | chrome/app/theme/balloon_shelf.png | bin | 275 -> 301 bytes | |||
-rw-r--r-- | chrome/app/theme/theme_resources.grd | 6 | ||||
-rw-r--r-- | chrome/browser/notifications/balloon_collection.cc | 20 | ||||
-rw-r--r-- | chrome/browser/notifications/desktop_notification_service.cc | 6 | ||||
-rw-r--r-- | chrome/browser/resources/notification.html | 63 | ||||
-rw-r--r-- | chrome/browser/views/notifications/balloon_view.cc | 47 | ||||
-rw-r--r-- | views/controls/button/text_button.cc | 55 | ||||
-rw-r--r-- | views/controls/button/text_button.h | 23 |
13 files changed, 147 insertions, 73 deletions
diff --git a/chrome/app/theme/balloon_close.png b/chrome/app/theme/balloon_close.png Binary files differnew file mode 100755 index 0000000..cd5609e --- /dev/null +++ b/chrome/app/theme/balloon_close.png diff --git a/chrome/app/theme/balloon_close_hover.png b/chrome/app/theme/balloon_close_hover.png Binary files differnew file mode 100755 index 0000000..8d36beb --- /dev/null +++ b/chrome/app/theme/balloon_close_hover.png diff --git a/chrome/app/theme/balloon_frame.png b/chrome/app/theme/balloon_frame.png Binary files differindex f3059e4..347523b 100644 --- a/chrome/app/theme/balloon_frame.png +++ b/chrome/app/theme/balloon_frame.png diff --git a/chrome/app/theme/balloon_options_arrow.png b/chrome/app/theme/balloon_options_arrow.png Binary files differnew file mode 100755 index 0000000..e3d757c --- /dev/null +++ b/chrome/app/theme/balloon_options_arrow.png diff --git a/chrome/app/theme/balloon_options_arrow_hover.png b/chrome/app/theme/balloon_options_arrow_hover.png Binary files differnew file mode 100755 index 0000000..f4f6283 --- /dev/null +++ b/chrome/app/theme/balloon_options_arrow_hover.png diff --git a/chrome/app/theme/balloon_shelf.png b/chrome/app/theme/balloon_shelf.png Binary files differindex 66de8f1..dd1173a 100644 --- a/chrome/app/theme/balloon_shelf.png +++ b/chrome/app/theme/balloon_shelf.png diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 77781ce..74dee3f 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -308,7 +308,11 @@ <!-- Desktop notifications --> <include name="IDR_BALLOON_BORDER" file="balloon_frame.png" type="BINDATA" /> <include name="IDR_BALLOON_SHELF" file="balloon_shelf.png" type="BINDATA" /> - + <include name="IDR_BALLOON_CLOSE" file="balloon_close.png" type="BINDATA" /> + <include name="IDR_BALLOON_CLOSE_HOVER" file="balloon_close_hover.png" type="BINDATA" /> + <include name="IDR_BALLOON_OPTIONS_ARROW" file="balloon_options_arrow.png" type="BINDATA" /> + <include name="IDR_BALLOON_OPTIONS_ARROW_HOVER" file="balloon_options_arrow_hover.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/notifications/balloon_collection.cc b/chrome/browser/notifications/balloon_collection.cc index b0d2ea6..194ebdd 100644 --- a/chrome/browser/notifications/balloon_collection.cc +++ b/chrome/browser/notifications/balloon_collection.cc @@ -18,6 +18,10 @@ const double kPercentBalloonFillFactor = 0.7; // Allow at least this number of balloons on the screen. const int kMinAllowedBalloonCount = 2; +// Margin from the edge of the work area +const int kVerticalEdgeMargin = 5; +const int kHorizontalEdgeMargin = 5; + } // namespace // static @@ -127,20 +131,20 @@ gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const { int y = 0; switch (placement_) { case HORIZONTALLY_FROM_BOTTOM_LEFT: - x = work_area_.x(); - y = work_area_.bottom(); + x = work_area_.x() + kHorizontalEdgeMargin; + y = work_area_.bottom() - kVerticalEdgeMargin; break; case HORIZONTALLY_FROM_BOTTOM_RIGHT: - x = work_area_.right(); - y = work_area_.bottom(); + x = work_area_.right() - kHorizontalEdgeMargin; + y = work_area_.bottom() - kVerticalEdgeMargin; break; case VERTICALLY_FROM_TOP_RIGHT: - x = work_area_.right(); - y = work_area_.y(); + x = work_area_.right() - kHorizontalEdgeMargin; + y = work_area_.y() + kVerticalEdgeMargin; break; case VERTICALLY_FROM_BOTTOM_RIGHT: - x = work_area_.right(); - y = work_area_.bottom(); + x = work_area_.right() - kHorizontalEdgeMargin; + y = work_area_.bottom() - kVerticalEdgeMargin; break; default: NOTREACHED(); diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc index 8561440..bfe472d 100644 --- a/chrome/browser/notifications/desktop_notification_service.cc +++ b/chrome/browser/notifications/desktop_notification_service.cc @@ -61,11 +61,9 @@ static string16 CreateDataUrl(const GURL& icon_url, const string16& title, subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body)))); if (icon_url.is_valid()) { - subst.push_back(ASCIIToUTF16("block")); - subst.push_back(ASCIIToUTF16("60")); + subst.push_back(ASCIIToUTF16("margin-left:56px;")); } else { - subst.push_back(ASCIIToUTF16("none")); - subst.push_back(ASCIIToUTF16("5")); + subst.push_back(EmptyString16()); } string16 format_string = ASCIIToUTF16("data:text/html;charset=utf-8," diff --git a/chrome/browser/resources/notification.html b/chrome/browser/resources/notification.html index 5e436e7..f3d824a1 100644 --- a/chrome/browser/resources/notification.html +++ b/chrome/browser/resources/notification.html @@ -1,36 +1,39 @@ <html> <head> -<title>$2</title> -<style type="text/css"><!-- -#icon { -height:48px; -width:48px; -position:absolute; -top:2px; -left:2px; -display:$4; -} -#title { -font-weight:bold; -position:absolute; -top:3px; -left:$5px; -font-family:sans-serif; -font-size:11pt; -} -#body { -position:absolute; -left:$5px; -top:20px; -font-family:sans-serif; -font-size:9pt; -} -//--> -</style> + <title>$2</title> + <style type="text/css"> + body { + margin:4px; + } + #body { + $4 + position:relative; + } + #icon { + position:absolute; + left:-52px; + top:2px; + height:48px; + width:48px; + padding-right:4px; + display:block; + } + #title { + font-weight:bold; + font-family:helvetica, arial, sans-serif; + font-size:100%; + } + #description { + font-family:helvetica, arial, sans-serif; + font-size:84%; + } + </style> </head> <body> -<div id="icon"><img src="$1" /></div> -<div id="title">$2</div> -<div id="body">$3</div> + <div id="body"> + <div id="icon"><img src="$1" width="48" height="48" /></div> + <div id="title">$2</div> + <div id="description">$3</div> + </div> </body> </html> diff --git a/chrome/browser/views/notifications/balloon_view.cc b/chrome/browser/views/notifications/balloon_view.cc index 94bed33..b6dffd5 100644 --- a/chrome/browser/views/notifications/balloon_view.cc +++ b/chrome/browser/views/notifications/balloon_view.cc @@ -42,14 +42,14 @@ const int kTopMargin = 1; const int kBottomMargin = 1; const int kLeftMargin = 1; const int kRightMargin = 1; -const int kShelfBorderTopOverlap = 2; +const int kShelfBorderTopOverlap = 3; // Properties of the dismiss button. -const int kDismissButtonWidth = 46; +const int kDismissButtonWidth = 60; const int kDismissButtonHeight = 20; // Properties of the options menu. -const int kOptionsMenuWidth = 48; +const int kOptionsMenuWidth = 60; const int kOptionsMenuHeight = 20; // Properties of the origin label. @@ -208,6 +208,8 @@ void BalloonViewImpl::Show(Balloon* balloon) { SetBounds(balloon_->position().x(), balloon_->position().y(), balloon_->size().width(), balloon_->size().height()); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + // We have to create two windows: one for the contents and one for the // frame. Why? // * The contents is an html window which cannot be a @@ -243,10 +245,13 @@ void BalloonViewImpl::Show(Balloon* balloon) { l10n_util::GetString(IDS_NOTIFICATION_BALLOON_DISMISS_LABEL); close_button_ = new views::TextButton(close_button_listener_.get(), dismiss_text); - close_button_->SetFont( - ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::SmallFont)); - close_button_->SetEnabledColor(BrowserThemeProvider::kDefaultColorTabText); + close_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont)); + close_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_CLOSE)); + close_button_->SetHoverIcon(*rb.GetBitmapNamed(IDR_BALLOON_CLOSE_HOVER)); + close_button_->SetEnabledColor(SK_ColorWHITE); + close_button_->SetHoverColor(SK_ColorDKGRAY); close_button_->set_alignment(views::TextButton::ALIGN_CENTER); + close_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT); close_button_->SetBounds(width() - kDismissButtonWidth - kRightMargin, height() - kDismissButtonHeight @@ -259,10 +264,14 @@ void BalloonViewImpl::Show(Balloon* balloon) { const std::wstring options_text = l10n_util::GetString(IDS_NOTIFICATION_OPTIONS_MENU_LABEL); options_menu_button_ = new views::MenuButton(NULL, options_text, this, false); - options_menu_button_->SetFont( - ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::SmallFont)); - options_menu_button_->SetEnabledColor( - BrowserThemeProvider::kDefaultColorTabText); + options_menu_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont)); + options_menu_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_OPTIONS_ARROW)); + options_menu_button_->SetHoverIcon( + *rb.GetBitmapNamed(IDR_BALLOON_OPTIONS_ARROW_HOVER)); + options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER); + options_menu_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT); + options_menu_button_->SetEnabledColor(SK_ColorWHITE); + options_menu_button_->SetHoverColor(SK_ColorDKGRAY); options_menu_button_->SetBounds(width() - kDismissButtonWidth - kOptionsMenuWidth - kRightMargin, @@ -280,7 +289,7 @@ void BalloonViewImpl::Show(Balloon* balloon) { views::Label* source_label = new views::Label(source_label_text); source_label->SetFont(ResourceBundle::GetSharedInstance().GetFont( ResourceBundle::SmallFont)); - source_label->SetColor(BrowserThemeProvider::kDefaultColorTabText); + source_label->SetColor(SK_ColorWHITE); source_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); source_label->SetBounds(kLeftLabelMargin, height() - kDismissButtonHeight @@ -325,21 +334,21 @@ void BalloonViewImpl::GetContentsMask(const gfx::Rect& rect, // // xx // x - path->moveTo(SkScalar(1), SkScalar(0)); + path->moveTo(SkScalar(0.5), SkScalar(0)); // Upper right corner - path->arcTo(rect.width() - SkScalar(2), SkScalar(0), - rect.width() - SkScalar(1), SkScalar(2), + path->arcTo(rect.width() - SkScalar(1.5), SkScalar(0), + rect.width() - SkScalar(0.5), SkScalar(1.5), SkScalar(1)); // Lower right corner - path->arcTo(rect.width() - SkScalar(1), rect.height() - SkScalar(2), - rect.width() - SkScalar(2), rect.height() - SkScalar(1), + path->arcTo(rect.width() - SkScalar(0.5), rect.height() - SkScalar(1.5), + rect.width() - SkScalar(1.5), rect.height() - SkScalar(0.5), SkScalar(1)); // Lower left corner - path->arcTo(SkScalar(1), rect.height() - SkScalar(1), - 0, rect.height() - SkScalar(2), + path->arcTo(SkScalar(0.5), rect.height() - SkScalar(0.5), + 0, rect.height() - SkScalar(1.5), SkScalar(1)); // Upper left corner - path->arcTo(0, SkScalar(1), SkScalar(1), 0, SkScalar(1)); + path->arcTo(0, SkScalar(0.5), SkScalar(0.5), 0, SkScalar(1)); } gfx::Point BalloonViewImpl::GetContentsOffset() const { diff --git a/views/controls/button/text_button.cc b/views/controls/button/text_button.cc index 068b323..0df9578c 100644 --- a/views/controls/button/text_button.cc +++ b/views/controls/button/text_button.cc @@ -29,6 +29,8 @@ const SkColor TextButton::kEnabledColor = SkColorSetRGB(6, 45, 117); const SkColor TextButton::kHighlightColor = SkColorSetARGB(200, 255, 255, 255); // static const SkColor TextButton::kDisabledColor = SkColorSetRGB(161, 161, 146); +// static +const SkColor TextButton::kHoverColor = TextButton::kEnabledColor; // How long the hover fade animation should last. static const int kHoverAnimationDurationMs = 170; @@ -158,12 +160,15 @@ void TextButtonBorder::GetInsets(gfx::Insets* insets) const { TextButton::TextButton(ButtonListener* listener, const std::wstring& text) : CustomButton(listener), alignment_(ALIGN_LEFT), + icon_placement_(ICON_ON_LEFT), font_(ResourceBundle::GetSharedInstance().GetFont( ResourceBundle::BaseFont)), color_(kEnabledColor), color_enabled_(kEnabledColor), color_disabled_(kDisabledColor), color_highlight_(kHighlightColor), + color_hover_(kHoverColor), + has_hover_icon_(false), max_width_(0) { SetText(text); set_border(new TextButtonBorder); @@ -186,6 +191,11 @@ void TextButton::SetIcon(const SkBitmap& icon) { icon_ = icon; } +void TextButton::SetHoverIcon(const SkBitmap& icon) { + icon_hover_ = icon; + has_hover_icon_ = true; +} + void TextButton::SetFont(const gfx::Font& font) { font_ = font; } @@ -204,6 +214,10 @@ void TextButton::SetHighlightColor(SkColor color) { color_highlight_ = color; } +void TextButton::SetHoverColor(SkColor color) { + color_hover_ = color; +} + void TextButton::ClearMaxTextSize() { max_text_size_ = text_size_; } @@ -228,13 +242,19 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { PaintFocusBorder(canvas); } + SkBitmap icon; + if (has_hover_icon_ && (state() == BS_HOT || state() == BS_PUSHED)) + icon = icon_hover_; + else + icon = icon_; + gfx::Insets insets = GetInsets(); int available_width = width() - insets.width(); int available_height = height() - insets.height(); // Use the actual text (not max) size to properly center the text. int content_width = text_size_.width(); - if (icon_.width() > 0) { - content_width += icon_.width(); + if (icon.width() > 0) { + content_width += icon.width(); if (!text_.empty()) content_width += kIconTextPadding; } @@ -249,12 +269,19 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { std::max(0, (available_width - content_width) / 2) + insets.left(); } int text_x = icon_x; - if (icon_.width() > 0) - text_x += icon_.width() + kIconTextPadding; + if (icon.width() > 0) + text_x += icon.width() + kIconTextPadding; const int text_width = std::min(text_size_.width(), width() - insets.right() - text_x); int text_y = (available_height - text_size_.height()) / 2 + insets.top(); + // If the icon should go on the other side, swap the elements. + if (icon_placement_ == ICON_ON_RIGHT) { + int new_text_x = icon_x; + icon_x = new_text_x + text_width + kIconTextPadding; + text_x = new_text_x; + } + if (text_width > 0) { // Because the text button can (at times) draw multiple elements on the // canvas, we can not mirror the button by simply flipping the canvas as @@ -267,11 +294,17 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { gfx::Rect text_bounds(text_x, text_y, text_width, text_size_.height()); text_bounds.set_x(MirroredLeftPointForRect(text_bounds)); + SkColor text_color; + if (state() == BS_HOT || state() == BS_PUSHED) + text_color = color_hover_; + else + text_color = color_; + if (for_drag) { #if defined(OS_WIN) // TODO(erg): Either port DrawStringWithHalo to linux or find an // alternative here. - canvas->DrawStringWithHalo(text_, font_, color_, color_highlight_, + canvas->DrawStringWithHalo(text_, font_, text_color, color_highlight_, text_bounds.x(), text_bounds.y(), text_bounds.width(), @@ -280,7 +313,7 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { #else canvas->DrawStringInt(text_, font_, - color_, + text_color, text_bounds.x(), text_bounds.y(), text_bounds.width(), @@ -289,7 +322,7 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { } else { canvas->DrawStringInt(text_, font_, - color_, + text_color, text_bounds.x(), text_bounds.y(), text_bounds.width(), @@ -297,13 +330,13 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { } } - if (icon_.width() > 0) { - int icon_y = (available_height - icon_.height()) / 2 + insets.top(); + if (icon.width() > 0) { + int icon_y = (available_height - icon.height()) / 2 + insets.top(); // Mirroring the icon position if necessary. - gfx::Rect icon_bounds(icon_x, icon_y, icon_.width(), icon_.height()); + gfx::Rect icon_bounds(icon_x, icon_y, icon.width(), icon.height()); icon_bounds.set_x(MirroredLeftPointForRect(icon_bounds)); - canvas->DrawBitmapInt(icon_, icon_bounds.x(), icon_bounds.y()); + canvas->DrawBitmapInt(icon, icon_bounds.x(), icon_bounds.y()); } } diff --git a/views/controls/button/text_button.h b/views/controls/button/text_button.h index 20848db..d895a6e 100644 --- a/views/controls/button/text_button.h +++ b/views/controls/button/text_button.h @@ -87,6 +87,19 @@ class TextButton : public CustomButton { // Sets the icon. void SetIcon(const SkBitmap& icon); SkBitmap icon() const { return icon_; } + void SetHoverIcon(const SkBitmap& icon); + SkBitmap icon_hover() const { return icon_hover_; } + + // Meanings are reversed for right-to-left layouts. + enum IconPlacement { + ICON_ON_LEFT, + ICON_ON_RIGHT + }; + + IconPlacement icon_placement() { return icon_placement_; } + void set_icon_placement(IconPlacement icon_placement) { + icon_placement_ = icon_placement; + } // TextButton remembers the maximum display size of the text passed to // SetText. This method resets the cached maximum display size to the @@ -98,6 +111,7 @@ class TextButton : public CustomButton { void SetEnabledColor(SkColor color); void SetDisabledColor(SkColor color); void SetHighlightColor(SkColor color); + void SetHoverColor(SkColor color); // Paint the button into the specified canvas. If |for_drag| is true, the // function paints a drag image representation into the canvas. @@ -112,6 +126,7 @@ class TextButton : public CustomButton { static const SkColor kEnabledColor; static const SkColor kHighlightColor; static const SkColor kDisabledColor; + static const SkColor kHoverColor; protected: virtual bool OnMousePressed(const MouseEvent& e); @@ -135,6 +150,9 @@ class TextButton : public CustomButton { // The alignment of the text string within the button. TextAlignment alignment_; + // The position of the icon. + IconPlacement icon_placement_; + // The font used to paint the text. gfx::Font font_; @@ -145,10 +163,15 @@ class TextButton : public CustomButton { SkColor color_enabled_; SkColor color_disabled_; SkColor color_highlight_; + SkColor color_hover_; // An icon displayed with the text. SkBitmap icon_; + // An optional different version of the icon for hover state. + SkBitmap icon_hover_; + bool has_hover_icon_; + // The width of the button will never be larger than this value. A value <= 0 // indicates the width is not constrained. int max_width_; |