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/native_theme/native_theme.h" | 14 #include "ui/native_theme/native_theme.h" |
15 #include "ui/views/controls/button/image_button.h" | 15 #include "ui/views/controls/button/image_button.h" |
16 #include "ui/views/controls/image_view.h" | 16 #include "ui/views/controls/image_view.h" |
17 #include "ui/views/controls/label.h" | 17 #include "ui/views/controls/label.h" |
18 #include "ui/views/layout/grid_layout.h" | 18 #include "ui/views/layout/grid_layout.h" |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 // Notification dimensions. | 22 // Notification dimensions. |
23 const int kNotificationPrimaryIconSize = 64; | 23 const int kPrimaryIconSize = 80; |
24 const int kNotificationSecondaryIconSize = 15; | 24 const int kIconLeftPadding = 0; |
25 const int kNotificationPadding1Width = 12; | 25 const int kIconColumnWidth = kPrimaryIconSize; |
26 const int kNotificationColumn1Width = kNotificationPrimaryIconSize; | 26 const int kIconToTextPadding = 15; |
27 const int kNotificationPadding2Width = 12; | 27 const int kTextToClosePadding = 10; |
28 const int kNotificationPadding3Width = 12; | 28 const int kCloseColumnWidth = 8; |
29 const int kNotificationColumn3Width = 26; | 29 const int kCloseRightPadding = 6; |
30 const int kNotificationPadding4Width = 10; | 30 const int kIconTopPadding = 0; |
31 const int kNotificationColumn4Width = 8; | 31 const int kTextTopPadding = 9; |
32 const int kNotificationPadding5Width = 8; | 32 const int kCloseTopPadding = 6; |
33 const int kNotificationColumn1Top = 12; | 33 const int kIconBottomPadding = 0; |
34 const int kNotificationColumn2Top = 9; | 34 const int kTextBottomPadding = 12; |
35 const int kNotificationColumn3Top = 4; | 35 const int kItemTitleToDetailsPadding = 3; |
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 : item_(item), |
57 size_(0, 0) { | |
Jun Mukai
2012/12/19 00:33:53
It's not this, but I noticed that ctor/dtor is dec
dharcourt
2012/12/19 01:47:44
I de-inlined the constructor & destructor to make
| |
61 gfx::Font font = GetDefaultFont(); | 58 gfx::Font font = GetDefaultFont(); |
62 preferred_size_.Enlarge(font.GetStringWidth(item.title), 0); | 59 size_.Enlarge(font.GetStringWidth(item.title), 0); |
63 preferred_size_.Enlarge(kNotificationItemInternalPadding, 0); | 60 size_.Enlarge(kItemTitleToDetailsPadding, 0); |
64 preferred_size_.Enlarge(font.GetStringWidth(item.message), 0); | 61 size_.Enlarge(font.GetStringWidth(item.message), 0); |
65 preferred_size_.set_height(font.GetHeight()); | 62 size_.set_height(font.GetHeight()); |
66 PreferredSizeChanged(); | 63 PreferredSizeChanged(); |
67 SchedulePaint(); | 64 SchedulePaint(); |
68 } | 65 } |
69 | 66 |
67 virtual ~ItemView() { | |
68 } | |
69 | |
70 // Overridden from views::View. | 70 // Overridden from views::View. |
71 virtual gfx::Size GetPreferredSize() OVERRIDE; | 71 virtual gfx::Size GetPreferredSize() OVERRIDE; |
72 virtual int GetBaseline() const OVERRIDE; | 72 virtual int GetBaseline() const OVERRIDE; |
73 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; | 73 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; |
74 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; | 74 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; |
75 virtual bool GetTooltipText(const gfx::Point& point, | 75 virtual bool GetTooltipText(const gfx::Point& point, |
76 string16* tooltip) const OVERRIDE; | 76 string16* tooltip) const OVERRIDE; |
77 | 77 |
78 protected: | 78 protected: |
79 // Overridden from views::View. | 79 // Overridden from views::View. |
80 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; | 80 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; |
Jun Mukai
2012/12/19 00:33:53
merge line 71-76 and this line. It doesn't make m
dharcourt
2012/12/19 01:47:44
I didn't know this was possible in C++. Wouldn't t
Jun Mukai
2012/12/19 22:28:41
It is quite common among chromium code base to put
dharcourt
2012/12/20 03:27:36
After implementing your suggestions for using Labe
| |
81 | 81 |
82 private: | 82 private: |
83 static gfx::Font GetDefaultFont(); | 83 static gfx::Font GetDefaultFont(); |
84 | 84 |
85 message_center::NotificationList::NotificationItem item_; | 85 message_center::NotificationList::NotificationItem item_; |
86 gfx::Size preferred_size_; | 86 gfx::Size size_; |
87 | 87 |
88 DISALLOW_COPY_AND_ASSIGN(ItemView); | 88 DISALLOW_COPY_AND_ASSIGN(ItemView); |
89 }; | 89 }; |
90 | 90 |
91 gfx::Size ItemView::GetPreferredSize() { | 91 gfx::Size ItemView::GetPreferredSize() { |
92 return preferred_size_; | 92 gfx::Insets insets = GetInsets(); |
93 return gfx::Size(insets.left() + size_.width() + insets.right(), | |
94 insets.top() + size_.height() + insets.bottom()); | |
93 } | 95 } |
94 | 96 |
95 int ItemView::GetBaseline() const { | 97 int ItemView::GetBaseline() const { |
96 return GetDefaultFont().GetBaseline(); | 98 gfx::Insets insets = GetInsets(); |
99 return insets.top() + GetDefaultFont().GetBaseline(); | |
97 } | 100 } |
98 | 101 |
99 bool ItemView::HitTestRect(const gfx::Rect& rect) const { | 102 bool ItemView::HitTestRect(const gfx::Rect& rect) const { |
100 return false; | 103 return false; |
101 } | 104 } |
102 | 105 |
103 void ItemView::GetAccessibleState( | 106 void ItemView::GetAccessibleState(ui::AccessibleViewState* state) { |
104 ui::AccessibleViewState* state) { | |
105 state->role = ui::AccessibilityTypes::ROLE_STATICTEXT; | 107 state->role = ui::AccessibilityTypes::ROLE_STATICTEXT; |
106 state->state = ui::AccessibilityTypes::STATE_READONLY; | 108 state->state = ui::AccessibilityTypes::STATE_READONLY; |
107 state->name = item_.message; // TODO(dharcourt): Include title localizably. | 109 state->name = item_.message; // TODO(dharcourt): Include title localizably. |
108 } | 110 } |
109 | 111 |
110 bool ItemView::GetTooltipText(const gfx::Point& point, | 112 bool ItemView::GetTooltipText(const gfx::Point& point, |
111 string16* tooltip) const { | 113 string16* tooltip) const { |
112 if (preferred_size_.width() > width()) { | 114 gfx::Insets insets = GetInsets(); |
115 if (insets.left() + size_.width() + insets.right() > width()) { | |
113 *tooltip = item_.message; // TODO(dharcourt): Include title localizably. | 116 *tooltip = item_.message; // TODO(dharcourt): Include title localizably. |
114 return true; | 117 return true; |
115 } | 118 } |
116 return false; | 119 return false; |
117 } | 120 } |
118 | 121 |
119 void ItemView::OnPaint(gfx::Canvas* canvas) { | 122 void ItemView::OnPaint(gfx::Canvas* canvas) { |
Jun Mukai
2012/12/19 00:33:53
Can you create views::Labels and put them to the c
dharcourt
2012/12/19 01:47:44
I'm trying this out... I'll upload a patch and upd
dharcourt
2012/12/20 03:27:36
Done, and it works very well and simplifies things
| |
120 OnPaintBackground(canvas); | 123 OnPaintBackground(canvas); |
121 OnPaintBorder(canvas); | 124 OnPaintBorder(canvas); |
122 OnPaintFocusBorder(canvas); | 125 OnPaintFocusBorder(canvas); |
123 | 126 |
124 gfx::Font font = GetDefaultFont(); | 127 gfx::Font font = GetDefaultFont(); |
125 int y = std::max(0, height() - preferred_size_.height()) / 2; | 128 gfx::Insets insets = GetInsets(); |
126 canvas->DrawStringInt(item_.title, font, kNotificationItemTitleColor, | 129 int x = insets.left(); |
127 0, y, width(), preferred_size_.height()); | 130 int y = insets.top(); |
131 canvas->DrawStringInt(item_.title, font, kItemTitleColor, | |
132 x, y, width() - x - insets.right(), size_.height()); | |
128 | 133 |
129 int x = font.GetStringWidth(item_.title) + kNotificationItemInternalPadding; | 134 int used = x + font.GetStringWidth(item_.title) + kItemTitleToDetailsPadding; |
130 if (x < width()) { | 135 int remaining = width() - used - insets.right(); |
136 if (remaining > 0) { | |
131 canvas->DrawStringInt( | 137 canvas->DrawStringInt( |
132 ui::ElideText(item_.message, font, width() - x, ui::ELIDE_AT_END), | 138 ui::ElideText(item_.message, font, remaining, ui::ELIDE_AT_END), |
133 font, kNotificationItemMessageColor, | 139 font, kItemMessageColor, |
134 x, y, width() - x, preferred_size_.height()); | 140 used, y, remaining, size_.height()); |
135 } | 141 } |
136 } | 142 } |
137 | 143 |
138 // static | 144 // static |
139 gfx::Font ItemView::GetDefaultFont() { | 145 gfx::Font ItemView::GetDefaultFont() { |
140 return ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); | 146 return ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); |
141 } | 147 } |
142 | 148 |
143 // BoxView draws a color rectangle or just reserves some space. | 149 // BoxView draws a color rectangle or just reserves some space. |
144 class BoxView : public views::View { | 150 class BoxView : public views::View { |
Jun Mukai
2012/12/19 00:33:53
This seems a transparent view used for padding. Am
dharcourt
2012/12/19 01:47:44
This is indeed a transparent view used for padding
Jun Mukai
2012/12/19 22:28:41
ah, I've misunderstood. thanks for description.
dharcourt
2012/12/20 03:27:36
Inspired by the ItemView reduction in size, and pr
| |
145 public: | 151 public: |
146 BoxView(int width, int height, SkColor color=SkColorSetARGB(0, 0, 0, 0)) | 152 BoxView(int width, int height, SkColor color=SkColorSetARGB(0, 0, 0, 0)) |
147 : size_(width, height) { | 153 : size_(width, height), |
148 if (SkColorGetA(color) > 0) | 154 color_(color) { |
149 set_background(views::Background::CreateSolidBackground(color)); | |
150 PreferredSizeChanged(); | 155 PreferredSizeChanged(); |
151 SchedulePaint(); | 156 SchedulePaint(); |
152 } | 157 } |
153 | 158 |
159 virtual ~BoxView() { | |
160 } | |
161 | |
154 // Overridden from View: | 162 // Overridden from View: |
155 virtual gfx::Size GetPreferredSize() OVERRIDE; | 163 virtual gfx::Size GetPreferredSize() OVERRIDE; |
156 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; | 164 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; |
157 | 165 |
166 protected: | |
167 // Overridden from views::View. | |
168 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; | |
169 | |
158 private: | 170 private: |
159 gfx::Size size_; | 171 gfx::Size size_; |
172 SkColor color_; | |
160 | 173 |
161 DISALLOW_COPY_AND_ASSIGN(BoxView); | 174 DISALLOW_COPY_AND_ASSIGN(BoxView); |
162 }; | 175 }; |
163 | 176 |
164 gfx::Size BoxView::GetPreferredSize() { | 177 gfx::Size BoxView::GetPreferredSize() { |
165 return size_; | 178 return size_; |
166 } | 179 } |
167 | 180 |
168 bool BoxView::HitTestRect(const gfx::Rect& rect) const { | 181 bool BoxView::HitTestRect(const gfx::Rect& rect) const { |
169 return false; | 182 return false; |
170 } | 183 } |
171 | 184 |
185 void BoxView::OnPaint(gfx::Canvas* canvas) { | |
186 if (SkColorGetA(color_) > 0) | |
187 canvas->FillRect(GetContentsBounds(), color_); | |
188 } | |
189 | |
172 } // namespace | 190 } // namespace |
173 | 191 |
174 namespace message_center { | 192 namespace message_center { |
175 | 193 |
176 MessageViewMultiple::MessageViewMultiple( | 194 MessageViewMultiple::MessageViewMultiple( |
177 NotificationList::Delegate* list_delegate, | 195 NotificationList::Delegate* list_delegate, |
178 const NotificationList::Notification& notification) | 196 const NotificationList::Notification& notification) |
179 : MessageView(list_delegate, notification) {} | 197 : MessageView(list_delegate, notification) { |
198 } | |
180 | 199 |
181 MessageViewMultiple::MessageViewMultiple() {} | 200 MessageViewMultiple::~MessageViewMultiple() { |
182 | 201 } |
183 MessageViewMultiple::~MessageViewMultiple() {} | |
184 | 202 |
185 // TODO(dharcourt): Make this a subclass of BaseFormatView or of a | 203 // TODO(dharcourt): Make this a subclass of BaseFormatView or of a |
186 // BaseFormatView superclass and leverage that class' SetUpView(). | 204 // BaseFormatView superclass and leverage that class' SetUpView(). |
187 void MessageViewMultiple::SetUpView() { | 205 void MessageViewMultiple::SetUpView() { |
188 | 206 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
189 SkColor background = notification_.is_read ? | |
190 kNotificationReadBackgroundColor : kNotificationBackgroundColor; | |
191 set_background(views::Background::CreateSolidBackground(background)); | |
192 | 207 |
193 views::GridLayout* layout = new views::GridLayout(this); | 208 views::GridLayout* layout = new views::GridLayout(this); |
194 SetLayoutManager(layout); | 209 SetLayoutManager(layout); |
195 | 210 |
196 // Four columns (icon, messages, time, close) surrounded by padding. The icon, | 211 // 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 | 212 // and close button columns and the padding have fixed widths and the text |
198 // the remaining space. Inter-column padding is included within columns | 213 // column fills up the remaining space. To minimize the number of columns and |
199 // whenever horizontal allignment allows for it. | 214 // simplify column spanning padding is applied to each view within columns |
215 // instead of through padding columns. | |
200 views::ColumnSet* columns = layout->AddColumnSet(0); | 216 views::ColumnSet* columns = layout->AddColumnSet(0); |
201 columns->AddPaddingColumn(0, kNotificationPadding1Width); | 217 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, |
202 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, | |
203 0, views::GridLayout::FIXED, | 218 0, views::GridLayout::FIXED, |
204 kNotificationColumn1Width, kNotificationColumn1Width); | 219 kIconLeftPadding + kIconColumnWidth + kIconToTextPadding, |
205 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, | 220 kIconLeftPadding + kIconColumnWidth + kIconToTextPadding); |
206 0, views::GridLayout::FIXED, | 221 // Padding + icon + padding. |
207 kNotificationPadding2Width, kNotificationPadding2Width); | |
208 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, | 222 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
209 100, views::GridLayout::USE_PREF, | 223 100, views::GridLayout::USE_PREF, |
210 0, 0); | 224 0, 0); |
211 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, | 225 // Text + padding (kTextToClosePadding). |
226 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, | |
212 0, views::GridLayout::FIXED, | 227 0, views::GridLayout::FIXED, |
213 kNotificationPadding3Width + kNotificationColumn3Width, | 228 kCloseColumnWidth + kCloseRightPadding, |
214 kNotificationPadding3Width + kNotificationColumn3Width); | 229 kCloseColumnWidth + kCloseRightPadding); |
215 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, | 230 // Close button + padding. |
216 0, views::GridLayout::FIXED, | |
217 kNotificationPadding4Width + kNotificationColumn4Width, | |
218 kNotificationPadding4Width + kNotificationColumn4Width); | |
219 columns->AddPaddingColumn(0, kNotificationPadding5Width); | |
220 | 231 |
221 // First row: Primary icon. | 232 // First row: Icon. This vertically spans the close button padding row, the |
233 // close button row, and all item rows. | |
222 layout->StartRow(0, 0); | 234 layout->StartRow(0, 0); |
223 views::ImageView* primary_icon = new views::ImageView; | 235 views::ImageView* icon = new views::ImageView; |
224 primary_icon->SetImageSize(gfx::Size(kNotificationPrimaryIconSize, | 236 icon->SetImageSize(gfx::Size(kPrimaryIconSize, kPrimaryIconSize)); |
225 kNotificationPrimaryIconSize)); | 237 icon->SetImage(notification_.primary_icon); |
226 primary_icon->SetImage(notification_.primary_icon); | 238 icon->SetHorizontalAlignment(views::ImageView::LEADING); |
227 primary_icon->set_border(CreateTopBorder(kNotificationColumn1Top)); | 239 icon->SetVerticalAlignment(views::ImageView::LEADING); |
228 primary_icon->SetVerticalAlignment(views::ImageView::LEADING); | 240 icon->set_border(MakePadding(kIconTopPadding, kIconLeftPadding, |
229 layout->AddView(primary_icon, 1, 3 + 2 * notification_.items.size()); | 241 kIconBottomPadding, kIconToTextPadding)); |
242 layout->AddView(icon, 1, 2 + notification_.items.size()); | |
230 | 243 |
231 // First row: Title. | 244 // First row: Title. This vertically spans the close button padding row and |
245 // the close button row. | |
232 // TODO(dharcourt): Skip the title Label when there's no title text. | 246 // 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); | 247 views::Label* title = new views::Label(notification_.title); |
235 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 248 title->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
236 title->SetFont(title->font().DeriveFont(4)); | 249 title->SetFont(title->font().DeriveFont(4)); |
237 title->SetEnabledColor(kNotificationTitleColor); | 250 title->SetEnabledColor(kTitleColor); |
238 title->SetBackgroundColor(kNotificationTitleBackgroundColor); | 251 title->SetBackgroundColor(kTitleBackgroundColor); |
239 title->set_border(CreateTopBorder(kNotificationColumn2Top)); | 252 title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextToClosePadding)); |
240 layout->AddView(title, 1, 2); | 253 layout->AddView(title, 1, 2); |
241 | 254 |
242 // First row: Time. | 255 // First row: Close button padding. |
243 // TODO(dharcourt): Timestamp as "1m/5m/1h/5h/1d/5d/..." (ago). | 256 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 | 257 |
250 // First row: Close button padding. | 258 // Second row: Close button, which has to be on a row of its own because its |
251 layout->AddView(new BoxView(1, kNotificationColumn4Top)); | 259 // top padding can't be set using empty borders (ImageButtons don't support |
252 | 260 // 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 | 261 // 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); | 262 layout->StartRow(100, 0); |
258 layout->SkipColumns(4); | 263 layout->SkipColumns(2); |
259 DCHECK(close_button_); | 264 DCHECK(close_button_); |
260 layout->AddView(close_button_); | 265 layout->AddView(close_button_); |
261 | 266 |
262 // Rows for each notification item, including appropriate padding. | 267 // One row for each notification item, including appropriate padding. |
263 layout->AddPaddingRow(0, 3); | 268 for (int i = 0, n = notification_.items.size(); i < n; ++i) { |
264 std::vector<NotificationList::NotificationItem>::const_iterator i; | 269 int bottom_padding = (i < n - 1) ? 4 : (kTextBottomPadding - 2); |
265 for (i = notification_.items.begin(); i != notification_.items.end(); ++i) { | 270 layout->StartRow(0, 0); |
266 layout->StartRowWithPadding(0, 0, 0, 3); | 271 layout->SkipColumns(1); |
267 layout->SkipColumns(2); | 272 ItemView* item = new ItemView(notification_.items[i]); |
268 layout->AddView(new ItemView(*i)); | 273 item->set_border(MakePadding(0, 0, bottom_padding, kTextToClosePadding)); |
269 layout->SkipColumns(2); | 274 layout->AddView(item); |
275 layout->SkipColumns(1); | |
270 } | 276 } |
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 } | 277 } |
307 | 278 |
308 } // namespace message_center | 279 } // namespace message_center |
OLD | NEW |