summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-05 00:51:58 +0000
committerjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-05 00:51:58 +0000
commitbd76fc2bcef23c62e570bdb67d782f4811a5f92d (patch)
tree0ece71dd45e5abe72bce4ecc9f12c1055238b3a2
parent103c215374c596425c599483053f69805720da71 (diff)
downloadchromium_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-xchrome/app/theme/balloon_close.pngbin0 -> 379 bytes
-rwxr-xr-xchrome/app/theme/balloon_close_hover.pngbin0 -> 373 bytes
-rw-r--r--chrome/app/theme/balloon_frame.pngbin285 -> 301 bytes
-rwxr-xr-xchrome/app/theme/balloon_options_arrow.pngbin0 -> 236 bytes
-rwxr-xr-xchrome/app/theme/balloon_options_arrow_hover.pngbin0 -> 238 bytes
-rw-r--r--chrome/app/theme/balloon_shelf.pngbin275 -> 301 bytes
-rw-r--r--chrome/app/theme/theme_resources.grd6
-rw-r--r--chrome/browser/notifications/balloon_collection.cc20
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc6
-rw-r--r--chrome/browser/resources/notification.html63
-rw-r--r--chrome/browser/views/notifications/balloon_view.cc47
-rw-r--r--views/controls/button/text_button.cc55
-rw-r--r--views/controls/button/text_button.h23
13 files changed, 147 insertions, 73 deletions
diff --git a/chrome/app/theme/balloon_close.png b/chrome/app/theme/balloon_close.png
new file mode 100755
index 0000000..cd5609e
--- /dev/null
+++ b/chrome/app/theme/balloon_close.png
Binary files differ
diff --git a/chrome/app/theme/balloon_close_hover.png b/chrome/app/theme/balloon_close_hover.png
new file mode 100755
index 0000000..8d36beb
--- /dev/null
+++ b/chrome/app/theme/balloon_close_hover.png
Binary files differ
diff --git a/chrome/app/theme/balloon_frame.png b/chrome/app/theme/balloon_frame.png
index f3059e4..347523b 100644
--- a/chrome/app/theme/balloon_frame.png
+++ b/chrome/app/theme/balloon_frame.png
Binary files differ
diff --git a/chrome/app/theme/balloon_options_arrow.png b/chrome/app/theme/balloon_options_arrow.png
new file mode 100755
index 0000000..e3d757c
--- /dev/null
+++ b/chrome/app/theme/balloon_options_arrow.png
Binary files differ
diff --git a/chrome/app/theme/balloon_options_arrow_hover.png b/chrome/app/theme/balloon_options_arrow_hover.png
new file mode 100755
index 0000000..f4f6283
--- /dev/null
+++ b/chrome/app/theme/balloon_options_arrow_hover.png
Binary files differ
diff --git a/chrome/app/theme/balloon_shelf.png b/chrome/app/theme/balloon_shelf.png
index 66de8f1..dd1173a 100644
--- a/chrome/app/theme/balloon_shelf.png
+++ b/chrome/app/theme/balloon_shelf.png
Binary files differ
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_;