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/message_view_multiple.h" | 5 #include "ui/message_center/message_view_multiple.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/native_theme/native_theme.h" | 15 #include "ui/native_theme/native_theme.h" |
15 #include "ui/views/controls/button/image_button.h" | 16 #include "ui/views/controls/button/image_button.h" |
16 #include "ui/views/controls/image_view.h" | 17 #include "ui/views/controls/image_view.h" |
17 #include "ui/views/controls/label.h" | 18 #include "ui/views/controls/label.h" |
18 #include "ui/views/layout/grid_layout.h" | 19 #include "ui/views/layout/grid_layout.h" |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 // Notification dimensions. | 23 // Notification dimensions. |
23 const int kNotificationPrimaryIconSize = 64; | 24 const int kIconLeftPadding = 0; |
24 const int kNotificationSecondaryIconSize = 15; | 25 const int kIconColumnWidth = message_center::kNotificationIconWidth; |
25 const int kNotificationPadding1Width = 12; | 26 const int kIconToTextPadding = 15; |
26 const int kNotificationColumn1Width = kNotificationPrimaryIconSize; | 27 const int kTextToClosePadding = 10; |
27 const int kNotificationPadding2Width = 12; | 28 const int kCloseColumnWidth = 8; |
28 const int kNotificationPadding3Width = 12; | 29 const int kCloseRightPadding = 6; |
29 const int kNotificationColumn3Width = 26; | 30 const int kIconTopPadding = 0; |
30 const int kNotificationPadding4Width = 10; | 31 const int kTextTopPadding = 9; |
31 const int kNotificationColumn4Width = 8; | 32 const int kCloseTopPadding = 6; |
32 const int kNotificationPadding5Width = 8; | 33 const int kIconBottomPadding = 0; |
33 const int kNotificationColumn1Top = 12; | 34 const int kTextBottomPadding = 12; |
34 const int kNotificationColumn2Top = 9; | 35 const int kItemTitleToDetailsPadding = 3; |
35 const int kNotificationColumn3Top = 4; | |
36 const int kNotificationColumn4Top = 8; | |
37 const int kNotificationPaddingBottom = 19; | |
38 const int kNotificationItemInternalPadding = 12; | |
39 | 36 |
40 // The text background colors below are used only to prevent view::Label from | 37 // Notification colors. The text background colors below are used only to keep |
41 // modifying the text color and will never be used for drawing. See | 38 // view::Label from modifying the text color and will not actually be drawn. |
42 // view::Label's SetEnabledColor() and SetBackgroundColor() for details. | 39 // See view::Label's SetEnabledColor() and SetBackgroundColor() for details. |
43 const SkColor kNotificationBackgroundColor = SkColorSetRGB(254, 254, 254); | 40 const SkColor kBackgroundColor = SkColorSetRGB(255, 255, 255); |
44 const SkColor kNotificationReadBackgroundColor = SkColorSetRGB(250, 250, 250); | 41 const SkColor kTitleColor = SkColorSetRGB(68, 68, 68); |
45 const SkColor kNotificationTitleColor = SkColorSetRGB(68, 68, 68); | 42 const SkColor kTitleBackgroundColor = SK_ColorWHITE; |
46 const SkColor kNotificationTitleBackgroundColor = SK_ColorWHITE; | 43 const SkColor kItemTitleColor = SkColorSetRGB(68, 68, 68); |
47 const SkColor kNotificationMessageColor = SkColorSetRGB(136, 136, 136); | 44 const SkColor kItemMessageColor = SkColorSetRGB(136, 136, 136); |
48 const SkColor kNotificationMessageBackgroundColor = SK_ColorBLACK; | 45 |
49 const SkColor kNotificationTimeColor = SkColorSetRGB(176, 176, 176); | 46 // Static function to create an empty border to be used as padding. |
50 const SkColor kNotificationTimeBackgroundColor = SK_ColorBLACK; | 47 views::Border* MakePadding(int top, int left, int bottom, int right) { |
51 const SkColor kNotificationItemTitleColor = SkColorSetRGB(68, 68, 68); | 48 return views::Border::CreateEmptyBorder(top, left, bottom, right); |
52 const SkColor kNotificationItemMessageColor = SkColorSetRGB(136, 136, 136); | 49 } |
53 const SkColor kNotificationSeparatorColor = SkColorSetRGB(226, 226, 226); | |
54 | 50 |
55 // ItemViews are responsible for drawing each MessageViewMultiple item's title | 51 // ItemViews are responsible for drawing each MessageViewMultiple item's title |
56 // and message next to each other within a single column. | 52 // and message next to each other within a single column. |
57 class ItemView : public views::View { | 53 class ItemView : public views::View { |
58 public: | 54 public: |
59 ItemView(const message_center::NotificationList::NotificationItem& item) | 55 ItemView(const message_center::NotificationList::NotificationItem& item); |
60 : item_(item), preferred_size_(0, 0) { | 56 virtual ~ItemView(); |
61 gfx::Font font = GetDefaultFont(); | |
62 preferred_size_.Enlarge(font.GetStringWidth(item.title), 0); | |
63 preferred_size_.Enlarge(kNotificationItemInternalPadding, 0); | |
64 preferred_size_.Enlarge(font.GetStringWidth(item.message), 0); | |
65 preferred_size_.set_height(font.GetHeight()); | |
66 PreferredSizeChanged(); | |
67 SchedulePaint(); | |
68 } | |
69 | 57 |
70 // Overridden from views::View. | 58 // Overridden from views::View. |
71 virtual gfx::Size GetPreferredSize() OVERRIDE; | 59 virtual gfx::Size GetPreferredSize() OVERRIDE; |
72 virtual int GetBaseline() const OVERRIDE; | 60 virtual int GetBaseline() const OVERRIDE; |
73 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; | 61 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; |
74 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; | 62 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; |
75 virtual bool GetTooltipText(const gfx::Point& point, | 63 virtual bool GetTooltipText(const gfx::Point& point, |
76 string16* tooltip) const OVERRIDE; | 64 string16* tooltip) const OVERRIDE; |
77 | 65 |
78 protected: | 66 protected: |
79 // Overridden from views::View. | 67 // Overridden from views::View. |
80 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; | 68 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; |
81 | 69 |
82 private: | 70 private: |
83 static gfx::Font GetDefaultFont(); | 71 static gfx::Font GetDefaultFont(); |
84 | 72 |
85 message_center::NotificationList::NotificationItem item_; | 73 message_center::NotificationList::NotificationItem item_; |
86 gfx::Size preferred_size_; | 74 gfx::Size size_; |
87 | 75 |
88 DISALLOW_COPY_AND_ASSIGN(ItemView); | 76 DISALLOW_COPY_AND_ASSIGN(ItemView); |
89 }; | 77 }; |
90 | 78 |
79 ItemView::ItemView( | |
80 const message_center::NotificationList::NotificationItem& item) | |
81 : item_(item), | |
82 size_(0, 0) { | |
83 gfx::Font font = GetDefaultFont(); | |
84 size_.Enlarge(font.GetStringWidth(item.title), 0); | |
85 size_.Enlarge(kItemTitleToDetailsPadding, 0); | |
86 size_.Enlarge(font.GetStringWidth(item.message), 0); | |
87 size_.set_height(font.GetHeight()); | |
88 PreferredSizeChanged(); | |
89 SchedulePaint(); | |
90 } | |
91 | |
92 ItemView::~ItemView() { | |
93 } | |
94 | |
91 gfx::Size ItemView::GetPreferredSize() { | 95 gfx::Size ItemView::GetPreferredSize() { |
92 return preferred_size_; | 96 gfx::Insets insets = GetInsets(); |
97 return gfx::Size(insets.left() + size_.width() + insets.right(), | |
98 insets.top() + size_.height() + insets.bottom()); | |
93 } | 99 } |
94 | 100 |
95 int ItemView::GetBaseline() const { | 101 int ItemView::GetBaseline() const { |
96 return GetDefaultFont().GetBaseline(); | 102 gfx::Insets insets = GetInsets(); |
103 return insets.top() + GetDefaultFont().GetBaseline(); | |
97 } | 104 } |
98 | 105 |
99 bool ItemView::HitTestRect(const gfx::Rect& rect) const { | 106 bool ItemView::HitTestRect(const gfx::Rect& rect) const { |
100 return false; | 107 return false; |
101 } | 108 } |
102 | 109 |
103 void ItemView::GetAccessibleState( | 110 void ItemView::GetAccessibleState(ui::AccessibleViewState* state) { |
104 ui::AccessibleViewState* state) { | |
105 state->role = ui::AccessibilityTypes::ROLE_STATICTEXT; | 111 state->role = ui::AccessibilityTypes::ROLE_STATICTEXT; |
106 state->state = ui::AccessibilityTypes::STATE_READONLY; | 112 state->state = ui::AccessibilityTypes::STATE_READONLY; |
107 state->name = item_.message; // TODO(dharcourt): Include title localizably. | 113 state->name = item_.message; // TODO(dharcourt): Include title localizably. |
108 } | 114 } |
109 | 115 |
110 bool ItemView::GetTooltipText(const gfx::Point& point, | 116 bool ItemView::GetTooltipText(const gfx::Point& point, |
111 string16* tooltip) const { | 117 string16* tooltip) const { |
112 if (preferred_size_.width() > width()) { | 118 gfx::Insets insets = GetInsets(); |
119 if (insets.left() + size_.width() + insets.right() > width()) { | |
113 *tooltip = item_.message; // TODO(dharcourt): Include title localizably. | 120 *tooltip = item_.message; // TODO(dharcourt): Include title localizably. |
114 return true; | 121 return true; |
115 } | 122 } |
116 return false; | 123 return false; |
117 } | 124 } |
118 | 125 |
119 void ItemView::OnPaint(gfx::Canvas* canvas) { | 126 void ItemView::OnPaint(gfx::Canvas* canvas) { |
120 OnPaintBackground(canvas); | 127 OnPaintBackground(canvas); |
121 OnPaintBorder(canvas); | 128 OnPaintBorder(canvas); |
122 OnPaintFocusBorder(canvas); | 129 OnPaintFocusBorder(canvas); |
123 | 130 |
124 gfx::Font font = GetDefaultFont(); | 131 gfx::Font font = GetDefaultFont(); |
125 int y = std::max(0, height() - preferred_size_.height()) / 2; | 132 gfx::Insets insets = GetInsets(); |
126 canvas->DrawStringInt(item_.title, font, kNotificationItemTitleColor, | 133 int x = insets.left(); |
127 0, y, width(), preferred_size_.height()); | 134 int y = insets.top(); |
135 canvas->DrawStringInt(item_.title, font, kItemTitleColor, | |
136 x, y, width() - x - insets.right(), size_.height()); | |
128 | 137 |
129 int x = font.GetStringWidth(item_.title) + kNotificationItemInternalPadding; | 138 int used = x + font.GetStringWidth(item_.title) + kItemTitleToDetailsPadding; |
130 if (x < width()) { | 139 int remaining = width() - used - insets.right(); |
140 if (remaining > 0) { | |
131 canvas->DrawStringInt( | 141 canvas->DrawStringInt( |
132 ui::ElideText(item_.message, font, width() - x, ui::ELIDE_AT_END), | 142 ui::ElideText(item_.message, font, remaining, ui::ELIDE_AT_END), |
133 font, kNotificationItemMessageColor, | 143 font, kItemMessageColor, |
134 x, y, width() - x, preferred_size_.height()); | 144 used, y, remaining, size_.height()); |
135 } | 145 } |
136 } | 146 } |
137 | 147 |
138 // static | 148 // static |
139 gfx::Font ItemView::GetDefaultFont() { | 149 gfx::Font ItemView::GetDefaultFont() { |
140 return ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); | 150 return ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); |
141 } | 151 } |
142 | 152 |
143 // BoxView draws a color rectangle or just reserves some space. | 153 // BoxView draws a color rectangle or just reserves some space. |
144 class BoxView : public views::View { | 154 class BoxView : public views::View { |
145 public: | 155 public: |
146 BoxView(int width, int height, SkColor color=SkColorSetARGB(0, 0, 0, 0)) | 156 BoxView(int width, int height, SkColor color=SkColorSetARGB(0, 0, 0, 0)) |
147 : size_(width, height) { | 157 : size_(width, height), |
148 if (SkColorGetA(color) > 0) | 158 color_(color) { |
Jun Mukai
2012/12/19 22:28:41
then, these method should be out-lined for the con
dharcourt
2012/12/20 03:27:36
Correct, those should not be inline for consistenc
| |
149 set_background(views::Background::CreateSolidBackground(color)); | |
150 PreferredSizeChanged(); | 159 PreferredSizeChanged(); |
151 SchedulePaint(); | 160 SchedulePaint(); |
152 } | 161 } |
153 | 162 |
163 virtual ~BoxView() { | |
164 } | |
165 | |
154 // Overridden from View: | 166 // Overridden from View: |
155 virtual gfx::Size GetPreferredSize() OVERRIDE; | 167 virtual gfx::Size GetPreferredSize() OVERRIDE; |
156 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; | 168 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; |
157 | 169 |
170 protected: | |
171 // Overridden from views::View. | |
172 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; | |
173 | |
158 private: | 174 private: |
159 gfx::Size size_; | 175 gfx::Size size_; |
176 SkColor color_; | |
160 | 177 |
161 DISALLOW_COPY_AND_ASSIGN(BoxView); | 178 DISALLOW_COPY_AND_ASSIGN(BoxView); |
162 }; | 179 }; |
163 | 180 |
164 gfx::Size BoxView::GetPreferredSize() { | 181 gfx::Size BoxView::GetPreferredSize() { |
165 return size_; | 182 return size_; |
166 } | 183 } |
167 | 184 |
168 bool BoxView::HitTestRect(const gfx::Rect& rect) const { | 185 bool BoxView::HitTestRect(const gfx::Rect& rect) const { |
169 return false; | 186 return false; |
170 } | 187 } |
171 | 188 |
189 void BoxView::OnPaint(gfx::Canvas* canvas) { | |
190 if (SkColorGetA(color_) > 0) | |
191 canvas->FillRect(GetContentsBounds(), color_); | |
192 } | |
193 | |
172 } // namespace | 194 } // namespace |
173 | 195 |
174 namespace message_center { | 196 namespace message_center { |
175 | 197 |
176 MessageViewMultiple::MessageViewMultiple( | 198 MessageViewMultiple::MessageViewMultiple( |
177 NotificationList::Delegate* list_delegate, | 199 NotificationList::Delegate* list_delegate, |
178 const NotificationList::Notification& notification) | 200 const NotificationList::Notification& notification) |
179 : MessageView(list_delegate, notification) {} | 201 : MessageView(list_delegate, notification) { |
202 } | |
180 | 203 |
181 MessageViewMultiple::MessageViewMultiple() {} | 204 MessageViewMultiple::~MessageViewMultiple() { |
182 | 205 } |
183 MessageViewMultiple::~MessageViewMultiple() {} | |
184 | 206 |
185 // TODO(dharcourt): Make this a subclass of BaseFormatView or of a | 207 // TODO(dharcourt): Make this a subclass of BaseFormatView or of a |
186 // BaseFormatView superclass and leverage that class' SetUpView(). | 208 // BaseFormatView superclass and leverage that class' SetUpView(). |
187 void MessageViewMultiple::SetUpView() { | 209 void MessageViewMultiple::SetUpView() { |
188 | 210 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
189 SkColor background = notification_.is_read ? | |
190 kNotificationReadBackgroundColor : kNotificationBackgroundColor; | |
191 set_background(views::Background::CreateSolidBackground(background)); | |
192 | 211 |
193 views::GridLayout* layout = new views::GridLayout(this); | 212 views::GridLayout* layout = new views::GridLayout(this); |
194 SetLayoutManager(layout); | 213 SetLayoutManager(layout); |
195 | 214 |
196 // Four columns (icon, messages, time, close) surrounded by padding. The icon, | 215 // Three columns (icon, text, close button) surrounded by padding. The icon |
197 // time, and close columns have fixed width and the message column fills up | 216 // and close button columns and the padding have fixed widths and the text |
198 // the remaining space. Inter-column padding is included within columns | 217 // column fills up the remaining space. To minimize the number of columns and |
199 // whenever horizontal allignment allows for it. | 218 // simplify column spanning padding is applied to each view within columns |
219 // instead of through padding columns. | |
200 views::ColumnSet* columns = layout->AddColumnSet(0); | 220 views::ColumnSet* columns = layout->AddColumnSet(0); |
201 columns->AddPaddingColumn(0, kNotificationPadding1Width); | 221 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, |
202 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, | |
203 0, views::GridLayout::FIXED, | 222 0, views::GridLayout::FIXED, |
204 kNotificationColumn1Width, kNotificationColumn1Width); | 223 kIconLeftPadding + kIconColumnWidth + kIconToTextPadding, |
205 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, | 224 kIconLeftPadding + kIconColumnWidth + kIconToTextPadding); |
206 0, views::GridLayout::FIXED, | 225 // Padding + icon + padding. |
207 kNotificationPadding2Width, kNotificationPadding2Width); | |
208 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, | 226 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
209 100, views::GridLayout::USE_PREF, | 227 100, views::GridLayout::USE_PREF, |
210 0, 0); | 228 0, 0); |
211 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, | 229 // Text + padding (kTextToClosePadding). |
230 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, | |
212 0, views::GridLayout::FIXED, | 231 0, views::GridLayout::FIXED, |
213 kNotificationPadding3Width + kNotificationColumn3Width, | 232 kCloseColumnWidth + kCloseRightPadding, |
214 kNotificationPadding3Width + kNotificationColumn3Width); | 233 kCloseColumnWidth + kCloseRightPadding); |
215 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, | 234 // Close button + padding. |
216 0, views::GridLayout::FIXED, | |
217 kNotificationPadding4Width + kNotificationColumn4Width, | |
218 kNotificationPadding4Width + kNotificationColumn4Width); | |
219 columns->AddPaddingColumn(0, kNotificationPadding5Width); | |
220 | 235 |
221 // First row: Primary icon. | 236 // First row: Icon. This vertically spans the close button padding row, the |
237 // close button row, and all item rows. | |
222 layout->StartRow(0, 0); | 238 layout->StartRow(0, 0); |
223 views::ImageView* primary_icon = new views::ImageView; | 239 views::ImageView* icon = new views::ImageView; |
224 primary_icon->SetImageSize(gfx::Size(kNotificationPrimaryIconSize, | 240 icon->SetImageSize(gfx::Size(message_center::kNotificationIconWidth, |
225 kNotificationPrimaryIconSize)); | 241 message_center::kNotificationIconWidth)); |
226 primary_icon->SetImage(notification_.primary_icon); | 242 icon->SetImage(notification_.primary_icon); |
227 primary_icon->set_border(CreateTopBorder(kNotificationColumn1Top)); | 243 icon->SetHorizontalAlignment(views::ImageView::LEADING); |
228 primary_icon->SetVerticalAlignment(views::ImageView::LEADING); | 244 icon->SetVerticalAlignment(views::ImageView::LEADING); |
229 layout->AddView(primary_icon, 1, 3 + 2 * notification_.items.size()); | 245 icon->set_border(MakePadding(kIconTopPadding, kIconLeftPadding, |
246 kIconBottomPadding, kIconToTextPadding)); | |
247 layout->AddView(icon, 1, 2 + notification_.items.size()); | |
230 | 248 |
231 // First row: Title. | 249 // First row: Title. This vertically spans the close button padding row and |
250 // the close button row. | |
232 // TODO(dharcourt): Skip the title Label when there's no title text. | 251 // TODO(dharcourt): Skip the title Label when there's no title text. |
233 layout->SkipColumns(1); | |
234 views::Label* title = new views::Label(notification_.title); | 252 views::Label* title = new views::Label(notification_.title); |
235 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 253 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
236 title->SetFont(title->font().DeriveFont(4)); | 254 title->SetFont(title->font().DeriveFont(4)); |
237 title->SetEnabledColor(kNotificationTitleColor); | 255 title->SetEnabledColor(kTitleColor); |
238 title->SetBackgroundColor(kNotificationTitleBackgroundColor); | 256 title->SetBackgroundColor(kTitleBackgroundColor); |
239 title->set_border(CreateTopBorder(kNotificationColumn2Top)); | 257 title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextToClosePadding)); |
240 layout->AddView(title, 1, 2); | 258 layout->AddView(title, 1, 2); |
241 | 259 |
242 // First row: Time. | 260 // First row: Close button padding. |
243 // TODO(dharcourt): Timestamp as "1m/5m/1h/5h/1d/5d/..." (ago). | 261 layout->AddView(new BoxView(1, kCloseTopPadding)); |
244 views::Label* time = new views::Label(UTF8ToUTF16("")); | |
245 time->SetEnabledColor(kNotificationTimeColor); | |
246 time->SetBackgroundColor(kNotificationTimeBackgroundColor); | |
247 time->set_border(CreateTopBorder(kNotificationColumn3Top)); | |
248 layout->AddView(time, 1, 2); | |
249 | 262 |
250 // First row: Close button padding. | 263 // Second row: Close button, which has to be on a row of its own because its |
251 layout->AddView(new BoxView(1, kNotificationColumn4Top)); | 264 // top padding can't be set using empty borders (ImageButtons don't support |
252 | 265 // borders). The resize factor of this row (100) is much higher than that of |
253 // Second row: Close button, which has to be on a row of its own because it's | 266 // other rows (0) to ensure the first row's height stays at kCloseTopPadding. |
254 // an ImageButton and so its padding can't be set using borders. This row is | |
255 // set to resize vertically to ensure the first row stays at its minimum | |
256 // height of kNotificationColumn4Top. | |
257 layout->StartRow(100, 0); | 267 layout->StartRow(100, 0); |
258 layout->SkipColumns(4); | 268 layout->SkipColumns(2); |
259 DCHECK(close_button_); | 269 DCHECK(close_button_); |
260 layout->AddView(close_button_); | 270 layout->AddView(close_button_); |
261 | 271 |
262 // Rows for each notification item, including appropriate padding. | 272 // One row for each notification item, including appropriate padding. |
263 layout->AddPaddingRow(0, 3); | 273 for (int i = 0, n = notification_.items.size(); i < n; ++i) { |
264 std::vector<NotificationList::NotificationItem>::const_iterator i; | 274 int bottom_padding = (i < n - 1) ? 4 : (kTextBottomPadding - 2); |
265 for (i = notification_.items.begin(); i != notification_.items.end(); ++i) { | 275 layout->StartRow(0, 0); |
266 layout->StartRowWithPadding(0, 0, 0, 3); | 276 layout->SkipColumns(1); |
267 layout->SkipColumns(2); | 277 ItemView* item = new ItemView(notification_.items[i]); |
268 layout->AddView(new ItemView(*i)); | 278 item->set_border(MakePadding(0, 0, bottom_padding, kTextToClosePadding)); |
269 layout->SkipColumns(2); | 279 layout->AddView(item); |
280 layout->SkipColumns(1); | |
270 } | 281 } |
271 | |
272 // Rows for horizontal separator line with appropriate padding. | |
273 layout->StartRowWithPadding(0, 0, 0, 6); | |
274 layout->SkipColumns(1); | |
275 layout->AddView(new BoxView(1000000, 1, kNotificationSeparatorColor), 4, 1); | |
276 | |
277 // Last row: Summary message with padding. | |
278 // TODO(dharcourt): Skip the message Label when there's no message text. | |
279 layout->StartRowWithPadding(0, 0, 0, 5); | |
280 layout->SkipColumns(2); | |
281 views::Label* message = new views::Label(notification_.message); | |
282 message->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
283 message->SetMultiLine(true); | |
284 message->SetEnabledColor(kNotificationMessageColor); | |
285 message->SetBackgroundColor(kNotificationMessageBackgroundColor); | |
286 message->set_border(CreateTopBorder(1)); | |
287 layout->AddView(message); | |
288 | |
289 // Last row: Secondary icon. | |
290 layout->SkipColumns(1); | |
291 views::ImageView* secondary_icon = new views::ImageView; | |
292 secondary_icon->SetImageSize(gfx::Size(kNotificationSecondaryIconSize, | |
293 kNotificationSecondaryIconSize)); | |
294 secondary_icon->SetImage(notification_.secondary_icon.isNull() ? | |
295 notification_.primary_icon : | |
296 notification_.secondary_icon); | |
297 secondary_icon->SetVerticalAlignment(views::ImageView::LEADING); | |
298 layout->AddView(secondary_icon); | |
299 | |
300 // Final row with the bottom padding. | |
301 layout->AddPaddingRow(0, kNotificationPaddingBottom); | |
302 } | |
303 | |
304 views::Border* MessageViewMultiple::CreateTopBorder(int height) { | |
305 return views::Border::CreateEmptyBorder(height, 0, 0, 0); | |
306 } | 282 } |
307 | 283 |
308 } // namespace message_center | 284 } // namespace message_center |
OLD | NEW |