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"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ui_resources.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "grit/ui_strings.h"
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/base/cursor/cursor.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/layout.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/canvas.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "ui/gfx/skia_util.h"
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/text_elider.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/message_center.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_types.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/views/bounded_label.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/constants.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/message_center_controller.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/notification_button.h"
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/message_center/views/padded_button.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/views/proportional_image_view.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h"
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/background.h"
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/border.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/button/image_button.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/image_view.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/label.h"
37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "ui/views/controls/progress_bar.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/layout/box_layout.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/layout/fill_layout.h"
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/native_cursor.h"
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/painter.h"
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/widget/widget.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Dimensions.
47a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst int kProgressBarWidth = message_center::kNotificationWidth -
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    message_center::kTextLeftPadding - message_center::kTextRightPadding;
492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst int kProgressBarBottomPadding = 0;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeEmptyBorder(int top,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          int left,
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          int bottom,
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          int right) {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return views::Border::CreateEmptyBorder(top, left, bottom, right);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeTextBorder(int padding, int top, int bottom) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Split the padding between the top and the bottom, then add the extra space.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return MakeEmptyBorder(padding / 2 + top,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         message_center::kTextLeftPadding,
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         (padding + 1) / 2 + bottom,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         message_center::kTextRightPadding);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeProgressBarBorder(int top, int bottom) {
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return MakeEmptyBorder(top,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         message_center::kTextLeftPadding,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         bottom,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         message_center::kTextRightPadding);
74a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
76a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// static
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<views::Border> MakeSeparatorBorder(int top,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              int left,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              SkColor color) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return views::Border::CreateSolidSidedBorder(top, left, 0, 0, color);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Return true if and only if the image is null or has alpha.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HasAlpha(gfx::ImageSkia& image, views::Widget* widget) {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine which bitmap to use.
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  float factor = 1.0f;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (widget)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    factor = ui::GetScaleFactorForNativeView(widget->GetNativeView());
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Extract that bitmap's alpha and look for a non-opaque pixel there.
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkBitmap bitmap = image.GetRepresentation(factor).sk_bitmap();
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!bitmap.isNull()) {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SkBitmap alpha;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bitmap.extractAlpha(&alpha);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (int y = 0; y < bitmap.height(); ++y) {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      for (int x = 0; x < bitmap.width(); ++x) {
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (alpha.getColor(x, y) != SK_ColorBLACK) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return true;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If no opaque pixel was found, return false unless the bitmap is empty.
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return bitmap.isNull();
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)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Overridden from views::View:
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetVisible(bool visible) OVERRIDE;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ItemView);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ItemView::ItemView(const message_center::NotificationItem& item) {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      0, 0, message_center::kItemTitleToMessagePadding));
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Label* title = new views::Label(item.title);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  title->set_collapse_when_hidden(true);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  title->SetEnabledColor(message_center::kRegularTextColor);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  title->SetBackgroundColor(message_center::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);
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  message->SetEnabledColor(message_center::kDimTextColor);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message->SetBackgroundColor(message_center::kDimTextBackgroundColor);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddChildView(message);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreferredSizeChanged();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SchedulePaint();
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ItemView::~ItemView() {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ItemView::SetVisible(bool visible) {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::View::SetVisible(visible);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < child_count(); ++i)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child_at(i)->SetVisible(visible);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The NotificationImage is the view representing the area covered by the
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// notification's image, including background and border.  Its size can be
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// specified in advance and images will be scaled to fit including a border if
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// necessary.
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)views::View* MakeNotificationImage(const gfx::Image& image, gfx::Size size) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::View* container = new views::View();
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  container->SetLayoutManager(new views::FillLayout());
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  container->set_background(views::Background::CreateSolidBackground(
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message_center::kImageBackgroundColor));
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size ideal_size(
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message_center::kNotificationPreferredImageWidth,
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message_center::kNotificationPreferredImageHeight);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size scaled_size =
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message_center::GetImageSizeForContainerSize(ideal_size, image.Size());
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::View* proportional_image_view =
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new message_center::ProportionalImageView(image.AsImageSkia(),
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                ideal_size);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This calculation determines that the new image would have the correct
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // height for width.
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ideal_size != scaled_size) {
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    proportional_image_view->SetBorder(views::Border::CreateSolidBorder(
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        message_center::kNotificationImageBorderSize, SK_ColorTRANSPARENT));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  container->AddChildView(proportional_image_view);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return container;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// NotificationProgressBar /////////////////////////////////////////////////////
190a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
191a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass NotificationProgressBar : public views::ProgressBar {
192a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch public:
193a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  NotificationProgressBar();
194a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  virtual ~NotificationProgressBar();
195a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
196a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch private:
197a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // Overriden from View
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE;
1992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
200a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
201a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(NotificationProgressBar);
202a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch};
203a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
204a3f7b4e666c476898878fa745f637129375cd889Ben MurdochNotificationProgressBar::NotificationProgressBar() {
205a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
206a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
207a3f7b4e666c476898878fa745f637129375cd889Ben MurdochNotificationProgressBar::~NotificationProgressBar() {
208a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
209a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NotificationProgressBar::GetPreferredSize() const {
2112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  gfx::Size pref_size(kProgressBarWidth, message_center::kProgressBarThickness);
212a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  gfx::Insets insets = GetInsets();
213a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  pref_size.Enlarge(insets.width(), insets.height());
214a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return pref_size;
215a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
216a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NotificationProgressBar::OnPaint(gfx::Canvas* canvas) {
2182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  gfx::Rect content_bounds = GetContentsBounds();
2192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Draw background.
2212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  SkPath background_path;
2222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  background_path.addRoundRect(gfx::RectToSkRect(content_bounds),
2232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               message_center::kProgressBarCornerRadius,
2242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               message_center::kProgressBarCornerRadius);
2252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  SkPaint background_paint;
2262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  background_paint.setStyle(SkPaint::kFill_Style);
2272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  background_paint.setFlags(SkPaint::kAntiAlias_Flag);
2282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  background_paint.setColor(message_center::kProgressBarBackgroundColor);
2292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  canvas->DrawPath(background_path, background_paint);
2302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Draw slice.
2322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const int slice_width =
2332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      static_cast<int>(content_bounds.width() * GetNormalizedValue() + 0.5);
2342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (slice_width < 1)
2352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
2362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  gfx::Rect slice_bounds = content_bounds;
2382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  slice_bounds.set_width(slice_width);
2392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  SkPath slice_path;
2402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  slice_path.addRoundRect(gfx::RectToSkRect(slice_bounds),
2412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                          message_center::kProgressBarCornerRadius,
2422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                          message_center::kProgressBarCornerRadius);
2432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  SkPaint slice_paint;
2442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  slice_paint.setStyle(SkPaint::kFill_Style);
2452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  slice_paint.setFlags(SkPaint::kAntiAlias_Flag);
2462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  slice_paint.setColor(message_center::kProgressBarSliceColor);
2472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  canvas->DrawPath(slice_path, slice_paint);
2482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
2492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace message_center {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationView ////////////////////////////////////////////////////////////
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationView* NotificationView::Create(MessageCenterController* controller,
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           const Notification& notification,
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           bool top_level) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (notification.type()) {
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case NOTIFICATION_TYPE_BASE_FORMAT:
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case NOTIFICATION_TYPE_IMAGE:
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case NOTIFICATION_TYPE_MULTIPLE:
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case NOTIFICATION_TYPE_SIMPLE:
265a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    case NOTIFICATION_TYPE_PROGRESS:
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the caller asks for an unrecognized kind of view (entirely possible
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // if an application is running on an older version of this code that
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // doesn't have the requested kind of notification template), we'll fall
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // back to a notification instance that will provide at least basic
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // functionality.
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Unable to fulfill request for unrecognized "
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << "notification type " << notification.type() << ". "
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << "Falling back to simple notification type.";
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Currently all roads lead to the generic NotificationView.
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NotificationView* notification_view =
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new NotificationView(controller, notification);
2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Don't create shadows for notification toasts on linux wih aura.
2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (top_level)
2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return notification_view;
2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  notification_view->CreateShadowBorder();
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return notification_view;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateViews(const Notification& notification) {
2930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateTitleView(notification);
2940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateMessageView(notification);
2950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateContextMessageView(notification);
2960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateProgressBarView(notification);
2970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateListItemViews(notification);
2980de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateIconView(notification);
2990de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateImageView(notification);
3000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateActionButtonViews(notification);
3010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
3020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
3030de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::SetAccessibleName(const Notification& notification) {
3040de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  std::vector<base::string16> accessible_lines;
3050de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  accessible_lines.push_back(notification.title());
3060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  accessible_lines.push_back(notification.message());
3070de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  accessible_lines.push_back(notification.context_message());
3080de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  std::vector<NotificationItem> items = notification.items();
3090de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
3100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    accessible_lines.push_back(items[i].title + base::ASCIIToUTF16(" ") +
3110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               items[i].message);
3120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
3130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  set_accessible_name(JoinString(accessible_lines, '\n'));
3140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
3150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationView::NotificationView(MessageCenterController* controller,
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   const Notification& notification)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : MessageView(this,
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  notification.id(),
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  notification.notifier_id(),
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  notification.small_image().AsImageSkia(),
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  notification.display_source()),
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      controller_(controller),
3240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      clickable_(notification.clickable()),
3250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      top_view_(NULL),
3260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      title_view_(NULL),
3270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      message_view_(NULL),
3280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      context_message_view_(NULL),
3290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      icon_view_(NULL),
3300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      bottom_view_(NULL),
3310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      image_view_(NULL),
3320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      progress_bar_view_(NULL) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create the top_view_, which collects into a vertical box all content
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // at the top of the notification (to the right of the icon) except for the
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // close button.
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  top_view_ = new views::View();
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  top_view_->SetLayoutManager(
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  top_view_->SetBorder(
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      MakeEmptyBorder(kTextTopPadding - 8, 0, kTextBottomPadding - 5, 0));
3410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  AddChildView(top_view_);
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create the bottom_view_, which collects into a vertical box all content
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // below the notification icon.
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bottom_view_ = new views::View();
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bottom_view_->SetLayoutManager(
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
3470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  AddChildView(bottom_view_);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateViews(notification);
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Put together the different content and control views. Layering those allows
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // for proper layout logic and it also allows the close button and small
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // image to overlap the content as needed to provide large enough click and
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // touch areas (<http://crbug.com/168822> and <http://crbug.com/168856>).
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddChildView(small_image());
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddChildView(close_button());
3570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  SetAccessibleName(notification);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationView::~NotificationView() {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NotificationView::GetPreferredSize() const {
3640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  int top_width = top_view_->GetPreferredSize().width() +
3650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                  icon_view_->GetPreferredSize().width();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int bottom_width = bottom_view_->GetPreferredSize().width();
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int preferred_width = std::max(top_width, bottom_width) + GetInsets().width();
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Size(preferred_width, GetHeightForWidth(preferred_width));
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int NotificationView::GetHeightForWidth(int width) const {
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Get the height assuming no line limit changes.
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int content_width = width - GetInsets().width();
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int top_height = top_view_->GetHeightForWidth(content_width);
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int bottom_height = bottom_view_->GetHeightForWidth(content_width);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // <http://crbug.com/230448> Fix: Adjust the height when the message_view's
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // line limit would be different for the specified width than it currently is.
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dharcourt): Avoid BoxLayout and directly compute the correct height.
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (message_view_) {
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int title_lines = 0;
382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (title_view_) {
383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      title_lines = title_view_->GetLinesForWidthAndLimit(width,
384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                          kMaxTitleLines);
385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int used_limit = message_view_->GetLineLimit();
387010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int correct_limit = GetMessageLineLimit(title_lines, width);
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (used_limit != correct_limit) {
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      top_height -= GetMessageHeight(content_width, used_limit);
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      top_height += GetMessageHeight(content_width, correct_limit);
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int content_height = std::max(top_height, kIconSize) + bottom_height;
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Adjust the height to make sure there is at least 16px of space below the
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // icon if there is any space there (<http://crbug.com/232966>).
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (content_height > kIconSize)
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    content_height = std::max(content_height,
400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              kIconSize + message_center::kIconBottomPadding);
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return content_height + GetInsets().height();
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationView::Layout() {
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MessageView::Layout();
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Insets insets = GetInsets();
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int content_width = width() - insets.width();
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Before any resizing, set or adjust the number of message lines.
411010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int title_lines = 0;
412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (title_view_) {
413010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    title_lines =
414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        title_view_->GetLinesForWidthAndLimit(width(), kMaxTitleLines);
415010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (message_view_)
417010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    message_view_->SetLineLimit(GetMessageLineLimit(title_lines, width()));
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top views.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int top_height = top_view_->GetHeightForWidth(content_width);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Icon.
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  icon_view_->SetBounds(insets.left(), insets.top(), kIconSize, kIconSize);
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom views.
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int bottom_y = insets.top() + std::max(top_height, kIconSize);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int bottom_height = bottom_view_->GetHeightForWidth(content_width);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bottom_view_->SetBounds(insets.left(), bottom_y,
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          content_width, bottom_height);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NotificationView::OnFocus() {
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MessageView::OnFocus();
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ScrollRectToVisible(GetLocalBounds());
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotificationView::ScrollRectToVisible(const gfx::Rect& rect) {
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Notification want to show the whole notification when a part of it (like
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a button) gets focused.
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  views::View::ScrollRectToVisible(GetLocalBounds());
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)views::View* NotificationView::GetEventHandlerForRect(const gfx::Rect& rect) {
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(tdanderson): Modify this function to support rect-based event
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // targeting. Using the center point of |rect| preserves this function's
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // expected behavior for the time being.
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point point = rect.CenterPoint();
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
450a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Want to return this for underlying views, otherwise GetCursor is not
451a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // called. But buttons are exceptions, they'll have their own event handlings.
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<views::View*> buttons(action_buttons_.begin(),
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    action_buttons_.end());
454a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  buttons.push_back(close_button());
455a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
456a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  for (size_t i = 0; i < buttons.size(); ++i) {
457a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    gfx::Point point_in_child = point;
458a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ConvertPointToTarget(this, buttons[i], &point_in_child);
459a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (buttons[i]->HitTestPoint(point_in_child))
460a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return buttons[i]->GetEventHandlerForPoint(point_in_child);
461a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
462a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
463a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return this;
464a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
465a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
466a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)gfx::NativeCursor NotificationView::GetCursor(const ui::MouseEvent& event) {
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!clickable_ || !controller_->HasClickedListener(notification_id()))
46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return views::View::GetCursor(event);
46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return views::GetNativeHandCursor();
471a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
472a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::UpdateWithNotification(
4740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
4750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  MessageView::UpdateWithNotification(notification);
4760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
4770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  CreateOrUpdateViews(notification);
4780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  SetAccessibleName(notification);
4790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  Layout();
4800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  SchedulePaint();
4810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
4820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationView::ButtonPressed(views::Button* sender,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const ui::Event& event) {
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Certain operations can cause |this| to be destructed, so copy the members
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // we send to other parts of the code.
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(dewittj): Remove this hack.
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string id(notification_id());
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See if the button pressed was an action button.
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < action_buttons_.size(); ++i) {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sender == action_buttons_[i]) {
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      controller_->ClickOnNotificationButton(id, i);
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Let the superclass handled anything other than action buttons.
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Warning: This may cause the NotificationView itself to be deleted,
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // so don't do anything afterwards.
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MessageView::ButtonPressed(sender, event);
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationView::ClickOnNotification(const std::string& notification_id) {
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  controller_->ClickOnNotification(notification_id);
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationView::RemoveNotification(const std::string& notification_id,
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          bool by_user) {
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  controller_->RemoveNotification(notification_id, by_user);
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateTitleView(
5130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
5140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (notification.title().empty()) {
5150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    if (title_view_) {
5160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      // Deletion will also remove |title_view_| from its parent.
5170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      delete title_view_;
5180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      title_view_ = NULL;
5190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
5200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return;
5210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
5220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(top_view_ != NULL);
5240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  const gfx::FontList& font_list =
5260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      views::Label().font_list().DeriveWithSizeDelta(2);
5270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  int title_character_limit =
5290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter;
5300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!title_view_) {
5320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    int padding = kTitleLineHeight - font_list.GetHeight();
5330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    title_view_ = new BoundedLabel(
5350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        gfx::TruncateString(notification.title(), title_character_limit),
5360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        font_list);
5370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    title_view_->SetLineHeight(kTitleLineHeight);
5380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    title_view_->SetLineLimit(kMaxTitleLines);
5390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    title_view_->SetColors(message_center::kRegularTextColor,
5400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                           kRegularTextBackgroundColor);
5410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    title_view_->SetBorder(MakeTextBorder(padding, 3, 0));
5420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    top_view_->AddChildView(title_view_);
5430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  } else {
5440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    title_view_->SetText(
5450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        gfx::TruncateString(notification.title(), title_character_limit));
5460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
5470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
5480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateMessageView(
5500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
5510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (notification.message().empty()) {
5520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    if (message_view_) {
5530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      // Deletion will also remove |message_view_| from its parent.
5540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      delete message_view_;
5550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      message_view_ = NULL;
5560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
5570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return;
5580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
5590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(top_view_ != NULL);
5610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!message_view_) {
5630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    int padding = kMessageLineHeight - views::Label().font_list().GetHeight();
5640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    message_view_ = new BoundedLabel(
5650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        gfx::TruncateString(notification.message(), kMessageCharacterLimit));
5660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    message_view_->SetLineHeight(kMessageLineHeight);
5670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    message_view_->SetColors(message_center::kRegularTextColor,
5680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kDimTextBackgroundColor);
5690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    message_view_->SetBorder(MakeTextBorder(padding, 4, 0));
5700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    top_view_->AddChildView(message_view_);
5710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  } else {
5720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    message_view_->SetText(
5730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        gfx::TruncateString(notification.message(), kMessageCharacterLimit));
5740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
5750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  message_view_->SetVisible(!notification.items().size());
5770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
5780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateContextMessageView(
5800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
5810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (notification.context_message().empty()) {
5820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    if (context_message_view_) {
5830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      // Deletion will also remove |context_message_view_| from its parent.
5840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      delete context_message_view_;
5850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      context_message_view_ = NULL;
5860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
5870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return;
5880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
5890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(top_view_ != NULL);
5910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!context_message_view_) {
5930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    int padding = kMessageLineHeight - views::Label().font_list().GetHeight();
5940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    context_message_view_ = new BoundedLabel(gfx::TruncateString(
5950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        notification.context_message(), kContextMessageCharacterLimit));
5960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    context_message_view_->SetLineLimit(
5970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        message_center::kContextMessageLineLimit);
5980de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    context_message_view_->SetLineHeight(kMessageLineHeight);
5990de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    context_message_view_->SetColors(message_center::kDimTextColor,
6000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                     kContextTextBackgroundColor);
6010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    context_message_view_->SetBorder(MakeTextBorder(padding, 4, 0));
6020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    top_view_->AddChildView(context_message_view_);
6030de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  } else {
6040de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    context_message_view_->SetText(gfx::TruncateString(
6050de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        notification.context_message(), kContextMessageCharacterLimit));
6060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6070de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
6080de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6090de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateProgressBarView(
6100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
6110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (notification.type() != NOTIFICATION_TYPE_PROGRESS) {
6120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    if (progress_bar_view_) {
6130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      // Deletion will also remove |progress_bar_view_| from its parent.
6140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      delete progress_bar_view_;
6150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      progress_bar_view_ = NULL;
6160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
6170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return;
6180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(top_view_ != NULL);
6210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!progress_bar_view_) {
6230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    progress_bar_view_ = new NotificationProgressBar();
6240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    progress_bar_view_->SetBorder(MakeProgressBarBorder(
6250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        message_center::kProgressBarTopPadding, kProgressBarBottomPadding));
6260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    top_view_->AddChildView(progress_bar_view_);
6270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  progress_bar_view_->SetValue(notification.progress() / 100.0);
6300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  progress_bar_view_->SetVisible(!notification.items().size());
6310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
6320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateListItemViews(
6340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
6350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  for (size_t i = 0; i < item_views_.size(); ++i)
6360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    delete item_views_[i];
6370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  item_views_.clear();
6380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  int padding = kMessageLineHeight - views::Label().font_list().GetHeight();
6400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  std::vector<NotificationItem> items = notification.items();
6410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (items.size() == 0)
6430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return;
6440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(top_view_);
6460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
6470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    ItemView* item_view = new ItemView(items[i]);
6480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    item_view->SetBorder(MakeTextBorder(padding, i ? 0 : 4, 0));
6490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    item_views_.push_back(item_view);
6500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    top_view_->AddChildView(item_view);
6510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
6530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateIconView(
6550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
6560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (icon_view_) {
6570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    delete icon_view_;
6580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view_ = NULL;
6590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // TODO(dewittj): Detect a compatible update and use the existing icon view.
6620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  gfx::ImageSkia icon = notification.icon().AsImageSkia();
6630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (notification.type() == NOTIFICATION_TYPE_SIMPLE &&
6640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      (icon.width() != kIconSize || icon.height() != kIconSize ||
6650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)       HasAlpha(icon, GetWidget()))) {
6660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    views::ImageView* icon_view = new views::ImageView();
6670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view->SetImage(icon);
6680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view->SetImageSize(gfx::Size(kLegacyIconSize, kLegacyIconSize));
6690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view->SetHorizontalAlignment(views::ImageView::CENTER);
6700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view->SetVerticalAlignment(views::ImageView::CENTER);
6710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view_ = icon_view;
6720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  } else {
6730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    icon_view_ =
6740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        new ProportionalImageView(icon, gfx::Size(kIconSize, kIconSize));
6750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  icon_view_->set_background(
6780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      views::Background::CreateSolidBackground(kIconBackgroundColor));
6790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  AddChildView(icon_view_);
6810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
6820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateImageView(
6840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
6850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (image_view_) {
6860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    delete image_view_;
6870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    image_view_ = NULL;
6880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
6890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(bottom_view_);
6910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK_EQ(this, bottom_view_->parent());
6920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
6930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // TODO(dewittj): Detect a compatible update and use the existing image view.
6940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!notification.image().IsEmpty()) {
6950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    gfx::Size image_size(kNotificationPreferredImageWidth,
6960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                         kNotificationPreferredImageHeight);
6970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    image_view_ = MakeNotificationImage(notification.image(), image_size);
69846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bottom_view_->AddChildViewAt(image_view_, 0);
6990de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
7000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
7010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
7020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void NotificationView::CreateOrUpdateActionButtonViews(
7030de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const Notification& notification) {
704cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<ButtonInfo> buttons = notification.buttons();
705cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool new_buttons = action_buttons_.size() != buttons.size();
7060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (new_buttons || buttons.size() == 0) {
708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // STLDeleteElements also clears the container.
709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    STLDeleteElements(&separators_);
710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    STLDeleteElements(&action_buttons_);
711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
7120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
7130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(bottom_view_);
7140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK_EQ(this, bottom_view_->parent());
7150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
7160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  for (size_t i = 0; i < buttons.size(); ++i) {
7170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    ButtonInfo button_info = buttons[i];
718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (new_buttons) {
719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      views::View* separator = new views::ImageView();
720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      separator->SetBorder(MakeSeparatorBorder(1, 0, kButtonSeparatorColor));
721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      separators_.push_back(separator);
722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bottom_view_->AddChildView(separator);
723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NotificationButton* button = new NotificationButton(this);
724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      button->SetTitle(button_info.title);
725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      button->SetIcon(button_info.icon.AsImageSkia());
726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      action_buttons_.push_back(button);
727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bottom_view_->AddChildView(button);
728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      action_buttons_[i]->SetTitle(button_info.title);
730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      action_buttons_[i]->SetIcon(button_info.icon.AsImageSkia());
731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      action_buttons_[i]->SchedulePaint();
732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      action_buttons_[i]->Layout();
733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (new_buttons) {
737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Layout();
738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    views::Widget* widget = GetWidget();
739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (widget != NULL) {
740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      widget->SetSize(widget->GetContentsView()->GetPreferredSize());
741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetWidget()->SynthesizeMouseMoveEvent();
742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
7430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
7440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
7450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int NotificationView::GetMessageLineLimit(int title_lines, int width) const {
7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Image notifications require that the image must be kept flush against
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // their icons, but we can allow more text if no image.
749010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int effective_title_lines = std::max(0, title_lines - 1);
750010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int line_reduction_from_title = (image_view_ ? 1 : 2) * effective_title_lines;
751010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!image_view_) {
752010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Title lines are counted as twice as big as message lines for the purpose
753010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // of this calculation.
754010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // The effect from the title reduction here should be:
755010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //   * 0 title lines: 5 max lines message.
756010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //   * 1 title line:  5 max lines message.
757010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //   * 2 title lines: 3 max lines message.
758010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return std::max(
759010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        0,
760010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        message_center::kMessageExpandedLineLimit - line_reduction_from_title);
761010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
763f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int message_line_limit = message_center::kMessageCollapsedLineLimit;
764f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
765f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Subtract any lines taken by the context message.
766f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (context_message_view_) {
767f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    message_line_limit -= context_message_view_->GetLinesForWidthAndLimit(
768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        width,
769f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        message_center::kContextMessageLineLimit);
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
772010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // The effect from the title reduction here should be:
773010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   * 0 title lines: 2 max lines message + context message.
774010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   * 1 title line:  2 max lines message + context message.
775010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   * 2 title lines: 1 max lines message + context message.
776010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  message_line_limit =
777010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      std::max(0, message_line_limit - line_reduction_from_title);
778010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
779f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return message_line_limit;
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
782cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int NotificationView::GetMessageHeight(int width, int limit) const {
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return message_view_ ?
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         message_view_->GetSizeForWidthAndLines(width, limit).height() : 0;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace message_center
788