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/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
8 #include "grit/ui_resources.h" | 8 #include "grit/ui_resources.h" |
9 #include "ui/base/accessibility/accessible_view_state.h" | 9 #include "ui/base/accessibility/accessible_view_state.h" |
10 #include "ui/base/resource/resource_bundle.h" | 10 #include "ui/base/resource/resource_bundle.h" |
11 #include "ui/base/text/text_elider.h" | 11 #include "ui/base/text/text_elider.h" |
12 #include "ui/gfx/canvas.h" | 12 #include "ui/gfx/canvas.h" |
13 #include "ui/gfx/size.h" | 13 #include "ui/gfx/size.h" |
14 #include "ui/message_center/message_center_constants.h" | 14 #include "ui/message_center/message_center_constants.h" |
15 #include "ui/native_theme/native_theme.h" | 15 #include "ui/native_theme/native_theme.h" |
16 #include "ui/views/controls/button/image_button.h" | 16 #include "ui/views/controls/button/image_button.h" |
17 #include "ui/views/controls/image_view.h" | 17 #include "ui/views/controls/image_view.h" |
18 #include "ui/views/controls/label.h" | 18 #include "ui/views/controls/label.h" |
19 #include "ui/views/layout/box_layout.h" | 19 #include "ui/views/layout/box_layout.h" |
20 #include "ui/views/layout/grid_layout.h" | 20 #include "ui/views/layout/grid_layout.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // Notification dimensions. | 24 // Notification dimensions. |
25 const int kIconTopPadding = 0; | 25 const int kIconTopPadding = 0; |
26 const int kIconLeftPadding = 0; | 26 const int kIconLeftPadding = 0; |
27 const int kIconBottomPadding = 0; | 27 const int kIconBottomPadding = 0; |
28 const int kIconColumnWidth = message_center::kNotificationIconWidth; | 28 const int kIconColumnWidth = message_center::kNotificationIconWidth; |
29 const int kIconToTextPadding = 15; | 29 const int kIconToTextPadding = 16; |
30 const int kTextTopPadding = 9; | 30 const int kTextTopPadding = 6; |
31 const int kTextBottomPadding = 12; | 31 const int kTextBottomPadding = 6; |
32 const int kTextToClosePadding = 10; | 32 const int kTextToClosePadding = 10; |
33 const int kCloseTopPadding = 6; | 33 const int kCloseTopPadding = 8; |
34 const int kCloseRightPadding = 6; | 34 const int kCloseRightPadding = 8; |
35 const int kCloseColumnWidth = 8; | 35 const int kCloseColumnWidth = 8; |
36 const int kItemTitleToDetailsPadding = 3; | 36 const int kItemTitleToDetailsPadding = 3; |
37 const int kImageTopPadding = 0; | 37 const int kImageTopPadding = 0; |
38 const int kImageLeftPadding = 0; | 38 const int kImageLeftPadding = 0; |
39 const int kImageBottomPadding = 0; | 39 const int kImageBottomPadding = 0; |
40 const int kImageRightPadding = 0; | 40 const int kImageRightPadding = 0; |
41 | 41 |
42 // Notification colors. The text background colors below are used only to keep | 42 // Notification colors. The text background colors below are used only to keep |
43 // view::Label from modifying the text color and will not actually be drawn. | 43 // view::Label from modifying the text color and will not actually be drawn. |
44 // See view::Label's SetEnabledColor() and SetBackgroundColor() for details. | 44 // See view::Label's SetEnabledColor() and SetBackgroundColor() for details. |
(...skipping 24 matching lines...) Expand all Loading... |
69 views::BoxLayout* layout = | 69 views::BoxLayout* layout = |
70 new views::BoxLayout(views::BoxLayout::kHorizontal, | 70 new views::BoxLayout(views::BoxLayout::kHorizontal, |
71 0, 0, kItemTitleToDetailsPadding); | 71 0, 0, kItemTitleToDetailsPadding); |
72 SetLayoutManager(layout); | 72 SetLayoutManager(layout); |
73 | 73 |
74 views::Label* title = new views::Label(item.title); | 74 views::Label* title = new views::Label(item.title); |
75 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 75 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
76 title->SetElideBehavior(views::Label::ELIDE_AT_END); | 76 title->SetElideBehavior(views::Label::ELIDE_AT_END); |
77 title->SetEnabledColor(kTitleColor); | 77 title->SetEnabledColor(kTitleColor); |
78 title->SetBackgroundColor(kTitleBackgroundColor); | 78 title->SetBackgroundColor(kTitleBackgroundColor); |
79 AddChildViewAt(title, 0); | 79 AddChildView(title); |
80 | 80 |
81 views::Label* details = new views::Label(item.message); | 81 views::Label* details = new views::Label(item.message); |
82 details->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 82 details->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
83 details->SetElideBehavior(views::Label::ELIDE_AT_END); | 83 details->SetElideBehavior(views::Label::ELIDE_AT_END); |
84 details->SetEnabledColor(kMessageColor); | 84 details->SetEnabledColor(kMessageColor); |
85 details->SetBackgroundColor(kMessageBackgroundColor); | 85 details->SetBackgroundColor(kMessageBackgroundColor); |
86 AddChildViewAt(details, 1); | 86 AddChildView(details); |
87 | 87 |
88 PreferredSizeChanged(); | 88 PreferredSizeChanged(); |
89 SchedulePaint(); | 89 SchedulePaint(); |
90 } | 90 } |
91 | 91 |
92 ItemView::~ItemView() { | 92 ItemView::~ItemView() { |
93 } | 93 } |
94 | 94 |
95 // ProportionalImageViews match their heights to their widths to preserve the | 95 // ProportionalImageViews match their heights to their widths to preserve the |
96 // proportions of their images. | 96 // proportions of their images. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 100, views::GridLayout::USE_PREF, | 158 100, views::GridLayout::USE_PREF, |
159 0, 0); | 159 0, 0); |
160 // Text + padding (kTextToClosePadding). | 160 // Text + padding (kTextToClosePadding). |
161 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, | 161 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, |
162 0, views::GridLayout::FIXED, | 162 0, views::GridLayout::FIXED, |
163 kCloseColumnWidth + kCloseRightPadding, | 163 kCloseColumnWidth + kCloseRightPadding, |
164 kCloseColumnWidth + kCloseRightPadding); | 164 kCloseColumnWidth + kCloseRightPadding); |
165 // Close button + padding. | 165 // Close button + padding. |
166 | 166 |
167 // Figure out how many rows the icon should span. | 167 // Figure out how many rows the icon should span. |
168 int span = 2; // Two rows for the close button padding and close button. | 168 int span = 1; // One row for the title and close button, |
169 int displayed_item_count = | 169 int displayed_item_count = |
170 std::min(notification_.items.size(), kNotificationMaximumItems); | 170 std::min(notification_.items.size(), kNotificationMaximumItems); |
171 if (displayed_item_count > 0) | 171 if (displayed_item_count > 0) |
172 span += displayed_item_count; // + one row per item. | 172 span += displayed_item_count; // ... and one row per item, |
173 else | 173 else |
174 span += 1; // + one row for the message. | 174 span += 1; // ... or one row for the message, |
| 175 span += 1; // ... and one row for the text padding. |
175 | 176 |
176 // First row: Icon. | 177 // First row: Icon. This spans all the text rows to its right. |
177 layout->StartRow(0, 0); | 178 layout->StartRow(0, 0); |
178 views::ImageView* icon = new views::ImageView(); | 179 views::ImageView* icon = new views::ImageView(); |
179 icon->SetImageSize(gfx::Size(message_center::kNotificationIconWidth, | 180 icon->SetImageSize(gfx::Size(message_center::kNotificationIconWidth, |
180 message_center::kNotificationIconWidth)); | 181 message_center::kNotificationIconWidth)); |
181 icon->SetImage(notification_.primary_icon); | 182 icon->SetImage(notification_.primary_icon); |
182 icon->SetHorizontalAlignment(views::ImageView::LEADING); | 183 icon->SetHorizontalAlignment(views::ImageView::LEADING); |
183 icon->SetVerticalAlignment(views::ImageView::LEADING); | 184 icon->SetVerticalAlignment(views::ImageView::LEADING); |
184 icon->set_border(MakePadding(kIconTopPadding, kIconLeftPadding, | 185 icon->set_border(MakePadding(kIconTopPadding, kIconLeftPadding, |
185 kIconBottomPadding, kIconToTextPadding)); | 186 kIconBottomPadding, kIconToTextPadding)); |
186 layout->AddView(icon, 1, span); | 187 layout->AddView(icon, 1, span); |
187 | 188 |
188 // First row: Title. This vertically spans the close button padding row and | 189 // First row: Title. |
189 // the close button row. | 190 if (notification_.title.empty()) { |
190 // TODO(dharcourt): Skip the title Label when there's no title text. | 191 layout->SkipColumns(1); |
191 views::Label* title = new views::Label(notification_.title); | 192 } else { |
192 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 193 views::Label* title = new views::Label(notification_.title); |
193 title->SetElideBehavior(views::Label::ELIDE_AT_END); | 194 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
194 title->SetFont(title->font().DeriveFont(4)); | 195 title->SetElideBehavior(views::Label::ELIDE_AT_END); |
195 title->SetEnabledColor(kTitleColor); | 196 title->SetFont(title->font().DeriveFont(4)); |
196 title->SetBackgroundColor(kTitleBackgroundColor); | 197 title->SetEnabledColor(kTitleColor); |
197 title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextToClosePadding)); | 198 title->SetBackgroundColor(kTitleBackgroundColor); |
198 layout->AddView(title, 1, 2, | 199 title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextToClosePadding)); |
199 views::GridLayout::LEADING, views::GridLayout::LEADING); | 200 layout->AddView(title); |
| 201 } |
200 | 202 |
201 // First row: Close button padding. | 203 // Second row: Close button. Because ImageButtons don't support padding, the |
202 views::View* padding = new views::ImageView(); | 204 // close_button_ ImageButton has to be put inside a plain view that does |
203 padding->set_border(MakePadding(kCloseTopPadding, 1, 0, 0)); | 205 // support the padding we need. |
204 layout->AddView(padding); | 206 DCHECK(close_button_); |
| 207 views::View* close = new views::View(); |
| 208 close->SetLayoutManager( |
| 209 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); |
| 210 close->AddChildView(close_button_); |
| 211 close->set_border(MakePadding(kCloseTopPadding, 0, 0, 0)); |
| 212 layout->AddView(close); |
205 | 213 |
206 // Second row: Close button, which has to be on a row of its own because its | 214 // One row for the message if appropriate. |
207 // top padding can't be set using empty borders (ImageButtons don't support | 215 if (notification_.items.size() == 0 && !notification_.message.empty()) { |
208 // borders). The resize factor of this row (1) is higher than that of the | 216 layout->StartRow(0, 0); |
209 // first rows (0) to ensure the first row's height stays at kCloseTopPadding. | |
210 layout->StartRow(1, 0); | |
211 layout->SkipColumns(2); | |
212 DCHECK(close_button_); | |
213 layout->AddView(close_button_); | |
214 | |
215 // One row for the message if appropriate. The resize factor of this row (2) | |
216 // is higher than that of preceding rows (0 and 1) to ensure the content of | |
217 // the notification is top-aligned. | |
218 if (notification_.items.size() == 0) { | |
219 layout->StartRow(2, 0); | |
220 layout->SkipColumns(1); | 217 layout->SkipColumns(1); |
221 views::Label* message = new views::Label(notification_.message); | 218 views::Label* message = new views::Label(notification_.message); |
222 message->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 219 message->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
223 message->SetElideBehavior(views::Label::ELIDE_AT_END); | 220 message->SetMultiLine(true); |
224 message->SetEnabledColor(kMessageColor); | 221 message->SetEnabledColor(kMessageColor); |
225 message->SetBackgroundColor(kMessageBackgroundColor); | 222 message->SetBackgroundColor(kMessageBackgroundColor); |
226 message->set_border(MakePadding(0, 0, 3, kTextToClosePadding)); | 223 message->set_border(MakePadding(0, 0, 3, kTextToClosePadding)); |
227 layout->AddView(message, 1, 1, | 224 layout->AddView(message); |
228 views::GridLayout::LEADING, views::GridLayout::LEADING); | |
229 layout->SkipColumns(1); | 225 layout->SkipColumns(1); |
230 } | 226 } |
231 | 227 |
232 // One row for each notification item, including appropriate padding. The | 228 // One row for each notification item, including appropriate padding. |
233 // resize factor of the last row of items (3) is higher than that of all | |
234 // preceding rows (0, 1, and 2) to ensure the content of the notification is | |
235 // top-aligned. | |
236 for (int i = 0, n = displayed_item_count; i < n; ++i) { | 229 for (int i = 0, n = displayed_item_count; i < n; ++i) { |
237 int bottom_padding = (i < n - 1) ? 4 : (kTextBottomPadding - 2); | 230 layout->StartRow(0, 0); |
238 int resize_factor = (i < n - 1) ? 2 : 3; | |
239 layout->StartRow(resize_factor, 0); | |
240 layout->SkipColumns(1); | 231 layout->SkipColumns(1); |
241 ItemView* item = new ItemView(notification_.items[i]); | 232 ItemView* item = new ItemView(notification_.items[i]); |
242 item->set_border(MakePadding(0, 0, bottom_padding, kTextToClosePadding)); | 233 item->set_border(MakePadding(0, 0, 4, kTextToClosePadding)); |
243 layout->AddView(item); | 234 layout->AddView(item); |
244 layout->SkipColumns(1); | 235 layout->SkipColumns(1); |
245 } | 236 } |
246 | 237 |
| 238 // One text padding row, which adds some extra padding between the last line |
| 239 // of text and anything below it but also ensures all text above it is |
| 240 // top-aligned by having its height grow at the expense of the rows above it. |
| 241 layout->StartRow(100, 0); |
| 242 layout->SkipColumns(1); |
| 243 views::View* padding = new views::ImageView(); |
| 244 padding->set_border(MakePadding(kTextBottomPadding, 1, 0, 0)); |
| 245 layout->AddView(padding); |
| 246 layout->SkipColumns(1); |
| 247 |
247 // One row for the image. | 248 // One row for the image. |
248 layout->StartRow(0, 0); | 249 layout->StartRow(0, 0); |
249 views::ImageView* image = new ProportionalImageView(); | 250 views::ImageView* image = new ProportionalImageView(); |
250 image->SetImageSize(notification_.image.size()); | 251 image->SetImageSize(notification_.image.size()); |
251 image->SetImage(notification_.image); | 252 image->SetImage(notification_.image); |
252 image->SetHorizontalAlignment(views::ImageView::CENTER); | 253 image->SetHorizontalAlignment(views::ImageView::CENTER); |
253 image->SetVerticalAlignment(views::ImageView::LEADING); | 254 image->SetVerticalAlignment(views::ImageView::LEADING); |
254 image->set_border(MakePadding(kImageTopPadding, kImageLeftPadding, | 255 image->set_border(MakePadding(kImageTopPadding, kImageLeftPadding, |
255 kImageBottomPadding, kImageRightPadding)); | 256 kImageBottomPadding, kImageRightPadding)); |
256 layout->AddView(image, 3, 1, | 257 layout->AddView(image, 3, 1, |
257 views::GridLayout::FILL, views::GridLayout::LEADING); | 258 views::GridLayout::FILL, views::GridLayout::LEADING); |
258 } | 259 } |
259 | 260 |
260 } // namespace message_center | 261 } // namespace message_center |
OLD | NEW |