| 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/views/notification_view.h" | 5 #include "ui/message_center/views/notification_view.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 #if defined(OS_WIN) | 53 #if defined(OS_WIN) |
| 54 #include "ui/base/win/shell.h" | 54 #include "ui/base/win/shell.h" |
| 55 #endif | 55 #endif |
| 56 | 56 |
| 57 namespace { | 57 namespace { |
| 58 | 58 |
| 59 // Dimensions. | 59 // Dimensions. |
| 60 const int kProgressBarBottomPadding = 0; | 60 const int kProgressBarBottomPadding = 0; |
| 61 | 61 |
| 62 const int kCloseIconTopPadding = 5; |
| 63 const int kCloseIconRightPadding = 5; |
| 64 |
| 62 // static | 65 // static |
| 63 scoped_ptr<views::Border> MakeEmptyBorder(int top, | 66 scoped_ptr<views::Border> MakeEmptyBorder(int top, |
| 64 int left, | 67 int left, |
| 65 int bottom, | 68 int bottom, |
| 66 int right) { | 69 int right) { |
| 67 return views::Border::CreateEmptyBorder(top, left, bottom, right); | 70 return views::Border::CreateEmptyBorder(top, left, bottom, right); |
| 68 } | 71 } |
| 69 | 72 |
| 70 // static | 73 // static |
| 71 scoped_ptr<views::Border> MakeTextBorder(int padding, int top, int bottom) { | 74 scoped_ptr<views::Border> MakeTextBorder(int padding, int top, int bottom) { |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 // targeting. Using the center point of |rect| preserves this function's | 224 // targeting. Using the center point of |rect| preserves this function's |
| 222 // expected behavior for the time being. | 225 // expected behavior for the time being. |
| 223 gfx::Point point = rect.CenterPoint(); | 226 gfx::Point point = rect.CenterPoint(); |
| 224 | 227 |
| 225 // Want to return this for underlying views, otherwise GetCursor is not | 228 // Want to return this for underlying views, otherwise GetCursor is not |
| 226 // called. But buttons are exceptions, they'll have their own event handlings. | 229 // called. But buttons are exceptions, they'll have their own event handlings. |
| 227 std::vector<views::View*> buttons(action_buttons_.begin(), | 230 std::vector<views::View*> buttons(action_buttons_.begin(), |
| 228 action_buttons_.end()); | 231 action_buttons_.end()); |
| 229 if (settings_button_view_) | 232 if (settings_button_view_) |
| 230 buttons.push_back(settings_button_view_); | 233 buttons.push_back(settings_button_view_); |
| 231 buttons.push_back(close_button()); | 234 if (close_button_) |
| 235 buttons.push_back(close_button_.get()); |
| 232 | 236 |
| 233 for (size_t i = 0; i < buttons.size(); ++i) { | 237 for (size_t i = 0; i < buttons.size(); ++i) { |
| 234 gfx::Point point_in_child = point; | 238 gfx::Point point_in_child = point; |
| 235 ConvertPointToTarget(this, buttons[i], &point_in_child); | 239 ConvertPointToTarget(this, buttons[i], &point_in_child); |
| 236 if (buttons[i]->HitTestPoint(point_in_child)) | 240 if (buttons[i]->HitTestPoint(point_in_child)) |
| 237 return buttons[i]->GetEventHandlerForPoint(point_in_child); | 241 return buttons[i]->GetEventHandlerForPoint(point_in_child); |
| 238 } | 242 } |
| 239 | 243 |
| 240 return root; | 244 return root; |
| 241 } | 245 } |
| 242 | 246 |
| 243 void NotificationView::CreateOrUpdateViews(const Notification& notification) { | 247 void NotificationView::CreateOrUpdateViews(const Notification& notification) { |
| 248 CreateOrUpdateCloseButtonView(notification); |
| 244 CreateOrUpdateTitleView(notification); | 249 CreateOrUpdateTitleView(notification); |
| 245 CreateOrUpdateMessageView(notification); | 250 CreateOrUpdateMessageView(notification); |
| 246 CreateOrUpdateProgressBarView(notification); | 251 CreateOrUpdateProgressBarView(notification); |
| 247 CreateOrUpdateListItemViews(notification); | 252 CreateOrUpdateListItemViews(notification); |
| 248 CreateOrUpdateIconView(notification); | 253 CreateOrUpdateIconView(notification); |
| 249 CreateOrUpdateImageView(notification); | 254 CreateOrUpdateImageView(notification); |
| 250 CreateOrUpdateContextMessageView(notification); | 255 CreateOrUpdateContextMessageView(notification); |
| 251 CreateOrUpdateSettingsButtonView(notification); | 256 CreateOrUpdateSettingsButtonView(notification); |
| 252 CreateOrUpdateActionButtonViews(notification); | 257 CreateOrUpdateActionButtonViews(notification); |
| 253 } | 258 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); | 306 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); |
| 302 AddChildView(bottom_view_); | 307 AddChildView(bottom_view_); |
| 303 | 308 |
| 304 CreateOrUpdateViews(notification); | 309 CreateOrUpdateViews(notification); |
| 305 | 310 |
| 306 // Put together the different content and control views. Layering those allows | 311 // Put together the different content and control views. Layering those allows |
| 307 // for proper layout logic and it also allows the close button and small | 312 // for proper layout logic and it also allows the close button and small |
| 308 // image to overlap the content as needed to provide large enough click and | 313 // image to overlap the content as needed to provide large enough click and |
| 309 // touch areas (<http://crbug.com/168822> and <http://crbug.com/168856>). | 314 // touch areas (<http://crbug.com/168822> and <http://crbug.com/168856>). |
| 310 AddChildView(small_image()); | 315 AddChildView(small_image()); |
| 311 AddChildView(close_button()); | |
| 312 SetAccessibleName(notification); | 316 SetAccessibleName(notification); |
| 313 | 317 |
| 314 SetEventTargeter( | 318 SetEventTargeter( |
| 315 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); | 319 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); |
| 316 } | 320 } |
| 317 | 321 |
| 318 NotificationView::~NotificationView() { | 322 NotificationView::~NotificationView() { |
| 319 } | 323 } |
| 320 | 324 |
| 321 gfx::Size NotificationView::GetPreferredSize() const { | 325 gfx::Size NotificationView::GetPreferredSize() const { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 title_lines = | 375 title_lines = |
| 372 title_view_->GetLinesForWidthAndLimit(width(), kMaxTitleLines); | 376 title_view_->GetLinesForWidthAndLimit(width(), kMaxTitleLines); |
| 373 } | 377 } |
| 374 if (message_view_) | 378 if (message_view_) |
| 375 message_view_->SetLineLimit(GetMessageLineLimit(title_lines, width())); | 379 message_view_->SetLineLimit(GetMessageLineLimit(title_lines, width())); |
| 376 | 380 |
| 377 // Top views. | 381 // Top views. |
| 378 int top_height = top_view_->GetHeightForWidth(content_width); | 382 int top_height = top_view_->GetHeightForWidth(content_width); |
| 379 top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height); | 383 top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height); |
| 380 | 384 |
| 385 // Close button. |
| 386 if (close_button_) { |
| 387 gfx::Rect content_bounds = GetContentsBounds(); |
| 388 gfx::Size close_size(close_button_->GetPreferredSize()); |
| 389 gfx::Rect close_rect(content_bounds.right() - close_size.width(), |
| 390 content_bounds.y(), |
| 391 close_size.width(), |
| 392 close_size.height()); |
| 393 close_button_->SetBoundsRect(close_rect); |
| 394 } |
| 395 |
| 381 // Icon. | 396 // Icon. |
| 382 icon_view_->SetBounds(insets.left(), insets.top(), kIconSize, kIconSize); | 397 icon_view_->SetBounds(insets.left(), insets.top(), kIconSize, kIconSize); |
| 383 | 398 |
| 384 // Settings & Bottom views. | 399 // Settings & Bottom views. |
| 385 int bottom_y = insets.top() + std::max(top_height, kIconSize); | 400 int bottom_y = insets.top() + std::max(top_height, kIconSize); |
| 386 int bottom_height = bottom_view_->GetHeightForWidth(content_width); | 401 int bottom_height = bottom_view_->GetHeightForWidth(content_width); |
| 387 | 402 |
| 388 if (settings_button_view_) { | 403 if (settings_button_view_) { |
| 389 gfx::Size settings_size(settings_button_view_->GetPreferredSize()); | 404 gfx::Size settings_size(settings_button_view_->GetPreferredSize()); |
| 390 settings_button_view_->SetBounds(content_width - settings_size.width(), | 405 settings_button_view_->SetBounds(content_width - settings_size.width(), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 } | 453 } |
| 439 | 454 |
| 440 // See if the button pressed was an action button. | 455 // See if the button pressed was an action button. |
| 441 for (size_t i = 0; i < action_buttons_.size(); ++i) { | 456 for (size_t i = 0; i < action_buttons_.size(); ++i) { |
| 442 if (sender == action_buttons_[i]) { | 457 if (sender == action_buttons_[i]) { |
| 443 controller_->ClickOnNotificationButton(id, i); | 458 controller_->ClickOnNotificationButton(id, i); |
| 444 return; | 459 return; |
| 445 } | 460 } |
| 446 } | 461 } |
| 447 | 462 |
| 463 if (close_button_ && sender == close_button_.get()) { |
| 464 controller_->RemoveNotification(notification_id(), true); // By user. |
| 465 } |
| 466 |
| 448 // Let the superclass handle everything else. | 467 // Let the superclass handle everything else. |
| 449 // Warning: This may cause the NotificationView itself to be deleted, | 468 // Warning: This may cause the NotificationView itself to be deleted, |
| 450 // so don't do anything afterwards. | 469 // so don't do anything afterwards. |
| 451 MessageView::ButtonPressed(sender, event); | 470 MessageView::ButtonPressed(sender, event); |
| 452 } | 471 } |
| 453 | 472 |
| 454 void NotificationView::ClickOnNotification(const std::string& notification_id) { | 473 void NotificationView::ClickOnNotification(const std::string& notification_id) { |
| 455 controller_->ClickOnNotification(notification_id); | 474 controller_->ClickOnNotification(notification_id); |
| 456 } | 475 } |
| 457 | 476 |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 if (new_buttons) { | 784 if (new_buttons) { |
| 766 Layout(); | 785 Layout(); |
| 767 views::Widget* widget = GetWidget(); | 786 views::Widget* widget = GetWidget(); |
| 768 if (widget != NULL) { | 787 if (widget != NULL) { |
| 769 widget->SetSize(widget->GetContentsView()->GetPreferredSize()); | 788 widget->SetSize(widget->GetContentsView()->GetPreferredSize()); |
| 770 GetWidget()->SynthesizeMouseMoveEvent(); | 789 GetWidget()->SynthesizeMouseMoveEvent(); |
| 771 } | 790 } |
| 772 } | 791 } |
| 773 } | 792 } |
| 774 | 793 |
| 794 void NotificationView::CreateOrUpdateCloseButtonView( |
| 795 const Notification& notification) { |
| 796 set_closable(notification.closable()); |
| 797 |
| 798 if (notification.closable() && !close_button_) { |
| 799 PaddedButton *close = new PaddedButton(this); |
| 800 close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding); |
| 801 close->SetNormalImage(IDR_NOTIFICATION_CLOSE); |
| 802 close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER); |
| 803 close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED); |
| 804 close->set_animate_on_state_change(false); |
| 805 close->SetAccessibleName(l10n_util::GetStringUTF16( |
| 806 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME)); |
| 807 // The close button should be added to view hierarchy by the derived class. |
| 808 // This ensures that it is on top of other views. |
| 809 close->set_owned_by_client(); |
| 810 close_button_.reset(close); |
| 811 AddChildView(close_button_.get()); |
| 812 } else if (!notification.closable() && close_button_) { |
| 813 close_button_.reset(); |
| 814 } |
| 815 } |
| 816 |
| 775 int NotificationView::GetMessageLineLimit(int title_lines, int width) const { | 817 int NotificationView::GetMessageLineLimit(int title_lines, int width) const { |
| 776 // Image notifications require that the image must be kept flush against | 818 // Image notifications require that the image must be kept flush against |
| 777 // their icons, but we can allow more text if no image. | 819 // their icons, but we can allow more text if no image. |
| 778 int effective_title_lines = std::max(0, title_lines - 1); | 820 int effective_title_lines = std::max(0, title_lines - 1); |
| 779 int line_reduction_from_title = (image_view_ ? 1 : 2) * effective_title_lines; | 821 int line_reduction_from_title = (image_view_ ? 1 : 2) * effective_title_lines; |
| 780 if (!image_view_) { | 822 if (!image_view_) { |
| 781 // Title lines are counted as twice as big as message lines for the purpose | 823 // Title lines are counted as twice as big as message lines for the purpose |
| 782 // of this calculation. | 824 // of this calculation. |
| 783 // The effect from the title reduction here should be: | 825 // The effect from the title reduction here should be: |
| 784 // * 0 title lines: 5 max lines message. | 826 // * 0 title lines: 5 max lines message. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 806 std::max(0, message_line_limit - line_reduction_from_title); | 848 std::max(0, message_line_limit - line_reduction_from_title); |
| 807 | 849 |
| 808 return message_line_limit; | 850 return message_line_limit; |
| 809 } | 851 } |
| 810 | 852 |
| 811 int NotificationView::GetMessageHeight(int width, int limit) const { | 853 int NotificationView::GetMessageHeight(int width, int limit) const { |
| 812 return message_view_ ? | 854 return message_view_ ? |
| 813 message_view_->GetSizeForWidthAndLines(width, limit).height() : 0; | 855 message_view_->GetSizeForWidthAndLines(width, limit).height() : 0; |
| 814 } | 856 } |
| 815 | 857 |
| 858 bool NotificationView::IsCloseButtonFocused() { |
| 859 if (!close_button_) |
| 860 return false; |
| 861 |
| 862 views::FocusManager* focus_manager = GetFocusManager(); |
| 863 return focus_manager && |
| 864 focus_manager->GetFocusedView() == close_button_.get(); |
| 865 } |
| 866 |
| 867 void NotificationView::RequestFocusOnCloseButton() { |
| 868 if (close_button_) |
| 869 close_button_->RequestFocus(); |
| 870 } |
| 871 |
| 872 bool NotificationView::IsClosable() { |
| 873 return close_button_; |
| 874 } |
| 875 |
| 816 } // namespace message_center | 876 } // namespace message_center |
| OLD | NEW |