notification_view.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/views/notification_view.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/utf_string_conversions.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ui_resources.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/accessibility/accessible_view_state.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/text/text_elider.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/canvas.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/message_center_constants.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/message_center_switches.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/message_center_util.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_change_observer.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_types.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/views/message_simple_view.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/button/image_button.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/image_view.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/label.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/layout/box_layout.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/layout/fill_layout.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Dimensions. 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kIconColumnWidth = message_center::kNotificationIconSize; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kLegacyIconSize = 40; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kIconToTextPadding = 16; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTextTopPadding = 6; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTextLeftPadding = kIconColumnWidth + kIconToTextPadding; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTextBottomPadding = 6; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTextRightPadding = 23; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kItemTitleToMessagePadding = 3; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kButtonHeight = 38; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kButtonHorizontalPadding = 16; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kButtonVecticalPadding = 0; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kButtonIconTopPadding = 11; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kButtonIconToTitlePadding = 16; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kButtonTitleTopPadding = 0; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kTitleCharacterLimit = 100; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMessageCharacterLimit = 200; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Notification colors. The text background colors below are used only to keep 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// view::Label from modifying the text color and will not actually be drawn. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See view::Label's SetEnabledColor() and SetBackgroundColor() for details. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kBackgroundColor = SkColorSetRGB(255, 255, 255); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kLegacyIconBackgroundColor = SkColorSetRGB(230, 230, 230); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kRegularTextColor = SkColorSetRGB(68, 68, 68); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kRegularTextBackgroundColor = SK_ColorWHITE; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kDimTextColor = SkColorSetRGB(136, 136, 136); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kDimTextBackgroundColor = SK_ColorBLACK; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kButtonSeparatorColor = SkColorSetRGB(234, 234, 234); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static. 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)views::Background* MakeBackground(SkColor color = kBackgroundColor) { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return views::Background::CreateSolidBackground(color); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)views::Border* MakeBorder(int top, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom, 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int left = kTextLeftPadding, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int right = kTextRightPadding, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor color = 0x00000000) { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (color == 0x00000000) ? 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Border::CreateEmptyBorder(top, left, bottom, right) : 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Border::CreateSolidSidedBorder(top, left, bottom, right, color); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ContainerView /////////////////////////////////////////////////////////////// 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ContainerViews are vertical BoxLayout views that propagates their childrens' 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ChildPreferredSizeChanged() and ChildVisibilityChanged() calls. 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ContainerView : public views::View { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ContainerView(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~ContainerView(); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void ChildVisibilityChanged(View* child) OVERRIDE; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ContainerView); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContainerView::ContainerView() { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContainerView::~ContainerView() { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ContainerView::ChildPreferredSizeChanged(View* child) { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PreferredSizeChanged(); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ContainerView::ChildVisibilityChanged(View* child) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PreferredSizeChanged(); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ItemView //////////////////////////////////////////////////////////////////// 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ItemViews are responsible for drawing each list notification item's title and 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// message next to each other within a single column. 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ItemView : public views::View { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ItemView(const message_center::NotificationItem& item); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~ItemView(); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetVisible(bool visible) OVERRIDE; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ItemView); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ItemView::ItemView(const message_center::NotificationItem& item) { 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, 0, kItemTitleToMessagePadding)); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Label* title = new views::Label(item.title); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title->set_collapse_when_hidden(true); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title->SetHorizontalAlignment(gfx::ALIGN_LEFT); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title->SetElideBehavior(views::Label::ELIDE_AT_END); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title->SetEnabledColor(kRegularTextColor); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title->SetBackgroundColor(kRegularTextBackgroundColor); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(title); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Label* message = new views::Label(item.message); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->set_collapse_when_hidden(true); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->SetHorizontalAlignment(gfx::ALIGN_LEFT); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->SetElideBehavior(views::Label::ELIDE_AT_END); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->SetEnabledColor(kDimTextColor); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->SetBackgroundColor(kDimTextBackgroundColor); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(message); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PreferredSizeChanged(); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ItemView::~ItemView() { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ItemView::SetVisible(bool visible) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View::SetVisible(visible); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < child_count(); ++i) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) child_at(i)->SetVisible(visible); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ProportionalImageView /////////////////////////////////////////////////////// 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ProportionalImageViews center their images to preserve their proportion. 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ProportionalImageView : public views::View { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProportionalImageView(const gfx::ImageSkia& image); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~ProportionalImageView(); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Overridden from views::View: 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual gfx::Size GetPreferredSize() OVERRIDE; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int GetHeightForWidth(int width) OVERRIDE; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size GetImageSizeForWidth(int width); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ImageSkia image_; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ProportionalImageView); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProportionalImageView::ProportionalImageView(const gfx::ImageSkia& image) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : image_(image) { 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProportionalImageView::~ProportionalImageView() { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Size ProportionalImageView::GetPreferredSize() { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size size = GetImageSizeForWidth(image_.width()); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Size(size.width() + GetInsets().width(), 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.height() + GetInsets().height()); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ProportionalImageView::GetHeightForWidth(int width) { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetImageSizeForWidth(width).height(); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProportionalImageView::OnPaint(gfx::Canvas* canvas) { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View::OnPaint(canvas); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size draw_size(GetImageSizeForWidth(width())); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!draw_size.IsEmpty()) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect draw_bounds = GetLocalBounds(); 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) draw_bounds.Inset(GetInsets()); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) draw_bounds.ClampToCenteredSize(draw_size); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size image_size(image_.size()); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_size == draw_size) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->DrawImageInt(image_, draw_bounds.x(), draw_bounds.y()); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Resize case 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkPaint paint; 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) paint.setFilterBitmap(true); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->DrawImageInt(image_, 0, 0, 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_size.width(), image_size.height(), 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) draw_bounds.x(), draw_bounds.y(), 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) draw_size.width(), draw_size.height(), 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true, paint); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Size ProportionalImageView::GetImageSizeForWidth(int width) { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size size = visible() ? image_.size() : gfx::Size(); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (width > 0 && !size.IsEmpty()) { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double proportion = size.height() / (double) size.width(); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.SetSize(width, std::max(0.5 + width * proportion, 1.0)); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (size.height() > message_center::kNotificationMaximumImageHeight) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height = message_center::kNotificationMaximumImageHeight; 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.SetSize(std::max(0.5 + height / proportion, 1.0), height); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationButton ////////////////////////////////////////////////////////// 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationButtons render the action buttons of notifications. 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NotificationButton : public views::CustomButton { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationButton(views::ButtonListener* listener); 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~NotificationButton(); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetIcon(const gfx::ImageSkia& icon); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetTitle(const string16& title); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Overridden from views::View: 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual gfx::Size GetPreferredSize() OVERRIDE; 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int GetHeightForWidth(int width) OVERRIDE; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::ImageView* icon_; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Label* title_; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationButton::NotificationButton(views::ButtonListener* listener) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : views::CustomButton(listener), 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_(NULL), 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_(NULL) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_focusable(true); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kButtonHorizontalPadding, 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kButtonVecticalPadding, 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kButtonIconToTitlePadding)); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationButton::~NotificationButton() { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationButton::SetIcon(const gfx::ImageSkia& image) { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_ != NULL) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete icon_; // This removes the icon from this view's children. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image.isNull()) { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_ = NULL; 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_ = new views::ImageView(); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_->SetImageSize(gfx::Size(message_center::kNotificationButtonIconSize, 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_center::kNotificationButtonIconSize)); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_->SetImage(image); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_->SetHorizontalAlignment(views::ImageView::LEADING); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_->SetVerticalAlignment(views::ImageView::LEADING); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_->set_border(MakeBorder(kButtonIconTopPadding, 0, 0, 0)); 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildViewAt(icon_, 0); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationButton::SetTitle(const string16& title) { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (title_ != NULL) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete title_; // This removes the title from this view's children. 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (title.empty()) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_ = NULL; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_ = new views::Label(title); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_->SetElideBehavior(views::Label::ELIDE_AT_END); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_->SetEnabledColor(kRegularTextColor); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_->SetBackgroundColor(kRegularTextBackgroundColor); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_->set_border(MakeBorder(kButtonTitleTopPadding, 0, 0, 0)); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(title_); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Size NotificationButton::GetPreferredSize() { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Size(message_center::kNotificationWidth, kButtonHeight); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int NotificationButton::GetHeightForWidth(int width) { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kButtonHeight; 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace message_center { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationView //////////////////////////////////////////////////////////// 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageView* NotificationView::Create(const Notification& notification, 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationChangeObserver* observer, 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool expanded) { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use MessageSimpleView for simple notifications unless rich style 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // notifications are enabled. This preserves the appearance of notifications 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // created by existing code that uses webkitNotifications. 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsRichNotificationEnabled() && 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification.type() == NOTIFICATION_TYPE_SIMPLE) 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new MessageSimpleView(notification, observer); 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (notification.type()) { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_BASE_FORMAT: 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_IMAGE: 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_MULTIPLE: 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_SIMPLE: 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the caller asks for an unrecognized kind of view (entirely possible 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if an application is running on an older version of this code that 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't have the requested kind of notification template), we'll fall 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // back to a notification instance that will provide at least basic 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // functionality. 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Unable to fulfill request for unrecognized " 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "notification type " << notification.type() << ". " 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Falling back to simple notification type."; 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Currently all roads lead to the generic NotificationView. 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new NotificationView(notification, observer, expanded); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationView::NotificationView(const Notification& notification, 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationChangeObserver* observer, 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool expanded) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : MessageView(notification, observer, expanded) { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the opaque background that's above the view's shadow. 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background_view_ = new views::View(); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background_view_->set_background(MakeBackground()); 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the top_view_, which collects into a vertical box all content 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // at the top of the notification (to the right of the icon) except for the 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // close button. 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top_view_ = new ContainerView(); 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the title view if appropriate. 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_ = NULL; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!notification.title().empty()) { 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_ = new views::Label( 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MaybeTruncateText( notification.title(), kTitleCharacterLimit)); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_expanded()) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->SetMultiLine(true); 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->SetElideBehavior(views::Label::ELIDE_AT_END); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->SetFont(title_view_->font().DeriveFont(2)); 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->SetEnabledColor(kRegularTextColor); 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->SetBackgroundColor(kRegularTextBackgroundColor); 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_view_->set_border(MakeBorder(kTextTopPadding, 3)); 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top_view_->AddChildView(title_view_); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the message view if appropriate. 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_ = NULL; 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!notification.message().empty()) { 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_ = new views::Label( 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MaybeTruncateText(notification.message(), kMessageCharacterLimit)); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetVisible(!is_expanded() || !notification.items().size()); 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->set_collapse_when_hidden(true); 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_expanded()) 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetMultiLine(true); 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetElideBehavior(views::Label::ELIDE_AT_END); 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetEnabledColor(kRegularTextColor); 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetBackgroundColor(kRegularTextBackgroundColor); 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->set_border(MakeBorder(0, 3)); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top_view_->AddChildView(message_view_); 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the list item views (up to a maximum). 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<NotificationItem> items = notification.items(); 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) { 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ItemView* item_view = new ItemView(items[i]); 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_view->SetVisible(is_expanded()); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_view->set_border(MakeBorder(0, 4)); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_views_.push_back(item_view); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top_view_->AddChildView(item_view); 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the notification icon view. 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (notification.type() == NOTIFICATION_TYPE_SIMPLE) { 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::ImageView* icon_view = new views::ImageView(); 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view->SetImage(notification.icon().AsImageSkia()); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view->SetImageSize(gfx::Size(kLegacyIconSize, kLegacyIconSize)); 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view->SetHorizontalAlignment(views::ImageView::CENTER); 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view->SetVerticalAlignment(views::ImageView::CENTER); 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view->set_background(MakeBackground(kLegacyIconBackgroundColor)); 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view_ = icon_view; 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view_ = new ProportionalImageView(notification.icon().AsImageSkia()); 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the bottom_view_, which collects into a vertical box all content 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // below the notification icon except for the expand button. 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bottom_view_ = new ContainerView(); 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the image view if appropriate. 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_view_ = NULL; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!notification.image().IsEmpty()) { 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_view_ = new ProportionalImageView(notification.image().AsImageSkia()); 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_view_->SetVisible(is_expanded()); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bottom_view_->AddChildView(image_view_); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create action buttons if appropriate. 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ButtonInfo> buttons = notification.buttons(); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < buttons.size(); ++i) { 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View* separator = new views::ImageView(); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) separator->set_border(MakeBorder(1, 0, 0, 0, kButtonSeparatorColor)); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bottom_view_->AddChildView(separator); 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationButton* button = new NotificationButton(this); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ButtonInfo button_info = buttons[i]; 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetTitle(button_info.title); 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetIcon(button_info.icon.AsImageSkia()); 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) action_buttons_.push_back(button); 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bottom_view_->AddChildView(button); 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Hide the expand button if appropriate. 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool expandable = item_views_.size() || image_view_; 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expand_button()->SetVisible(expandable && !is_expanded()); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put together the different content and control views. Layering those allows 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for proper layout logic and it also allows the close and expand buttons to 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // overlap the content as needed to provide large enough click and touch areas 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (<http://crbug.com/168822> and <http://crbug.com/168856>). 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(background_view_); 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(top_view_); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(icon_view_); 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(bottom_view_); 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(close_button()); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(expand_button()); 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationView::~NotificationView() { 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Size NotificationView::GetPreferredSize() { 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int top_width = top_view_->GetPreferredSize().width(); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom_width = bottom_view_->GetPreferredSize().width(); 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int preferred_width = std::max(top_width, bottom_width) + GetInsets().width(); 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Size(preferred_width, GetHeightForWidth(preferred_width)); 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int NotificationView::GetHeightForWidth(int width) { 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Insets insets = GetInsets(); 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int top_height = top_view_->GetHeightForWidth(width - insets.width()); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom_height = bottom_view_->GetHeightForWidth(width - insets.width()); 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_size = message_center::kNotificationIconSize; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return std::max(top_height, icon_size) + bottom_height + insets.height(); 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationView::Layout() { 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Insets insets = GetInsets(); 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int content_width = width() - insets.width(); 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int content_right = width() - insets.right(); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background_view_->SetBounds(insets.left(), insets.top(), 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_width, height() - insets.height()); 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int top_height = top_view_->GetHeightForWidth(content_width); 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height); 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_size = message_center::kNotificationIconSize; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_view_->SetBounds(insets.left(), insets.top(), icon_size, icon_size); 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom_y = insets.top() + std::max(top_height, icon_size); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom_height = bottom_view_->GetHeightForWidth(content_width); 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bottom_view_->SetBounds(insets.left(), bottom_y, 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_width, bottom_height); 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size close_size(close_button()->GetPreferredSize()); 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button()->SetBounds(content_right - close_size.width(), insets.top(), 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_size.width(), close_size.height()); 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size expand_size(expand_button()->GetPreferredSize()); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expand_y = bottom_y - expand_size.height(); 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expand_button()->SetBounds(content_right - expand_size.width(), expand_y, 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expand_size.width(), expand_size.height()); 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationView::ButtonPressed(views::Button* sender, 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::Event& event) { 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if the button pressed was an action button. 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < action_buttons_.size(); ++i) { 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sender == action_buttons_[i]) { 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer()->OnButtonClicked(notification_id(), i); 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Let the superclass handled anything other than action buttons. 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessageView::ButtonPressed(sender, event); 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Show and hide subviews appropriately on expansion. 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sender == expand_button()) { 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (message_view_ && item_views_.size()) 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_view_->SetVisible(false); 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < item_views_.size(); ++i) 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_views_[i]->SetVisible(true); 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_view_) 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_view_->SetVisible(true); 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expand_button()->SetVisible(false); 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PreferredSizeChanged(); 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)string16 NotificationView::MaybeTruncateText(const string16& text, 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t limit) { 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Currently just truncate the text by the total number of characters. 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(mukai): add better assumption like number of lines. 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_expanded()) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return text; 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::TruncateString(text, limit); 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace message_center 544