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" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/stl_util.h" 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/base/cursor/cursor.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/layout.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/canvas.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h" 152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "ui/gfx/skia_util.h" 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/text_elider.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/message_center.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_types.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/bounded_label.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/constants.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/message_center_controller.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/notification_button.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/message_center/views/padded_button.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/proportional_image_view.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h" 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h" 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/strings/grit/ui_strings.h" 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/background.h" 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/border.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/button/image_button.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/image_view.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/label.h" 35a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "ui/views/controls/progress_bar.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/layout/box_layout.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/layout/fill_layout.h" 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/native_cursor.h" 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/painter.h" 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/views/view_targeter.h" 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/widget/widget.h" 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Dimensions. 46a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst int kProgressBarWidth = message_center::kNotificationWidth - 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kTextLeftPadding - message_center::kTextRightPadding; 482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst int kProgressBarBottomPadding = 0; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeEmptyBorder(int top, 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int left, 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int bottom, 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int right) { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return views::Border::CreateEmptyBorder(top, left, bottom, right); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeTextBorder(int padding, int top, int bottom) { 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Split the padding between the top and the bottom, then add the extra space. 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MakeEmptyBorder(padding / 2 + top, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kTextLeftPadding, 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (padding + 1) / 2 + bottom, 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kTextRightPadding); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeProgressBarBorder(int top, int bottom) { 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MakeEmptyBorder(top, 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kTextLeftPadding, 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bottom, 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kTextRightPadding); 73a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 74a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// static 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeSeparatorBorder(int top, 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int left, 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkColor color) { 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return views::Border::CreateSolidSidedBorder(top, left, 0, 0, color); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Return true if and only if the image is null or has alpha. 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HasAlpha(gfx::ImageSkia& image, views::Widget* widget) { 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Determine which bitmap to use. 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float factor = 1.0f; 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (widget) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) factor = ui::GetScaleFactorForNativeView(widget->GetNativeView()); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Extract that bitmap's alpha and look for a non-opaque pixel there. 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SkBitmap bitmap = image.GetRepresentation(factor).sk_bitmap(); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!bitmap.isNull()) { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkBitmap alpha; 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bitmap.extractAlpha(&alpha); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int y = 0; y < bitmap.height(); ++y) { 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int x = 0; x < bitmap.width(); ++x) { 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (alpha.getColor(x, y) != SK_ColorBLACK) { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If no opaque pixel was found, return false unless the bitmap is empty. 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return bitmap.isNull(); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ItemView //////////////////////////////////////////////////////////////////// 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ItemViews are responsible for drawing each list notification item's title and 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// message next to each other within a single column. 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ItemView : public views::View { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ItemView(const message_center::NotificationItem& item); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~ItemView(); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Overridden from views::View: 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, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 0, message_center::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); 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) title->SetEnabledColor(message_center::kRegularTextColor); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) title->SetBackgroundColor(message_center::kRegularTextBackgroundColor); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(title); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Label* message = new views::Label(item.message); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->set_collapse_when_hidden(true); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message->SetHorizontalAlignment(gfx::ALIGN_LEFT); 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) message->SetEnabledColor(message_center::kDimTextColor); 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message->SetBackgroundColor(message_center::kDimTextBackgroundColor); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(message); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PreferredSizeChanged(); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ItemView::~ItemView() { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ItemView::SetVisible(bool visible) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View::SetVisible(visible); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < child_count(); ++i) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) child_at(i)->SetVisible(visible); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The NotificationImage is the view representing the area covered by the 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// notification's image, including background and border. Its size can be 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// specified in advance and images will be scaled to fit including a border if 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// necessary. 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)views::View* MakeNotificationImage(const gfx::Image& image, gfx::Size size) { 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) views::View* container = new views::View(); 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) container->SetLayoutManager(new views::FillLayout()); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) container->set_background(views::Background::CreateSolidBackground( 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kImageBackgroundColor)); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Size ideal_size( 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kNotificationPreferredImageWidth, 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kNotificationPreferredImageHeight); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Size scaled_size = 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::GetImageSizeForContainerSize(ideal_size, image.Size()); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) views::View* proportional_image_view = 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new message_center::ProportionalImageView(image.AsImageSkia(), 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ideal_size); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This calculation determines that the new image would have the correct 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // height for width. 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ideal_size != scaled_size) { 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) proportional_image_view->SetBorder(views::Border::CreateSolidBorder( 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::kNotificationImageBorderSize, SK_ColorTRANSPARENT)); 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) container->AddChildView(proportional_image_view); 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return container; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 188a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// NotificationProgressBar ///////////////////////////////////////////////////// 189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 190a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass NotificationProgressBar : public views::ProgressBar { 191a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch public: 192a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch NotificationProgressBar(); 193a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch virtual ~NotificationProgressBar(); 194a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 195a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch private: 196a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Overriden from View 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual gfx::Size GetPreferredSize() const OVERRIDE; 1982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 199a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 200a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch DISALLOW_COPY_AND_ASSIGN(NotificationProgressBar); 201a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}; 202a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 203a3f7b4e666c476898878fa745f637129375cd889Ben MurdochNotificationProgressBar::NotificationProgressBar() { 204a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 205a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 206a3f7b4e666c476898878fa745f637129375cd889Ben MurdochNotificationProgressBar::~NotificationProgressBar() { 207a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 208a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NotificationProgressBar::GetPreferredSize() const { 2102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch gfx::Size pref_size(kProgressBarWidth, message_center::kProgressBarThickness); 211a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch gfx::Insets insets = GetInsets(); 212a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch pref_size.Enlarge(insets.width(), insets.height()); 213a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return pref_size; 214a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 215a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 2162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NotificationProgressBar::OnPaint(gfx::Canvas* canvas) { 2172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch gfx::Rect content_bounds = GetContentsBounds(); 2182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 2192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Draw background. 2202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch SkPath background_path; 2212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch background_path.addRoundRect(gfx::RectToSkRect(content_bounds), 2222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch message_center::kProgressBarCornerRadius, 2232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch message_center::kProgressBarCornerRadius); 2242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch SkPaint background_paint; 2252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch background_paint.setStyle(SkPaint::kFill_Style); 2262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch background_paint.setFlags(SkPaint::kAntiAlias_Flag); 2272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch background_paint.setColor(message_center::kProgressBarBackgroundColor); 2282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch canvas->DrawPath(background_path, background_paint); 2292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 2302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Draw slice. 2312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch const int slice_width = 2322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch static_cast<int>(content_bounds.width() * GetNormalizedValue() + 0.5); 2332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (slice_width < 1) 2342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return; 2352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 2362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch gfx::Rect slice_bounds = content_bounds; 2372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch slice_bounds.set_width(slice_width); 2382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch SkPath slice_path; 2392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch slice_path.addRoundRect(gfx::RectToSkRect(slice_bounds), 2402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch message_center::kProgressBarCornerRadius, 2412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch message_center::kProgressBarCornerRadius); 2422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch SkPaint slice_paint; 2432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch slice_paint.setStyle(SkPaint::kFill_Style); 2442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch slice_paint.setFlags(SkPaint::kAntiAlias_Flag); 2452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch slice_paint.setColor(message_center::kProgressBarSliceColor); 2462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch canvas->DrawPath(slice_path, slice_paint); 2472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch} 2482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace message_center { 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationView //////////////////////////////////////////////////////////// 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationView* NotificationView::Create(MessageCenterController* controller, 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Notification& notification, 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool top_level) { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (notification.type()) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_BASE_FORMAT: 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_IMAGE: 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_MULTIPLE: 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTIFICATION_TYPE_SIMPLE: 264a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case NOTIFICATION_TYPE_PROGRESS: 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the caller asks for an unrecognized kind of view (entirely possible 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if an application is running on an older version of this code that 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't have the requested kind of notification template), we'll fall 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // back to a notification instance that will provide at least basic 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // functionality. 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Unable to fulfill request for unrecognized " 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "notification type " << notification.type() << ". " 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Falling back to simple notification type."; 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Currently all roads lead to the generic NotificationView. 278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NotificationView* notification_view = 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new NotificationView(controller, notification); 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't create shadows for notification toasts on linux wih aura. 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (top_level) 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return notification_view; 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification_view->CreateShadowBorder(); 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return notification_view; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::View* NotificationView::TargetForRect(views::View* root, 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const gfx::Rect& rect) { 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK_EQ(root, this); 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(tdanderson): Modify this function to support rect-based event 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // targeting. Using the center point of |rect| preserves this function's 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // expected behavior for the time being. 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Point point = rect.CenterPoint(); 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Want to return this for underlying views, otherwise GetCursor is not 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // called. But buttons are exceptions, they'll have their own event handlings. 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<views::View*> buttons(action_buttons_.begin(), 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) action_buttons_.end()); 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buttons.push_back(close_button()); 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < buttons.size(); ++i) { 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Point point_in_child = point; 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ConvertPointToTarget(this, buttons[i], &point_in_child); 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (buttons[i]->HitTestPoint(point_in_child)) 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return buttons[i]->GetEventHandlerForPoint(point_in_child); 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return root; 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateViews(const Notification& notification) { 3170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateTitleView(notification); 3180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateMessageView(notification); 3190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateContextMessageView(notification); 3200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateProgressBarView(notification); 3210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateListItemViews(notification); 3220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateIconView(notification); 3230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateImageView(notification); 3240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateActionButtonViews(notification); 3250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 3260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 3270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::SetAccessibleName(const Notification& notification) { 3280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::vector<base::string16> accessible_lines; 3290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) accessible_lines.push_back(notification.title()); 3300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) accessible_lines.push_back(notification.message()); 3310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) accessible_lines.push_back(notification.context_message()); 3320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::vector<NotificationItem> items = notification.items(); 3330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) { 3340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) accessible_lines.push_back(items[i].title + base::ASCIIToUTF16(" ") + 3350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) items[i].message); 3360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 3370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) set_accessible_name(JoinString(accessible_lines, '\n')); 3380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 3390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationView::NotificationView(MessageCenterController* controller, 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Notification& notification) 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : MessageView(this, 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification.id(), 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification.notifier_id(), 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification.small_image().AsImageSkia(), 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification.display_source()), 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_(controller), 3480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) clickable_(notification.clickable()), 3490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) top_view_(NULL), 3500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) title_view_(NULL), 3510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view_(NULL), 3520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) context_message_view_(NULL), 3530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view_(NULL), 3540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) bottom_view_(NULL), 3550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) image_view_(NULL), 3560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) progress_bar_view_(NULL) { 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the top_view_, which collects into a vertical box all content 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // at the top of the notification (to the right of the icon) except for the 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // close button. 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) top_view_ = new views::View(); 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) top_view_->SetLayoutManager( 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) top_view_->SetBorder( 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeEmptyBorder(kTextTopPadding - 8, 0, kTextBottomPadding - 5, 0)); 3650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) AddChildView(top_view_); 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the bottom_view_, which collects into a vertical box all content 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // below the notification icon. 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bottom_view_ = new views::View(); 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bottom_view_->SetLayoutManager( 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); 3710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) AddChildView(bottom_view_); 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateViews(notification); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put together the different content and control views. Layering those allows 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // for proper layout logic and it also allows the close button and small 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // image to overlap the content as needed to provide large enough click and 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // touch areas (<http://crbug.com/168822> and <http://crbug.com/168856>). 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AddChildView(small_image()); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(close_button()); 3810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) SetAccessibleName(notification); 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetEventTargeter( 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationView::~NotificationView() { 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NotificationView::GetPreferredSize() const { 3910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) int top_width = top_view_->GetPreferredSize().width() + 3920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view_->GetPreferredSize().width(); 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom_width = bottom_view_->GetPreferredSize().width(); 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int preferred_width = std::max(top_width, bottom_width) + GetInsets().width(); 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Size(preferred_width, GetHeightForWidth(preferred_width)); 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int NotificationView::GetHeightForWidth(int width) const { 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Get the height assuming no line limit changes. 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int content_width = width - GetInsets().width(); 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int top_height = top_view_->GetHeightForWidth(content_width); 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int bottom_height = bottom_view_->GetHeightForWidth(content_width); 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // <http://crbug.com/230448> Fix: Adjust the height when the message_view's 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // line limit would be different for the specified width than it currently is. 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(dharcourt): Avoid BoxLayout and directly compute the correct height. 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (message_view_) { 408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int title_lines = 0; 409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (title_view_) { 410010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) title_lines = title_view_->GetLinesForWidthAndLimit(width, 411010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kMaxTitleLines); 412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int used_limit = message_view_->GetLineLimit(); 414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int correct_limit = GetMessageLineLimit(title_lines, width); 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (used_limit != correct_limit) { 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) top_height -= GetMessageHeight(content_width, used_limit); 417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) top_height += GetMessageHeight(content_width, correct_limit); 418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int content_height = std::max(top_height, kIconSize) + bottom_height; 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Adjust the height to make sure there is at least 16px of space below the 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // icon if there is any space there (<http://crbug.com/232966>). 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (content_height > kIconSize) 426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch content_height = std::max(content_height, 427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch kIconSize + message_center::kIconBottomPadding); 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return content_height + GetInsets().height(); 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationView::Layout() { 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MessageView::Layout(); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Insets insets = GetInsets(); 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int content_width = width() - insets.width(); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Before any resizing, set or adjust the number of message lines. 438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int title_lines = 0; 439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (title_view_) { 440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) title_lines = 441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) title_view_->GetLinesForWidthAndLimit(width(), kMaxTitleLines); 442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (message_view_) 444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) message_view_->SetLineLimit(GetMessageLineLimit(title_lines, width())); 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Top views. 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int top_height = top_view_->GetHeightForWidth(content_width); 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height); 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Icon. 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) icon_view_->SetBounds(insets.left(), insets.top(), kIconSize, kIconSize); 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Bottom views. 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int bottom_y = insets.top() + std::max(top_height, kIconSize); 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom_height = bottom_view_->GetHeightForWidth(content_width); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bottom_view_->SetBounds(insets.left(), bottom_y, 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_width, bottom_height); 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NotificationView::OnFocus() { 46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MessageView::OnFocus(); 46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ScrollRectToVisible(GetLocalBounds()); 46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotificationView::ScrollRectToVisible(const gfx::Rect& rect) { 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Notification want to show the whole notification when a part of it (like 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // a button) gets focused. 468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) views::View::ScrollRectToVisible(GetLocalBounds()); 469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 471a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)gfx::NativeCursor NotificationView::GetCursor(const ui::MouseEvent& event) { 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!clickable_ || !controller_->HasClickedListener(notification_id())) 47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return views::View::GetCursor(event); 47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return views::GetNativeHandCursor(); 476a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 4780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::UpdateWithNotification( 4790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 4800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) MessageView::UpdateWithNotification(notification); 4810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 4820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) CreateOrUpdateViews(notification); 4830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) SetAccessibleName(notification); 4840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) Layout(); 4850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) SchedulePaint(); 4860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 4870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationView::ButtonPressed(views::Button* sender, 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::Event& event) { 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Certain operations can cause |this| to be destructed, so copy the members 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // we send to other parts of the code. 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(dewittj): Remove this hack. 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string id(notification_id()); 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if the button pressed was an action button. 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < action_buttons_.size(); ++i) { 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sender == action_buttons_[i]) { 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ClickOnNotificationButton(id, i); 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Let the superclass handled anything other than action buttons. 50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Warning: This may cause the NotificationView itself to be deleted, 50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // so don't do anything afterwards. 50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MessageView::ButtonPressed(sender, event); 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationView::ClickOnNotification(const std::string& notification_id) { 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ClickOnNotification(notification_id); 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationView::RemoveNotification(const std::string& notification_id, 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool by_user) { 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->RemoveNotification(notification_id, by_user); 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateTitleView( 5180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 5190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (notification.title().empty()) { 5200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (title_view_) { 5210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Deletion will also remove |title_view_| from its parent. 5220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete title_view_; 5230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) title_view_ = NULL; 5240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 5260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(top_view_ != NULL); 5290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const gfx::FontList& font_list = 5310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) views::Label().font_list().DeriveWithSizeDelta(2); 5320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) int title_character_limit = 5340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter; 5350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::string16 title = gfx::TruncateString(notification.title(), 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) title_character_limit, 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::WORD_BREAK); 5390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!title_view_) { 5400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) int padding = kTitleLineHeight - font_list.GetHeight(); 5410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) title_view_ = new BoundedLabel(title, font_list); 5430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) title_view_->SetLineHeight(kTitleLineHeight); 5440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) title_view_->SetLineLimit(kMaxTitleLines); 5450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) title_view_->SetColors(message_center::kRegularTextColor, 5460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kRegularTextBackgroundColor); 5470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) title_view_->SetBorder(MakeTextBorder(padding, 3, 0)); 5480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) top_view_->AddChildView(title_view_); 5490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } else { 5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) title_view_->SetText(title); 5510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 5530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateMessageView( 5550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 5560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (notification.message().empty()) { 5570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (message_view_) { 5580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Deletion will also remove |message_view_| from its parent. 5590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete message_view_; 5600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view_ = NULL; 5610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 5630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(top_view_ != NULL); 5660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::string16 text = gfx::TruncateString(notification.message(), 5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kMessageCharacterLimit, 5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::WORD_BREAK); 5700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!message_view_) { 5710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) int padding = kMessageLineHeight - views::Label().font_list().GetHeight(); 5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_view_ = new BoundedLabel(text); 5730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view_->SetLineHeight(kMessageLineHeight); 5740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view_->SetColors(message_center::kRegularTextColor, 5750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kDimTextBackgroundColor); 5760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view_->SetBorder(MakeTextBorder(padding, 4, 0)); 5770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) top_view_->AddChildView(message_view_); 5780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } else { 5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_view_->SetText(text); 5800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_view_->SetVisible(!notification.items().size()); 5830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 5840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateContextMessageView( 5860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 5870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (notification.context_message().empty()) { 5880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (context_message_view_) { 5890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Deletion will also remove |context_message_view_| from its parent. 5900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete context_message_view_; 5910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) context_message_view_ = NULL; 5920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 5940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 5950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(top_view_ != NULL); 5970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::string16 text = gfx::TruncateString(notification.context_message(), 5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kContextMessageCharacterLimit, 6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::WORD_BREAK); 6010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!context_message_view_) { 6020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) int padding = kMessageLineHeight - views::Label().font_list().GetHeight(); 6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context_message_view_ = new BoundedLabel(text); 6040de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) context_message_view_->SetLineLimit( 6050de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_center::kContextMessageLineLimit); 6060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) context_message_view_->SetLineHeight(kMessageLineHeight); 6070de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) context_message_view_->SetColors(message_center::kDimTextColor, 6080de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kContextTextBackgroundColor); 6090de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) context_message_view_->SetBorder(MakeTextBorder(padding, 4, 0)); 6100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) top_view_->AddChildView(context_message_view_); 6110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } else { 6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context_message_view_->SetText(text); 6130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 6150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateProgressBarView( 6170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 6180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (notification.type() != NOTIFICATION_TYPE_PROGRESS) { 6190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (progress_bar_view_) { 6200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Deletion will also remove |progress_bar_view_| from its parent. 6210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete progress_bar_view_; 6220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) progress_bar_view_ = NULL; 6230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 6250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(top_view_ != NULL); 6280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!progress_bar_view_) { 6300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) progress_bar_view_ = new NotificationProgressBar(); 6310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) progress_bar_view_->SetBorder(MakeProgressBarBorder( 6320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_center::kProgressBarTopPadding, kProgressBarBottomPadding)); 6330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) top_view_->AddChildView(progress_bar_view_); 6340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) progress_bar_view_->SetValue(notification.progress() / 100.0); 6370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) progress_bar_view_->SetVisible(!notification.items().size()); 6380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 6390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateListItemViews( 6410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 6420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) for (size_t i = 0; i < item_views_.size(); ++i) 6430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete item_views_[i]; 6440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) item_views_.clear(); 6450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) int padding = kMessageLineHeight - views::Label().font_list().GetHeight(); 6470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) std::vector<NotificationItem> items = notification.items(); 6480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (items.size() == 0) 6500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return; 6510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(top_view_); 6530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) { 6540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) ItemView* item_view = new ItemView(items[i]); 6550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) item_view->SetBorder(MakeTextBorder(padding, i ? 0 : 4, 0)); 6560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) item_views_.push_back(item_view); 6570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) top_view_->AddChildView(item_view); 6580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 6600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateIconView( 6620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 6630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (icon_view_) { 6640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete icon_view_; 6650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view_ = NULL; 6660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // TODO(dewittj): Detect a compatible update and use the existing icon view. 6690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) gfx::ImageSkia icon = notification.icon().AsImageSkia(); 6700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (notification.type() == NOTIFICATION_TYPE_SIMPLE && 6710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) (icon.width() != kIconSize || icon.height() != kIconSize || 6720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) HasAlpha(icon, GetWidget()))) { 6730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) views::ImageView* icon_view = new views::ImageView(); 6740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view->SetImage(icon); 6750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view->SetImageSize(gfx::Size(kLegacyIconSize, kLegacyIconSize)); 6760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view->SetHorizontalAlignment(views::ImageView::CENTER); 6770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view->SetVerticalAlignment(views::ImageView::CENTER); 6780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view_ = icon_view; 6790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } else { 6800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view_ = 6810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) new ProportionalImageView(icon, gfx::Size(kIconSize, kIconSize)); 6820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) icon_view_->set_background( 6850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) views::Background::CreateSolidBackground(kIconBackgroundColor)); 6860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) AddChildView(icon_view_); 6880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 6890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateImageView( 6910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 6920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (image_view_) { 6930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) delete image_view_; 6940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) image_view_ = NULL; 6950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 6960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 6970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(bottom_view_); 6980de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_EQ(this, bottom_view_->parent()); 6990de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 7000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // TODO(dewittj): Detect a compatible update and use the existing image view. 7010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!notification.image().IsEmpty()) { 7020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) gfx::Size image_size(kNotificationPreferredImageWidth, 7030de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) kNotificationPreferredImageHeight); 7040de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) image_view_ = MakeNotificationImage(notification.image(), image_size); 70546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bottom_view_->AddChildViewAt(image_view_, 0); 7060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 7070de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 7080de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 7090de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateActionButtonViews( 7100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const Notification& notification) { 711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<ButtonInfo> buttons = notification.buttons(); 712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool new_buttons = action_buttons_.size() != buttons.size(); 7130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_buttons || buttons.size() == 0) { 715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // STLDeleteElements also clears the container. 716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) STLDeleteElements(&separators_); 717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) STLDeleteElements(&action_buttons_); 718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 7190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 7200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK(bottom_view_); 7210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) DCHECK_EQ(this, bottom_view_->parent()); 7220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 7230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) for (size_t i = 0; i < buttons.size(); ++i) { 7240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) ButtonInfo button_info = buttons[i]; 725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_buttons) { 726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) views::View* separator = new views::ImageView(); 727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) separator->SetBorder(MakeSeparatorBorder(1, 0, kButtonSeparatorColor)); 728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) separators_.push_back(separator); 729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bottom_view_->AddChildView(separator); 730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NotificationButton* button = new NotificationButton(this); 731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->SetTitle(button_info.title); 732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->SetIcon(button_info.icon.AsImageSkia()); 733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) action_buttons_.push_back(button); 734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bottom_view_->AddChildView(button); 735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) action_buttons_[i]->SetTitle(button_info.title); 737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) action_buttons_[i]->SetIcon(button_info.icon.AsImageSkia()); 738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) action_buttons_[i]->SchedulePaint(); 739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) action_buttons_[i]->Layout(); 740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_buttons) { 744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Layout(); 745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) views::Widget* widget = GetWidget(); 746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (widget != NULL) { 747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget->SetSize(widget->GetContentsView()->GetPreferredSize()); 748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetWidget()->SynthesizeMouseMoveEvent(); 749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 7500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 7510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 7520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int NotificationView::GetMessageLineLimit(int title_lines, int width) const { 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Image notifications require that the image must be kept flush against 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // their icons, but we can allow more text if no image. 756010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int effective_title_lines = std::max(0, title_lines - 1); 757010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int line_reduction_from_title = (image_view_ ? 1 : 2) * effective_title_lines; 758010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!image_view_) { 759010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Title lines are counted as twice as big as message lines for the purpose 760010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // of this calculation. 761010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The effect from the title reduction here should be: 762010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // * 0 title lines: 5 max lines message. 763010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // * 1 title line: 5 max lines message. 764010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // * 2 title lines: 3 max lines message. 765010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return std::max( 766010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 767010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) message_center::kMessageExpandedLineLimit - line_reduction_from_title); 768010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int message_line_limit = message_center::kMessageCollapsedLineLimit; 771f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 772f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Subtract any lines taken by the context message. 773f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (context_message_view_) { 774f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) message_line_limit -= context_message_view_->GetLinesForWidthAndLimit( 775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) width, 776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) message_center::kContextMessageLineLimit); 777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 779010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The effect from the title reduction here should be: 780010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // * 0 title lines: 2 max lines message + context message. 781010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // * 1 title line: 2 max lines message + context message. 782010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // * 2 title lines: 1 max lines message + context message. 783010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) message_line_limit = 784010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::max(0, message_line_limit - line_reduction_from_title); 785010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 786f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return message_line_limit; 787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 789cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int NotificationView::GetMessageHeight(int width, int limit) const { 790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return message_view_ ? 791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_view_->GetSizeForWidthAndLines(width, limit).height() : 0; 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace message_center 795