| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/message_center/views/group_view.h" | |
| 6 | |
| 7 #include "base/strings/string_number_conversions.h" | |
| 8 #include "base/strings/string_util.h" | |
| 9 #include "base/strings/utf_string_conversions.h" | |
| 10 #include "grit/ui_resources.h" | |
| 11 #include "grit/ui_strings.h" | |
| 12 #include "ui/base/l10n/l10n_util.h" | |
| 13 #include "ui/base/layout.h" | |
| 14 #include "ui/base/resource/resource_bundle.h" | |
| 15 #include "ui/gfx/canvas.h" | |
| 16 #include "ui/gfx/size.h" | |
| 17 #include "ui/gfx/skia_util.h" | |
| 18 #include "ui/gfx/text_elider.h" | |
| 19 #include "ui/message_center/message_center.h" | |
| 20 #include "ui/message_center/message_center_style.h" | |
| 21 #include "ui/message_center/message_center_tray.h" | |
| 22 #include "ui/message_center/message_center_util.h" | |
| 23 #include "ui/message_center/notification.h" | |
| 24 #include "ui/message_center/views/bounded_label.h" | |
| 25 #include "ui/message_center/views/constants.h" | |
| 26 #include "ui/message_center/views/notification_button.h" | |
| 27 #include "ui/message_center/views/proportional_image_view.h" | |
| 28 #include "ui/native_theme/native_theme.h" | |
| 29 #include "ui/views/background.h" | |
| 30 #include "ui/views/border.h" | |
| 31 #include "ui/views/controls/button/image_button.h" | |
| 32 #include "ui/views/controls/image_view.h" | |
| 33 #include "ui/views/controls/label.h" | |
| 34 #include "ui/views/layout/box_layout.h" | |
| 35 #include "ui/views/layout/fill_layout.h" | |
| 36 #include "ui/views/widget/widget.h" | |
| 37 | |
| 38 #if defined(USE_AURA) | |
| 39 #include "ui/base/cursor/cursor.h" | |
| 40 #endif | |
| 41 | |
| 42 namespace { | |
| 43 | |
| 44 // static | |
| 45 views::Border* MakeTextBorder(int padding, int top, int bottom) { | |
| 46 // Split the padding between the top and the bottom, then add the extra space. | |
| 47 return views::Border::CreateEmptyBorder(padding / 2 + top, | |
| 48 message_center::kTextLeftPadding, | |
| 49 (padding + 1) / 2 + bottom, | |
| 50 message_center::kTextRightPadding); | |
| 51 } | |
| 52 | |
| 53 } // namespace | |
| 54 | |
| 55 namespace message_center { | |
| 56 | |
| 57 // GroupView //////////////////////////////////////////////////////////// | |
| 58 | |
| 59 GroupView::GroupView(MessageCenterController* controller, | |
| 60 const NotifierId& notifier_id, | |
| 61 const Notification& last_notification, | |
| 62 const gfx::ImageSkia& group_icon, | |
| 63 int group_size) | |
| 64 : MessageView(this, | |
| 65 last_notification.id(), | |
| 66 notifier_id, | |
| 67 last_notification.display_source()), | |
| 68 controller_(controller), | |
| 69 notifier_id_(notifier_id), | |
| 70 display_source_(last_notification.display_source()), | |
| 71 group_icon_(group_icon), | |
| 72 group_size_(group_size), | |
| 73 last_notification_id_(last_notification.id()), | |
| 74 top_view_(NULL), | |
| 75 bottom_view_(NULL), | |
| 76 title_view_(NULL), | |
| 77 message_view_(NULL), | |
| 78 context_message_view_(NULL), | |
| 79 icon_view_(NULL) | |
| 80 { | |
| 81 std::vector<base::string16> accessible_lines; | |
| 82 // Create the top_view_, which collects into a vertical box all content | |
| 83 // at the top of the notification (to the right of the icon) except for the | |
| 84 // close button. | |
| 85 top_view_ = new views::View(); | |
| 86 top_view_->SetLayoutManager( | |
| 87 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); | |
| 88 top_view_->set_border(views::Border::CreateEmptyBorder( | |
| 89 kTextTopPadding - 8, 0, kTextBottomPadding - 5, 0)); | |
| 90 | |
| 91 const gfx::FontList default_label_font_list = views::Label().font_list(); | |
| 92 | |
| 93 // Create the title view if appropriate. | |
| 94 const gfx::FontList& font_list = | |
| 95 default_label_font_list.DeriveFontListWithSizeDelta(2); | |
| 96 int padding = kTitleLineHeight - font_list.GetHeight(); | |
| 97 | |
| 98 title_view_ = new BoundedLabel( | |
| 99 gfx::TruncateString(base::string16(last_notification.title()), | |
| 100 kTitleCharacterLimit), | |
| 101 font_list); | |
| 102 accessible_lines.push_back(last_notification.title()); | |
| 103 title_view_->SetLineHeight(kTitleLineHeight); | |
| 104 title_view_->SetLineLimit(message_center::kTitleLineLimit); | |
| 105 title_view_->SetColors(message_center::kRegularTextColor, | |
| 106 kRegularTextBackgroundColor); | |
| 107 title_view_->set_border(MakeTextBorder(padding, 3, 0)); | |
| 108 top_view_->AddChildView(title_view_); | |
| 109 | |
| 110 // Create the message view if appropriate. | |
| 111 if (!last_notification.message().empty()) { | |
| 112 int padding = kMessageLineHeight - default_label_font_list.GetHeight(); | |
| 113 message_view_ = new BoundedLabel( | |
| 114 gfx::TruncateString(last_notification.message(), | |
| 115 kMessageCharacterLimit)); | |
| 116 message_view_->SetLineHeight(kMessageLineHeight); | |
| 117 message_view_->SetColors(message_center::kRegularTextColor, | |
| 118 kDimTextBackgroundColor); | |
| 119 message_view_->set_border(MakeTextBorder(padding, 4, 0)); | |
| 120 top_view_->AddChildView(message_view_); | |
| 121 accessible_lines.push_back(last_notification.message()); | |
| 122 } | |
| 123 | |
| 124 // Create the context message view if appropriate. | |
| 125 if (!last_notification.context_message().empty()) { | |
| 126 int padding = kMessageLineHeight - default_label_font_list.GetHeight(); | |
| 127 context_message_view_ = new BoundedLabel(gfx::TruncateString( | |
| 128 last_notification.context_message(), kContextMessageCharacterLimit), | |
| 129 default_label_font_list); | |
| 130 context_message_view_->SetLineLimit( | |
| 131 message_center::kContextMessageLineLimit); | |
| 132 context_message_view_->SetLineHeight(kMessageLineHeight); | |
| 133 context_message_view_->SetColors(message_center::kDimTextColor, | |
| 134 kContextTextBackgroundColor); | |
| 135 context_message_view_->set_border(MakeTextBorder(padding, 4, 0)); | |
| 136 top_view_->AddChildView(context_message_view_); | |
| 137 accessible_lines.push_back(last_notification.context_message()); | |
| 138 } | |
| 139 | |
| 140 // Create the notification icon view. | |
| 141 icon_view_ = new ProportionalImageView(last_notification.icon().AsImageSkia(), | |
| 142 gfx::Size(kIconSize, kIconSize)); | |
| 143 icon_view_->set_background(views::Background::CreateSolidBackground( | |
| 144 kIconBackgroundColor)); | |
| 145 | |
| 146 // Create the bottom_view_, which collects into a vertical box all content | |
| 147 // below the notification icon except for the expandGroup button. | |
| 148 bottom_view_ = new views::View(); | |
| 149 bottom_view_->SetLayoutManager( | |
| 150 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); | |
| 151 | |
| 152 // Create "N more.." action button | |
| 153 views::View* separator = new views::ImageView(); | |
| 154 separator->set_border(views::Border::CreateSolidSidedBorder( | |
| 155 1, 0, 0, 0, kButtonSeparatorColor)); | |
| 156 bottom_view_->AddChildView(separator); | |
| 157 more_button_ = new NotificationButton(this); | |
| 158 base::string16 button_title = | |
| 159 l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_MORE_FROM, | |
| 160 base::IntToString16(group_size_), | |
| 161 display_source_); | |
| 162 more_button_->SetTitle(button_title); | |
| 163 more_button_->SetIcon(group_icon_); | |
| 164 bottom_view_->AddChildView(more_button_); | |
| 165 | |
| 166 // Put together the different content and control views. Layering those allows | |
| 167 // for proper layout logic and it also allows the close button to | |
| 168 // overlap the content as needed to provide large enough click and touch area. | |
| 169 AddChildView(top_view_); | |
| 170 AddChildView(icon_view_); | |
| 171 AddChildView(bottom_view_); | |
| 172 AddChildView(close_button()); | |
| 173 set_accessible_name(JoinString(accessible_lines, '\n')); | |
| 174 } | |
| 175 | |
| 176 GroupView::~GroupView() { | |
| 177 } | |
| 178 | |
| 179 gfx::Size GroupView::GetPreferredSize() { | |
| 180 int top_width = top_view_->GetPreferredSize().width(); | |
| 181 int bottom_width = bottom_view_->GetPreferredSize().width(); | |
| 182 int preferred_width = std::max(top_width, bottom_width) + GetInsets().width(); | |
| 183 return gfx::Size(preferred_width, GetHeightForWidth(preferred_width)); | |
| 184 } | |
| 185 | |
| 186 int GroupView::GetHeightForWidth(int width) { | |
| 187 int content_width = width - GetInsets().width(); | |
| 188 int top_height = top_view_->GetHeightForWidth(content_width); | |
| 189 int bottom_height = bottom_view_->GetHeightForWidth(content_width); | |
| 190 int content_height = std::max(top_height, kIconSize) + bottom_height; | |
| 191 | |
| 192 // Adjust the height to make sure there is at least 16px of space below the | |
| 193 // icon if there is any space there (<http://crbug.com/232966>). | |
| 194 if (content_height > kIconSize) | |
| 195 content_height = std::max(content_height, | |
| 196 kIconSize + message_center::kIconBottomPadding); | |
| 197 | |
| 198 return content_height + GetInsets().height(); | |
| 199 } | |
| 200 | |
| 201 void GroupView::Layout() { | |
| 202 MessageView::Layout(); | |
| 203 gfx::Insets insets = GetInsets(); | |
| 204 int content_width = width() - insets.width(); | |
| 205 | |
| 206 // Top views. | |
| 207 int top_height = top_view_->GetHeightForWidth(content_width); | |
| 208 top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height); | |
| 209 | |
| 210 // Icon. | |
| 211 icon_view_->SetBounds(insets.left(), insets.top(), kIconSize, kIconSize); | |
| 212 | |
| 213 // Bottom views. | |
| 214 int bottom_y = insets.top() + std::max(top_height, kIconSize); | |
| 215 int bottom_height = bottom_view_->GetHeightForWidth(content_width); | |
| 216 bottom_view_->SetBounds(insets.left(), bottom_y, | |
| 217 content_width, bottom_height); | |
| 218 } | |
| 219 | |
| 220 void GroupView::OnFocus() { | |
| 221 MessageView::OnFocus(); | |
| 222 ScrollRectToVisible(GetLocalBounds()); | |
| 223 } | |
| 224 | |
| 225 gfx::NativeCursor GroupView::GetCursor(const ui::MouseEvent& event) { | |
| 226 // If we ever have non-Aura views environment, this will fail compilation. | |
| 227 #if defined(USE_AURA) | |
| 228 return ui::kCursorHand; | |
| 229 #endif | |
| 230 } | |
| 231 | |
| 232 void GroupView::ButtonPressed(views::Button* sender, | |
| 233 const ui::Event& event) { | |
| 234 if (sender == more_button_) { | |
| 235 controller_->ExpandGroup(notifier_id_); | |
| 236 return; | |
| 237 } | |
| 238 // Let the superclass handle anything other than action buttons. | |
| 239 // Warning: This may cause the GroupView itself to be deleted, | |
| 240 // so don't do anything afterwards. | |
| 241 MessageView::ButtonPressed(sender, event); | |
| 242 } | |
| 243 | |
| 244 void GroupView::ClickOnNotification(const std::string& notification_id) { | |
| 245 controller_->GroupBodyClicked(notification_id); | |
| 246 } | |
| 247 | |
| 248 void GroupView::RemoveNotification(const std::string& notification_id, | |
| 249 bool by_user) { | |
| 250 controller_->RemoveGroup(notifier_id_); | |
| 251 } | |
| 252 | |
| 253 } // namespace message_center | |
| OLD | NEW |