| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/message_center/notification_view.h" | 5 #include "ui/message_center/notification_view.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "grit/ui_resources.h" | 9 #include "grit/ui_resources.h" |
| 10 #include "ui/base/accessibility/accessible_view_state.h" | 10 #include "ui/base/accessibility/accessible_view_state.h" |
| 11 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
| 12 #include "ui/base/text/text_elider.h" | 12 #include "ui/base/text/text_elider.h" |
| 13 #include "ui/gfx/canvas.h" |
| 13 #include "ui/gfx/size.h" | 14 #include "ui/gfx/size.h" |
| 14 #include "ui/message_center/message_center_constants.h" | 15 #include "ui/message_center/message_center_constants.h" |
| 15 #include "ui/message_center/message_center_switches.h" | 16 #include "ui/message_center/message_center_switches.h" |
| 16 #include "ui/message_center/message_simple_view.h" | 17 #include "ui/message_center/message_simple_view.h" |
| 17 #include "ui/message_center/notification.h" | 18 #include "ui/message_center/notification.h" |
| 19 #include "ui/message_center/notification_change_delegate.h" |
| 18 #include "ui/message_center/notification_types.h" | 20 #include "ui/message_center/notification_types.h" |
| 19 #include "ui/native_theme/native_theme.h" | 21 #include "ui/native_theme/native_theme.h" |
| 20 #include "ui/views/controls/button/image_button.h" | 22 #include "ui/views/controls/button/image_button.h" |
| 21 #include "ui/views/controls/image_view.h" | 23 #include "ui/views/controls/image_view.h" |
| 22 #include "ui/views/controls/label.h" | 24 #include "ui/views/controls/label.h" |
| 23 #include "ui/views/layout/box_layout.h" | 25 #include "ui/views/layout/box_layout.h" |
| 24 #include "ui/views/layout/fill_layout.h" | 26 #include "ui/views/layout/fill_layout.h" |
| 25 #include "ui/views/layout/grid_layout.h" | 27 #include "ui/views/layout/grid_layout.h" |
| 26 | 28 |
| 27 namespace { | 29 namespace { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 message->SetBackgroundColor(kMessageBackgroundColor); | 90 message->SetBackgroundColor(kMessageBackgroundColor); |
| 89 AddChildView(message); | 91 AddChildView(message); |
| 90 | 92 |
| 91 PreferredSizeChanged(); | 93 PreferredSizeChanged(); |
| 92 SchedulePaint(); | 94 SchedulePaint(); |
| 93 } | 95 } |
| 94 | 96 |
| 95 ItemView::~ItemView() { | 97 ItemView::~ItemView() { |
| 96 } | 98 } |
| 97 | 99 |
| 98 // ProportionalImageViews match their heights to their widths to preserve the | 100 // ProportionalImageViews center their images to preserve their proportion. |
| 99 // proportions of their images. | 101 // Note that for this subclass of views::ImageView GetImageBounds() will return |
| 102 // potentially incorrect values (this can't be fixed because GetImageBounds() |
| 103 // is not virtual) and horizontal and vertical alignments will be ignored. |
| 100 class ProportionalImageView : public views::ImageView { | 104 class ProportionalImageView : public views::ImageView { |
| 101 public: | 105 public: |
| 102 ProportionalImageView(); | 106 ProportionalImageView(); |
| 103 virtual ~ProportionalImageView(); | 107 virtual ~ProportionalImageView(); |
| 104 | 108 |
| 105 // Overridden from views::View. | 109 // Overridden from views::View: |
| 106 virtual int GetHeightForWidth(int width) OVERRIDE; | 110 virtual int GetHeightForWidth(int width) OVERRIDE; |
| 111 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; |
| 107 | 112 |
| 108 private: | 113 private: |
| 114 gfx::Size GetImageSizeForWidth(int width); |
| 115 |
| 109 DISALLOW_COPY_AND_ASSIGN(ProportionalImageView); | 116 DISALLOW_COPY_AND_ASSIGN(ProportionalImageView); |
| 110 }; | 117 }; |
| 111 | 118 |
| 112 ProportionalImageView::ProportionalImageView() { | 119 ProportionalImageView::ProportionalImageView() { |
| 113 } | 120 } |
| 114 | 121 |
| 115 ProportionalImageView::~ProportionalImageView() { | 122 ProportionalImageView::~ProportionalImageView() { |
| 116 } | 123 } |
| 117 | 124 |
| 118 int ProportionalImageView::GetHeightForWidth(int width) { | 125 int ProportionalImageView::GetHeightForWidth(int width) { |
| 119 int height = 0; | 126 return GetImageSizeForWidth(width).height(); |
| 120 gfx::ImageSkia image = GetImage(); | 127 } |
| 121 if (image.width() > 0 && image.height() > 0) { | 128 |
| 122 double proportion = image.height() / (double) image.width(); | 129 void ProportionalImageView::OnPaint(gfx::Canvas* canvas) { |
| 123 height = 0.5 + width * proportion; | 130 View::OnPaint(canvas); |
| 124 if (height > message_center::kNotificationMaximumImageHeight) { | 131 |
| 125 height = message_center::kNotificationMaximumImageHeight; | 132 gfx::Size draw_size(GetImageSizeForWidth(width())); |
| 126 width = 0.5 + height / proportion; | 133 if (!draw_size.IsEmpty()) { |
| 134 int x = (width() - draw_size.width()) / 2; |
| 135 int y = (height() - draw_size.height()) / 2; |
| 136 |
| 137 gfx::Size image_size(GetImage().size()); |
| 138 if (image_size == draw_size) { |
| 139 canvas->DrawImageInt(GetImage(), x, y); |
| 140 } else { |
| 141 // Resize case |
| 142 SkPaint paint; |
| 143 paint.setFilterBitmap(true); |
| 144 canvas->DrawImageInt(GetImage(), 0, 0, |
| 145 image_size.width(), image_size.height(), x, y, |
| 146 draw_size.width(), draw_size.height(), true, paint); |
| 127 } | 147 } |
| 128 SetImageSize(gfx::Size(width, height)); | |
| 129 } | 148 } |
| 130 return height; | 149 } |
| 150 |
| 151 gfx::Size ProportionalImageView::GetImageSizeForWidth(int width) { |
| 152 gfx::Size size(GetImage().size()); |
| 153 if (width > 0 && !size.IsEmpty()) { |
| 154 double proportion = size.height() / (double) size.width(); |
| 155 size.SetSize(width, std::max(0.5 + width * proportion, 1.0)); |
| 156 if (size.height() > message_center::kNotificationMaximumImageHeight) { |
| 157 int height = message_center::kNotificationMaximumImageHeight; |
| 158 size.SetSize(std::max(0.5 + height / proportion, 1.0), height); |
| 159 } |
| 160 } |
| 161 return size; |
| 131 } | 162 } |
| 132 | 163 |
| 133 // NotificationsButtons render the action buttons of notifications. | 164 // NotificationsButtons render the action buttons of notifications. |
| 134 class NotificationButton : public views::CustomButton { | 165 class NotificationButton : public views::CustomButton { |
| 135 public: | 166 public: |
| 136 NotificationButton(views::ButtonListener* listener); | 167 NotificationButton(views::ButtonListener* listener); |
| 137 virtual ~NotificationButton(); | 168 virtual ~NotificationButton(); |
| 138 | 169 |
| 139 void SetIcon(const gfx::ImageSkia& icon); | 170 void SetIcon(const gfx::ImageSkia& icon); |
| 140 void SetTitle(const string16& title); | 171 void SetTitle(const string16& title); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 title_->set_border(MakePadding(kActionButtonTitleTopPadding, 0, 0, 0)); | 219 title_->set_border(MakePadding(kActionButtonTitleTopPadding, 0, 0, 0)); |
| 189 AddChildView(title_); | 220 AddChildView(title_); |
| 190 } | 221 } |
| 191 } | 222 } |
| 192 | 223 |
| 193 } // namespace | 224 } // namespace |
| 194 | 225 |
| 195 namespace message_center { | 226 namespace message_center { |
| 196 | 227 |
| 197 // static | 228 // static |
| 198 MessageView* NotificationView::Create( | 229 MessageView* NotificationView::Create(const Notification& notification, |
| 199 const Notification& notification, | 230 NotificationChangeDelegate* delegate, |
| 200 NotificationList::Delegate* list_delegate) { | 231 bool expanded) { |
| 201 // For the time being, use MessageSimpleView for simple notifications unless | 232 // For the time being, use MessageSimpleView for simple notifications unless |
| 202 // one of the use-the-new-style flags are set. This preserves the appearance | 233 // one of the use-the-new-style flags are set. This preserves the appearance |
| 203 // of notifications created by existing code that uses webkitNotifications. | 234 // of notifications created by existing code that uses webkitNotifications. |
| 204 if (notification.type() == NOTIFICATION_TYPE_SIMPLE && | 235 if (notification.type() == NOTIFICATION_TYPE_SIMPLE && |
| 205 !CommandLine::ForCurrentProcess()->HasSwitch( | 236 !CommandLine::ForCurrentProcess()->HasSwitch( |
| 206 message_center::switches::kEnableRichNotifications) && | 237 message_center::switches::kEnableRichNotifications) && |
| 207 !CommandLine::ForCurrentProcess()->HasSwitch( | 238 !CommandLine::ForCurrentProcess()->HasSwitch( |
| 208 message_center::switches::kEnableNewSimpleNotifications)) { | 239 message_center::switches::kEnableNewSimpleNotifications)) { |
| 209 return new MessageSimpleView(list_delegate, notification); | 240 return new MessageSimpleView(notification, delegate); |
| 210 } | 241 } |
| 211 | 242 |
| 212 switch (notification.type()) { | 243 switch (notification.type()) { |
| 213 case NOTIFICATION_TYPE_BASE_FORMAT: | 244 case NOTIFICATION_TYPE_BASE_FORMAT: |
| 214 case NOTIFICATION_TYPE_IMAGE: | 245 case NOTIFICATION_TYPE_IMAGE: |
| 215 case NOTIFICATION_TYPE_MULTIPLE: | 246 case NOTIFICATION_TYPE_MULTIPLE: |
| 216 case NOTIFICATION_TYPE_SIMPLE: | 247 case NOTIFICATION_TYPE_SIMPLE: |
| 217 break; | 248 break; |
| 218 default: | 249 default: |
| 219 // If the caller asks for an unrecognized kind of view (entirely possible | 250 // If the caller asks for an unrecognized kind of view (entirely possible |
| 220 // if an application is running on an older version of this code that | 251 // if an application is running on an older version of this code that |
| 221 // doesn't have the requested kind of notification template), we'll fall | 252 // doesn't have the requested kind of notification template), we'll fall |
| 222 // back to a notification instance that will provide at least basic | 253 // back to a notification instance that will provide at least basic |
| 223 // functionality. | 254 // functionality. |
| 224 LOG(WARNING) << "Unable to fulfill request for unrecognized " | 255 LOG(WARNING) << "Unable to fulfill request for unrecognized " |
| 225 << "notification type " << notification.type() << ". " | 256 << "notification type " << notification.type() << ". " |
| 226 << "Falling back to simple notification type."; | 257 << "Falling back to simple notification type."; |
| 227 } | 258 } |
| 228 | 259 |
| 229 // Currently all roads lead to the generic NotificationView. | 260 // Currently all roads lead to the generic NotificationView. |
| 230 return new NotificationView(list_delegate, notification); | 261 return new NotificationView(notification, delegate, expanded); |
| 231 } | 262 } |
| 232 | 263 |
| 233 NotificationView::NotificationView(NotificationList::Delegate* list_delegate, | 264 NotificationView::NotificationView(const Notification& notification, |
| 234 const Notification& notification) | 265 NotificationChangeDelegate* delegate, |
| 235 : MessageView(list_delegate, notification) { | 266 bool expanded) |
| 236 // This view is composed of two layers: The first layer has the notification | 267 : MessageView(notification, delegate, expanded), |
| 237 // content (text, images, action buttons, ...). This is overlaid by a second | 268 content_view_(NULL), |
| 238 // layer that has the notification close button and will later also have the | 269 icon_view_(NULL) { |
| 239 // expand button. This allows the close and expand buttons to overlap the | 270 AddChildViews(notification); |
| 240 // content as needed to provide a large enough click area | |
| 241 // (<http://crbug.com/168822> and touch area <http://crbug.com/168856>). | |
| 242 AddChildView(MakeContentView(notification)); | |
| 243 AddChildView(close_button()); | |
| 244 } | 271 } |
| 245 | 272 |
| 246 NotificationView::~NotificationView() { | 273 NotificationView::~NotificationView() { |
| 247 } | 274 } |
| 248 | 275 |
| 249 void NotificationView::Layout() { | 276 void NotificationView::Layout() { |
| 250 if (content_view_) { | 277 gfx::Rect content_bounds(GetLocalBounds()); |
| 251 gfx::Rect contents_bounds = GetContentsBounds(); | 278 content_bounds.Inset(GetInsets()); |
| 252 content_view_->SetBoundsRect(contents_bounds); | 279 content_view_->SetBoundsRect(content_bounds); |
| 253 if (close_button()) { | 280 |
| 254 gfx::Size size(close_button()->GetPreferredSize()); | 281 gfx::Size close_size(close_button()->GetPreferredSize()); |
| 255 close_button()->SetBounds(contents_bounds.right() - size.width(), 0, | 282 close_button()->SetBounds(content_bounds.right() - close_size.width(), |
| 256 size.width(), size.height()); | 283 content_bounds.y(), |
| 257 } | 284 close_size.width(), |
| 258 } | 285 close_size.height()); |
| 286 |
| 287 gfx::Rect icon_bounds(content_bounds.origin(), icon_view_->size()); |
| 288 gfx::Size expand_size(expand_button()->GetPreferredSize()); |
| 289 expand_button()->SetBounds(content_bounds.right() - expand_size.width(), |
| 290 icon_bounds.bottom() - expand_size.height(), |
| 291 expand_size.width(), |
| 292 expand_size.height()); |
| 259 } | 293 } |
| 260 | 294 |
| 261 gfx::Size NotificationView::GetPreferredSize() { | 295 gfx::Size NotificationView::GetPreferredSize() { |
| 262 if (!content_view_) | 296 gfx::Size size; |
| 263 return gfx::Size(); | 297 if (content_view_) { |
| 264 gfx::Size size = content_view_->GetPreferredSize(); | 298 size = content_view_->GetPreferredSize(); |
| 265 if (border()) { | 299 if (border()) { |
| 266 gfx::Insets border_insets = border()->GetInsets(); | 300 gfx::Insets insets = border()->GetInsets(); |
| 267 size.Enlarge(border_insets.width(), border_insets.height()); | 301 size.Enlarge(insets.width(), insets.height()); |
| 302 } |
| 268 } | 303 } |
| 269 return size; | 304 return size; |
| 270 } | 305 } |
| 271 | 306 |
| 307 void NotificationView::Update(const Notification& notification) { |
| 308 MessageView::Update(notification); |
| 309 content_view_ = NULL; |
| 310 icon_view_ = NULL; |
| 311 action_buttons_.clear(); |
| 312 RemoveAllChildViews(true); |
| 313 AddChildViews(notification); |
| 314 PreferredSizeChanged(); |
| 315 SchedulePaint(); |
| 316 } |
| 317 |
| 272 void NotificationView::ButtonPressed(views::Button* sender, | 318 void NotificationView::ButtonPressed(views::Button* sender, |
| 273 const ui::Event& event) { | 319 const ui::Event& event) { |
| 274 for (size_t i = 0; i < action_buttons_.size(); ++i) { | 320 for (size_t i = 0; i < action_buttons_.size(); ++i) { |
| 275 if (action_buttons_[i] == sender) { | 321 if (sender == action_buttons_[i]) { |
| 276 list_delegate()->OnButtonClicked(notification_id(), i); | 322 delegate()->OnButtonClicked(notification_id(), i); |
| 277 return; | 323 return; |
| 278 } | 324 } |
| 279 } | 325 } |
| 280 MessageView::ButtonPressed(sender, event); | 326 MessageView::ButtonPressed(sender, event); |
| 281 } | 327 } |
| 282 | 328 |
| 283 views::View* NotificationView::MakeContentView( | 329 void NotificationView::AddChildViews(const Notification& notification) { |
| 284 const Notification& notification) { | 330 // Child views are in two layers: The first layer has the notification content |
| 331 // (text, images, action buttons, ...). This is overlaid by a second layer |
| 332 // that has the notification close and expand buttons. This allows the close |
| 333 // and expand buttons to overlap the content as needed to provide large enough |
| 334 // click and touch areas (<http://crbug.com/168822> and |
| 335 // <http://crbug.com/168856>). |
| 336 AddContentView(notification); |
| 337 AddChildView(close_button()); |
| 338 if (!is_expanded()) { |
| 339 AddChildView(expand_button()); |
| 340 } |
| 341 } |
| 342 |
| 343 void NotificationView::AddContentView(const Notification& notification) { |
| 285 content_view_ = new views::View(); | 344 content_view_ = new views::View(); |
| 286 content_view_->set_background( | 345 content_view_->set_background( |
| 287 views::Background::CreateSolidBackground(kBackgroundColor)); | 346 views::Background::CreateSolidBackground(kBackgroundColor)); |
| 288 | 347 |
| 289 // The top part of the content view is composed of an icon view on the left | 348 // The top part of the content view is composed of an icon view on the left |
| 290 // and a certain number of text views on the right (title and message or list | 349 // and a certain number of text views on the right (title and message or list |
| 291 // items), followed by a padding view. Laying out the icon view will require | 350 // items), followed by a padding view. Laying out the icon view will require |
| 292 // information about the text views, so these are created first and collected | 351 // information about the text views, so these are created first and collected |
| 293 // in this vector. | 352 // in this vector. |
| 294 std::vector<views::View*> texts; | 353 std::vector<views::View*> text_views; |
| 295 | 354 |
| 296 // Title if it exists. | 355 // Title if it exists. |
| 297 if (!notification.title().empty()) { | 356 if (!notification.title().empty()) { |
| 298 views::Label* title = new views::Label(notification.title()); | 357 views::Label* title = new views::Label(notification.title()); |
| 299 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 358 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 300 title->SetElideBehavior(views::Label::ELIDE_AT_END); | 359 if (is_expanded()) |
| 360 title->SetMultiLine(true); |
| 361 else |
| 362 title->SetElideBehavior(views::Label::ELIDE_AT_END); |
| 301 title->SetFont(title->font().DeriveFont(4)); | 363 title->SetFont(title->font().DeriveFont(4)); |
| 302 title->SetEnabledColor(kTitleColor); | 364 title->SetEnabledColor(kTitleColor); |
| 303 title->SetBackgroundColor(kTitleBackgroundColor); | 365 title->SetBackgroundColor(kTitleBackgroundColor); |
| 304 title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextRightPadding)); | 366 title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextRightPadding)); |
| 305 texts.push_back(title); | 367 text_views.push_back(title); |
| 368 } |
| 369 |
| 370 // List notification items up to a maximum if appropriate. |
| 371 size_t items = notification.items().size(); |
| 372 items = std::min(items, is_expanded() ? kNotificationMaximumItems : 0ul); |
| 373 for (size_t i = 0; i < items; ++i) { |
| 374 ItemView* item = new ItemView(notification.items()[i]); |
| 375 item->set_border(MakePadding(0, 0, 4, kTextRightPadding)); |
| 376 text_views.push_back(item); |
| 306 } | 377 } |
| 307 | 378 |
| 308 // Message if appropriate. | 379 // Message if appropriate. |
| 309 if (notification.items().size() == 0 && | 380 if (items == 0ul && !notification.message().empty()) { |
| 310 !notification.message().empty()) { | |
| 311 views::Label* message = new views::Label(notification.message()); | 381 views::Label* message = new views::Label(notification.message()); |
| 312 message->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 382 message->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 313 message->SetMultiLine(true); | 383 if (is_expanded()) |
| 384 message->SetMultiLine(true); |
| 385 else |
| 386 message->SetElideBehavior(views::Label::ELIDE_AT_END); |
| 314 message->SetEnabledColor(kMessageColor); | 387 message->SetEnabledColor(kMessageColor); |
| 315 message->SetBackgroundColor(kMessageBackgroundColor); | 388 message->SetBackgroundColor(kMessageBackgroundColor); |
| 316 message->set_border(MakePadding(0, 0, 3, kTextRightPadding)); | 389 message->set_border(MakePadding(0, 0, 3, kTextRightPadding)); |
| 317 texts.push_back(message); | 390 text_views.push_back(message); |
| 318 } | |
| 319 | |
| 320 // List notification items up to a maximum. | |
| 321 int items = std::min(notification.items().size(), | |
| 322 kNotificationMaximumItems); | |
| 323 for (int i = 0; i < items; ++i) { | |
| 324 ItemView* item = new ItemView(notification.items()[i]); | |
| 325 item->set_border(MakePadding(0, 0, 4, kTextRightPadding)); | |
| 326 texts.push_back(item); | |
| 327 } | 391 } |
| 328 | 392 |
| 329 // Set up the content view with a fixed-width icon column on the left and a | 393 // Set up the content view with a fixed-width icon column on the left and a |
| 330 // text column on the right that consumes the remaining space. To minimize the | 394 // text column on the right that consumes the remaining space. To minimize the |
| 331 // number of columns and simplify column spanning, padding is applied to each | 395 // number of columns and simplify column spanning, padding is applied to each |
| 332 // view within columns instead of through padding columns. | 396 // view within columns instead of through padding columns. |
| 333 views::GridLayout* layout = new views::GridLayout(content_view_); | 397 views::GridLayout* layout = new views::GridLayout(content_view_); |
| 334 content_view_->SetLayoutManager(layout); | 398 content_view_->SetLayoutManager(layout); |
| 335 views::ColumnSet* columns = layout->AddColumnSet(0); | 399 views::ColumnSet* columns = layout->AddColumnSet(0); |
| 336 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, | 400 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
| 337 0, views::GridLayout::FIXED, | 401 0, views::GridLayout::FIXED, |
| 338 kIconColumnWidth + kIconToTextPadding, | 402 kIconColumnWidth + kIconToTextPadding, |
| 339 kIconColumnWidth + kIconToTextPadding); | 403 kIconColumnWidth + kIconToTextPadding); |
| 340 // Padding + icon + padding. | 404 // Padding + icon + padding. |
| 341 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, | 405 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
| 342 100, views::GridLayout::USE_PREF, 0, 0); | 406 100, views::GridLayout::USE_PREF, 0, 0); |
| 343 // Text + padding. | 407 // Text + padding. |
| 344 | 408 |
| 345 // Create the first row and its icon view, which spans all the text views | 409 // Create the first row and its icon view, which spans all the text views |
| 346 // to its right as well as the padding view below them. | 410 // to its right as well as the padding view below them. |
| 347 layout->StartRow(0, 0); | 411 layout->StartRow(0, 0); |
| 348 views::ImageView* icon = new views::ImageView(); | 412 icon_view_ = new views::ImageView(); |
| 349 icon->SetImageSize(gfx::Size(message_center::kNotificationIconSize, | 413 icon_view_->SetImageSize(gfx::Size(message_center::kNotificationIconSize, |
| 350 message_center::kNotificationIconSize)); | 414 message_center::kNotificationIconSize)); |
| 351 icon->SetImage(notification.primary_icon()); | 415 icon_view_->SetImage(notification.icon()); |
| 352 icon->SetHorizontalAlignment(views::ImageView::LEADING); | 416 icon_view_->SetHorizontalAlignment(views::ImageView::LEADING); |
| 353 icon->SetVerticalAlignment(views::ImageView::LEADING); | 417 icon_view_->SetVerticalAlignment(views::ImageView::LEADING); |
| 354 icon->set_border(MakePadding(0, 0, 0, kIconToTextPadding)); | 418 icon_view_->set_border(MakePadding(0, 0, 0, kIconToTextPadding)); |
| 355 layout->AddView(icon, 1, texts.size() + 1); | 419 layout->AddView(icon_view_, 1, text_views.size() + 1); |
| 356 | 420 |
| 357 // Add the text views, creating rows for them if necessary. | 421 // Add the text views, creating rows for them if necessary. |
| 358 for (size_t i = 0; i < texts.size(); ++i) { | 422 for (size_t i = 0; i < text_views.size(); ++i) { |
| 359 if (i > 0) { | 423 if (i > 0) { |
| 360 layout->StartRow(0, 0); | 424 layout->StartRow(0, 0); |
| 361 layout->SkipColumns(1); | 425 layout->SkipColumns(1); |
| 362 } | 426 } |
| 363 layout->AddView(texts[i]); | 427 layout->AddView(text_views[i]); |
| 364 } | 428 } |
| 365 | 429 |
| 366 // Add a text padding row if necessary. This adds some space between the last | 430 // Add a text padding row if necessary. This adds some space between the last |
| 367 // line of text and anything below it but it also ensures views above it are | 431 // line of text and anything below it but it also ensures views above it are |
| 368 // top-justified by expanding vertically to take up any extra space. | 432 // top-justified by expanding vertically to take up any extra space. |
| 369 if (texts.size() == 0) { | 433 if (text_views.size() == 0) { |
| 370 layout->SkipColumns(1); | 434 layout->SkipColumns(1); |
| 371 } else { | 435 } else { |
| 372 layout->StartRow(100, 0); | 436 layout->StartRow(100, 0); |
| 373 layout->SkipColumns(1); | 437 layout->SkipColumns(1); |
| 374 views::View* padding = new views::ImageView(); | 438 views::View* padding = new views::ImageView(); |
| 375 padding->set_border(MakePadding(kTextBottomPadding, 1, 0, 0)); | 439 padding->set_border(MakePadding(kTextBottomPadding, 1, 0, 0)); |
| 376 layout->AddView(padding); | 440 layout->AddView(padding); |
| 377 } | 441 } |
| 378 | 442 |
| 379 // Add an image row if appropriate. | 443 // Add an image row if appropriate. |
| 380 if (!notification.image().isNull()) { | 444 if (is_expanded() && !notification.image().isNull()) { |
| 381 layout->StartRow(0, 0); | 445 layout->StartRow(0, 0); |
| 382 views::ImageView* image = new ProportionalImageView(); | 446 ProportionalImageView* image_view = new ProportionalImageView(); |
| 383 image->SetImageSize(notification.image().size()); | 447 image_view->SetImage(notification.image()); |
| 384 image->SetImage(notification.image()); | 448 layout->AddView(image_view, 2, 1); |
| 385 image->SetHorizontalAlignment(views::ImageView::CENTER); | |
| 386 image->SetVerticalAlignment(views::ImageView::LEADING); | |
| 387 layout->AddView(image, 2, 1); | |
| 388 } | 449 } |
| 389 | 450 |
| 390 // Add action button rows. | 451 // Add action button rows. |
| 391 for (size_t i = 0; i < notification.buttons().size(); ++i) { | 452 for (size_t i = 0; i < notification.buttons().size(); ++i) { |
| 392 views::View* separator = new views::View(); | 453 views::View* separator = new views::View(); |
| 393 separator->set_background(MakeBackground(kButtonSeparatorColor)); | 454 separator->set_background(MakeBackground(kButtonSeparatorColor)); |
| 394 layout->StartRow(0, 0); | 455 layout->StartRow(0, 0); |
| 395 layout->AddView(separator, 2, 1, | 456 layout->AddView(separator, 2, 1, |
| 396 views::GridLayout::FILL, views::GridLayout::FILL, 0, 1); | 457 views::GridLayout::FILL, views::GridLayout::FILL, 0, 1); |
| 397 NotificationButton* button = new NotificationButton(this); | 458 NotificationButton* button = new NotificationButton(this); |
| 398 ButtonInfo button_info = notification.buttons()[i]; | 459 ButtonInfo button_info = notification.buttons()[i]; |
| 399 button->SetTitle(button_info.title); | 460 button->SetTitle(button_info.title); |
| 400 button->SetIcon(button_info.icon); | 461 button->SetIcon(button_info.icon); |
| 401 action_buttons_.push_back(button); | 462 action_buttons_.push_back(button); |
| 402 layout->StartRow(0, 0); | 463 layout->StartRow(0, 0); |
| 403 layout->AddView(button, 2, 1, | 464 layout->AddView(button, 2, 1, |
| 404 views::GridLayout::FILL, views::GridLayout::FILL, 0, 40); | 465 views::GridLayout::FILL, views::GridLayout::FILL, 0, 40); |
| 405 } | 466 } |
| 406 | 467 |
| 407 return content_view_; | 468 AddChildView(content_view_); |
| 408 } | 469 } |
| 409 | 470 |
| 410 } // namespace message_center | 471 } // namespace message_center |
| OLD | NEW |