OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ash/system/web_notification/message_center_bubble.h" | |
6 | |
7 #include "ash/system/web_notification/web_notification_view.h" | |
8 #include "grit/ash_strings.h" | |
9 #include "ui/base/l10n/l10n_util.h" | |
10 #include "ui/base/resource/resource_bundle.h" | |
11 #include "ui/gfx/size.h" | |
12 #include "ui/views/controls/button/text_button.h" | |
13 #include "ui/views/controls/label.h" | |
14 #include "ui/views/controls/scroll_view.h" | |
15 #include "ui/views/layout/box_layout.h" | |
16 #include "ui/views/layout/grid_layout.h" | |
17 #include "ui/views/painter.h" | |
18 #include "ui/views/view.h" | |
19 #include "ui/views/widget/widget.h" | |
20 | |
21 namespace message_center { | |
22 | |
23 namespace { | |
24 | |
25 const int kWebNotificationBubbleMinHeight = 80; | |
26 const int kWebNotificationBubbleMaxHeight = 400; | |
27 const SkColor kBorderDarkColor = SkColorSetRGB(0xaa, 0xaa, 0xaa); | |
28 | |
29 // The view for the buttons at the bottom of the web notification tray. | |
30 class WebNotificationButtonView : public views::View, | |
31 public views::ButtonListener { | |
32 public: | |
33 explicit WebNotificationButtonView( | |
34 WebNotificationList::Delegate* list_delegate) | |
35 : list_delegate_(list_delegate), | |
36 close_all_button_(NULL) { | |
37 set_background(views::Background::CreateBackgroundPainter( | |
38 true, | |
39 views::Painter::CreateVerticalGradient( | |
40 WebNotificationBubble::kHeaderBackgroundColorLight, | |
41 WebNotificationBubble::kHeaderBackgroundColorDark))); | |
42 set_border(views::Border::CreateSolidSidedBorder( | |
43 2, 0, 0, 0, kBorderDarkColor)); | |
44 | |
45 views::GridLayout* layout = new views::GridLayout(this); | |
46 SetLayoutManager(layout); | |
47 views::ColumnSet* columns = layout->AddColumnSet(0); | |
48 columns->AddPaddingColumn(100, 0); | |
49 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, | |
50 0, /* resize percent */ | |
51 views::GridLayout::USE_PREF, 0, 0); | |
52 columns->AddPaddingColumn(0, 4); | |
53 | |
54 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
55 close_all_button_ = new views::TextButton( | |
56 this, rb.GetLocalizedString(IDS_ASH_WEB_NOTFICATION_TRAY_CLEAR_ALL)); | |
57 close_all_button_->set_alignment(views::TextButton::ALIGN_CENTER); | |
58 close_all_button_->set_focusable(true); | |
59 close_all_button_->set_request_focus_on_press(false); | |
60 | |
61 layout->AddPaddingRow(0, 4); | |
62 layout->StartRow(0, 0); | |
63 layout->AddView(close_all_button_); | |
64 } | |
65 | |
66 virtual ~WebNotificationButtonView() {} | |
67 | |
68 void SetCloseAllVisible(bool visible) { | |
69 close_all_button_->SetVisible(visible); | |
70 } | |
71 | |
72 // Overridden from ButtonListener. | |
73 virtual void ButtonPressed(views::Button* sender, | |
74 const ui::Event& event) OVERRIDE { | |
75 if (sender == close_all_button_) | |
76 list_delegate_->SendRemoveAllNotifications(); | |
77 } | |
78 | |
79 private: | |
80 WebNotificationList::Delegate* list_delegate_; | |
81 views::TextButton* close_all_button_; | |
82 | |
83 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView); | |
84 }; | |
85 | |
86 // A custom scroll-view that has a specified size. | |
87 class FixedSizedScrollView : public views::ScrollView { | |
88 public: | |
89 FixedSizedScrollView() { | |
90 set_focusable(true); | |
91 set_notify_enter_exit_on_child(true); | |
92 } | |
93 | |
94 virtual ~FixedSizedScrollView() {} | |
95 | |
96 void SetFixedSize(const gfx::Size& size) { | |
97 if (fixed_size_ == size) | |
98 return; | |
99 fixed_size_ = size; | |
100 PreferredSizeChanged(); | |
101 } | |
102 | |
103 // views::View overrides. | |
104 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
105 gfx::Size size = fixed_size_.IsEmpty() ? | |
106 GetContents()->GetPreferredSize() : fixed_size_; | |
107 gfx::Insets insets = GetInsets(); | |
108 size.Enlarge(insets.width(), insets.height()); | |
109 return size; | |
110 } | |
111 | |
112 virtual void Layout() OVERRIDE { | |
113 views::View* contents = GetContents(); | |
114 gfx::Rect bounds = gfx::Rect(contents->GetPreferredSize()); | |
115 bounds.set_width(std::max(0, width() - GetScrollBarWidth())); | |
116 contents->SetBoundsRect(bounds); | |
117 | |
118 views::ScrollView::Layout(); | |
119 if (!vertical_scroll_bar()->visible()) { | |
120 gfx::Rect bounds = contents->bounds(); | |
121 bounds.set_width(bounds.width() + GetScrollBarWidth()); | |
122 contents->SetBoundsRect(bounds); | |
123 } | |
124 } | |
125 | |
126 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { | |
127 views::View* contents = GetContents(); | |
128 gfx::Rect bounds = gfx::Rect(contents->GetPreferredSize()); | |
129 bounds.set_width(std::max(0, width() - GetScrollBarWidth())); | |
130 contents->SetBoundsRect(bounds); | |
131 } | |
132 | |
133 private: | |
134 gfx::Size fixed_size_; | |
135 | |
136 DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView); | |
137 }; | |
138 | |
139 // Container for the messages. | |
140 class ScrollContentView : public views::View { | |
141 public: | |
142 ScrollContentView() { | |
143 views::BoxLayout* layout = | |
144 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1); | |
145 layout->set_spread_blank_space(true); | |
146 SetLayoutManager(layout); | |
147 } | |
148 | |
149 virtual ~ScrollContentView() { | |
150 } | |
151 | |
152 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
153 if (!preferred_size_.IsEmpty()) | |
154 return preferred_size_; | |
155 return views::View::GetPreferredSize(); | |
156 } | |
157 | |
158 void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; } | |
159 | |
160 private: | |
161 gfx::Size preferred_size_; | |
162 DISALLOW_COPY_AND_ASSIGN(ScrollContentView); | |
163 }; | |
164 | |
165 } // namespace | |
166 | |
167 // Message Center contents. | |
168 class MessageCenterContentsView : public views::View { | |
169 public: | |
170 explicit MessageCenterContentsView( | |
171 WebNotificationList::Delegate* list_delegate) | |
172 : list_delegate_(list_delegate) { | |
173 SetLayoutManager( | |
174 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | |
175 | |
176 scroll_content_ = new ScrollContentView; | |
177 scroller_ = new FixedSizedScrollView; | |
178 scroller_->SetContents(scroll_content_); | |
179 AddChildView(scroller_); | |
180 | |
181 scroller_->SetPaintToLayer(true); | |
182 scroller_->SetFillsBoundsOpaquely(false); | |
183 scroller_->layer()->SetMasksToBounds(true); | |
184 | |
185 button_view_ = new WebNotificationButtonView(list_delegate); | |
186 AddChildView(button_view_); | |
187 } | |
188 | |
189 void FocusContents() { | |
190 scroller_->RequestFocus(); | |
191 } | |
192 | |
193 void Update(const WebNotificationList::Notifications& notifications) { | |
194 scroll_content_->RemoveAllChildViews(true); | |
195 scroll_content_->set_preferred_size(gfx::Size()); | |
196 size_t num_children = 0; | |
197 for (WebNotificationList::Notifications::const_iterator iter = | |
198 notifications.begin(); iter != notifications.end(); ++iter) { | |
199 WebNotificationView* view = new WebNotificationView( | |
200 list_delegate_, *iter, scroller_->GetScrollBarWidth()); | |
201 view->set_scroller(scroller_); | |
202 scroll_content_->AddChildView(view); | |
203 if (++num_children >= | |
204 WebNotificationList::kMaxVisibleMessageCenterNotifications) { | |
205 break; | |
206 } | |
207 } | |
208 if (num_children == 0) { | |
209 views::Label* label = new views::Label(l10n_util::GetStringUTF16( | |
210 IDS_ASH_WEB_NOTFICATION_TRAY_NO_MESSAGES)); | |
211 label->SetFont(label->font().DeriveFont(1)); | |
212 label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); | |
213 label->SetEnabledColor(SK_ColorGRAY); | |
214 scroll_content_->AddChildView(label); | |
215 button_view_->SetCloseAllVisible(false); | |
216 } else { | |
217 button_view_->SetCloseAllVisible(true); | |
218 } | |
219 SizeScrollContent(); | |
220 Layout(); | |
221 if (GetWidget()) | |
222 GetWidget()->GetRootView()->SchedulePaint(); | |
223 } | |
224 | |
225 size_t NumMessageViews() const { | |
226 return scroll_content_->child_count(); | |
227 } | |
228 | |
229 private: | |
230 void SizeScrollContent() { | |
231 gfx::Size scroll_size = scroll_content_->GetPreferredSize(); | |
232 const int button_height = button_view_->GetPreferredSize().height(); | |
233 const int min_height = kWebNotificationBubbleMinHeight - button_height; | |
234 const int max_height = kWebNotificationBubbleMaxHeight - button_height; | |
235 int scroll_height = std::min(std::max( | |
236 scroll_size.height(), min_height), max_height); | |
237 scroll_size.set_height(scroll_height); | |
238 if (scroll_height == min_height) | |
239 scroll_content_->set_preferred_size(scroll_size); | |
240 else | |
241 scroll_content_->set_preferred_size(gfx::Size()); | |
242 scroller_->SetFixedSize(scroll_size); | |
243 scroller_->SizeToPreferredSize(); | |
244 scroll_content_->InvalidateLayout(); | |
245 } | |
246 | |
247 WebNotificationList::Delegate* list_delegate_; | |
248 FixedSizedScrollView* scroller_; | |
249 ScrollContentView* scroll_content_; | |
250 WebNotificationButtonView* button_view_; | |
251 | |
252 DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView); | |
253 }; | |
254 | |
255 // Message Center Bubble. | |
256 MessageCenterBubble::MessageCenterBubble( | |
257 WebNotificationList::Delegate* delegate) | |
258 : WebNotificationBubble(delegate), | |
259 contents_view_(NULL) { | |
260 } | |
261 | |
262 MessageCenterBubble::~MessageCenterBubble() {} | |
263 | |
264 TrayBubbleView::InitParams MessageCenterBubble::GetInitParams( | |
265 TrayBubbleView::AnchorAlignment anchor_alignment) { | |
266 TrayBubbleView::InitParams init_params = | |
267 GetDefaultInitParams(anchor_alignment); | |
268 init_params.max_height = message_center::kWebNotificationBubbleMaxHeight; | |
269 init_params.can_activate = true; | |
270 return init_params; | |
271 } | |
272 | |
273 void MessageCenterBubble::InitializeContents(TrayBubbleView* bubble_view) { | |
274 bubble_view_ = bubble_view; | |
275 contents_view_ = new MessageCenterContentsView(list_delegate_); | |
276 bubble_view_->AddChildView(contents_view_); | |
277 UpdateBubbleView(); | |
278 contents_view_->FocusContents(); | |
279 } | |
280 | |
281 void MessageCenterBubble::OnBubbleViewDestroyed() { | |
282 contents_view_ = NULL; | |
283 } | |
284 | |
285 void MessageCenterBubble::UpdateBubbleView() { | |
286 if (!bubble_view_) | |
287 return; // Could get called after view is closed | |
288 contents_view_->Update( | |
289 list_delegate_->GetNotificationList()->notifications()); | |
290 bubble_view_->Show(); | |
291 bubble_view_->UpdateBubble(); | |
292 } | |
293 | |
294 void MessageCenterBubble::OnMouseEnteredView() { | |
295 } | |
296 | |
297 void MessageCenterBubble::OnMouseExitedView() { | |
298 } | |
299 | |
300 size_t MessageCenterBubble::NumMessageViewsForTest() const { | |
301 return contents_view_->NumMessageViews(); | |
302 } | |
303 | |
304 } // namespace message_center | |
OLD | NEW |