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 |