Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: chrome/browser/ui/views/message_center/message_center_widget_delegate.cc

Issue 18003003: Message center re-organized (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Compile issues fixed Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 "chrome/browser/ui/views/message_center/message_center_widget_delegate. h"
6
7 #include "chrome/browser/ui/views/message_center/message_center_frame_view.h"
8 #include "content/public/browser/user_metrics.h"
9 #include "ui/base/accessibility/accessible_view_state.h"
10 #include "ui/gfx/screen.h"
11 #include "ui/message_center/message_center_style.h"
12 #include "ui/message_center/message_center_util.h"
13 #include "ui/message_center/views/message_center_view.h"
14 #include "ui/native_theme/native_theme.h"
15 #include "ui/views/border.h"
16 #include "ui/views/layout/box_layout.h"
17 #include "ui/views/widget/widget.h"
18
19 namespace {
20
21 const int kBorderWidth = 1;
22
23 } // namespace
24
25 namespace message_center {
26
27 namespace internal {
28
29 // Gets the position of the systray (same as position of taskbar) from the
30 // work area bounds. Returns ALIGNMENT_NONE if position cannot be found.
31 Alignment GetSystrayAlignment() {
32 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
33 // TODO(dewittj): It's possible GetPrimaryDisplay is wrong.
34 gfx::Rect screen_bounds = screen->GetPrimaryDisplay().bounds();
35 gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
36
37 // Comparing the work area to the screen bounds gives us the location of the
38 // taskbar. If the work area is exactly the same as the screen bounds,
39 // we are unable to locate the systray so we say we don't know it's alignment.
40 if (work_area.height() < screen_bounds.height()) {
41 if (work_area.y() > screen_bounds.y())
42 return ALIGNMENT_TOP;
43 return ALIGNMENT_BOTTOM;
44 }
45 if (work_area.width() < screen_bounds.width()) {
46 if (work_area.x() > screen_bounds.x())
47 return ALIGNMENT_LEFT;
48 return ALIGNMENT_RIGHT;
49 }
50
51 return ALIGNMENT_NONE;
52 }
53
54 gfx::Point GetClosestCorner(const gfx::Rect& rect, const gfx::Point& query) {
55 gfx::Point center_point = rect.CenterPoint();
56 gfx::Point rv;
57
58 if (query.x() > center_point.x())
59 rv.set_x(rect.right());
60 else
61 rv.set_x(rect.x());
62
63 if (query.y() > center_point.y())
64 rv.set_y(rect.bottom());
65 else
66 rv.set_y(rect.y());
67
68 return rv;
69 }
70
71 // Gets the corner of the screen where the message center should pop up.
72 Alignment GetAnchorAlignment(const gfx::Rect& work_area, gfx::Point corner) {
73 gfx::Point center = work_area.CenterPoint();
74
75 Alignment anchor_alignment =
76 center.y() > corner.y() ? ALIGNMENT_TOP : ALIGNMENT_BOTTOM;
77 anchor_alignment =
78 (Alignment)(anchor_alignment |
79 (center.x() > corner.x() ? ALIGNMENT_LEFT : ALIGNMENT_RIGHT));
80
81 return anchor_alignment;
82 }
83
84 } // namespace internal
85
86 MessageCenterWidgetDelegate::MessageCenterWidgetDelegate(
87 WebNotificationTray* tray,
88 MessageCenterTray* mc_tray,
89 bool initially_settings_visible)
90 : MessageCenterView(tray->message_center(),
91 mc_tray,
92 initially_settings_visible),
93 color_explicitly_set_(false),
94 close_on_esc_(true),
95 close_on_deactivate_(true),
96 tray_(tray) {
97
98 PositionAnchor();
99 MessageCenterView::Init(max_height_);
100
101 min_width_ = max_width_ = kNotificationWidth;
dewittj 2013/06/28 01:13:18 Why not just have 'width_'?
sidharthms 2013/07/02 18:09:51 Done.
102 if (IsRichNotificationEnabled()) {
103 min_width_ += kMarginBetweenItems * 2;
104 max_width_ += kMarginBetweenItems * 2;
105 }
106 preferred_width_ = min_width_;
107
108 views::BoxLayout* layout =
109 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
110 layout->set_spread_blank_space(true);
111 SetLayoutManager(layout);
112
113 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
114 UpdateColorsFromTheme(GetNativeTheme());
115
116 if (get_use_acceleration_when_possible()) {
117 SetPaintToLayer(true);
118 SetFillsBoundsOpaquely(true);
119 }
120
121 InitWidget();
122 UpdateNotifications();
123 }
124
125 MessageCenterWidgetDelegate::~MessageCenterWidgetDelegate() {
126 views::Widget* widget = GetWidget();
127 if (widget) {
128 widget->RemoveObserver(this);
129 }
130 }
131
132 views::View* MessageCenterWidgetDelegate::GetContentsView() {
133 return this;
134 }
135
136 views::NonClientFrameView*
137 MessageCenterWidgetDelegate::CreateNonClientFrameView(views::Widget* widget) {
138 return new MessageCenterFrameView(kBorderWidth);
139 }
140
141 views::Widget* MessageCenterWidgetDelegate::GetWidget() {
142 return View::GetWidget();
143 }
144
145 const views::Widget* MessageCenterWidgetDelegate::GetWidget() const {
146 return View::GetWidget();
147 }
148
149 void MessageCenterWidgetDelegate::OnWidgetActivationChanged(
150 views::Widget* widget,
151 bool active) {
152 if (close_on_deactivate() && !active)
153 tray_->HideBubble();
154 }
155
156 void MessageCenterWidgetDelegate::PreferredSizeChanged() {
157 GetWidget()->SetBounds(GetBubbleBounds());
158 views::View::PreferredSizeChanged();
159 }
160
161 gfx::Size MessageCenterWidgetDelegate::GetPreferredSize() {
162 gfx::Size size =
163 gfx::Size(preferred_width_, GetHeightForWidth(preferred_width_));
164
165 // Make space for borders on sides.
166 size.Enlarge(2 * kBorderWidth, 2 * kBorderWidth);
167 return size;
168 }
169
170 gfx::Size MessageCenterWidgetDelegate::GetMaximumSize() {
171 gfx::Size size = GetPreferredSize();
172 size.set_width(max_width_);
173 return size;
174 }
175
176 int MessageCenterWidgetDelegate::GetHeightForWidth(int width) {
177 int height = MessageCenterView::GetHeightForWidth(width);
178 return (max_height_ != 0) ? std::min(height, max_height_) : height;
179 }
180 bool MessageCenterWidgetDelegate::AcceleratorPressed(
181 const ui::Accelerator& accelerator) {
182 if (!close_on_esc() || accelerator.key_code() != ui::VKEY_ESCAPE)
183 return false;
184 if (fade_animation_.get())
185 fade_animation_->Reset();
186 GetWidget()->Close();
187 return true;
188 }
189
190 void MessageCenterWidgetDelegate::OnNativeThemeChanged(
191 const ui::NativeTheme* theme) {
192 UpdateColorsFromTheme(theme);
193 }
194
195 void MessageCenterWidgetDelegate::InitWidget() {
196 views::Widget* widget = new views::Widget();
197 views::Widget::InitParams params(views::Widget::InitParams::TYPE_BUBBLE);
198 params.delegate = this;
199 params.keep_on_top = true;
200 params.top_level = true;
201 #if defined(OS_WIN) && !defined(USE_AURA)
202 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
203 #endif
204 widget->Init(params);
205
206 widget->AddObserver(this);
207 widget->StackAtTop();
208
209 // Popups should appear on top of everything, but not disturb the user's
210 // focus since they could appear at any time. Message Center is always
211 // shown as a result of user action so it can be activated here.
212 widget->SetAlwaysOnTop(true);
213 widget->Activate();
214 }
215
216 void MessageCenterWidgetDelegate::CloseWidget() {
217 GetWidget()->Close();
218 }
219
220 void MessageCenterWidgetDelegate::UpdateColorsFromTheme(
221 const ui::NativeTheme* theme) {
222 if (!color_explicitly_set_) {
223 color_ = GetNativeTheme()->GetSystemColor(
224 ui::NativeTheme::kColorId_WindowBackground);
225 }
226 set_background(views::Background::CreateSolidBackground(color()));
227 }
228
229 void MessageCenterWidgetDelegate::UpdateNotifications() {
230 const NotificationList::Notifications& notifications =
231 tray_->message_center()->GetNotifications();
232 SetNotifications(notifications);
233 GetWidget()->Show();
234 GetWidget()->SetBounds(GetBubbleBounds());
235 GetWidget()->GetRootView()->SchedulePaint();
236 }
237
238 MessageCenterFrameView* MessageCenterWidgetDelegate::GetBubbleFrameView()
239 const {
240 const views::Widget* widget = GetWidget();
241 const views::NonClientView* view = widget ? widget->non_client_view() : NULL;
242 return view ? static_cast<MessageCenterFrameView*>(view->frame_view()) : NULL;
243 }
244
245 gfx::Rect MessageCenterWidgetDelegate::GetBubbleBounds() {
246 const gfx::Size size = GetPreferredSize();
247 gfx::Rect bounds(size);
248
249 gfx::Point corrected_anchor = GetCorrectedAnchor(size);
250
251 if (bubble_alignment_ & ALIGNMENT_TOP)
252 bounds.set_y(corrected_anchor.y());
253 if (bubble_alignment_ & ALIGNMENT_BOTTOM)
254 bounds.set_y(corrected_anchor.y() - size.height());
255 if (bubble_alignment_ & ALIGNMENT_LEFT)
256 bounds.set_x(corrected_anchor.x());
257 if (bubble_alignment_ & ALIGNMENT_RIGHT)
258 bounds.set_x(corrected_anchor.x() - size.width());
259
260 return bounds;
261 }
262
263 void MessageCenterWidgetDelegate::AnimationEnded(
264 const ui::Animation* animation) {
265 if (animation == fade_animation_.get()) {
266 bool closed = fade_animation_->GetCurrentValue() == 0;
267 fade_animation_->Reset();
268 if (closed)
269 GetWidget()->Close();
270 }
271 MessageCenterView::AnimationEnded(animation);
272 }
273
274 void MessageCenterWidgetDelegate::AnimationProgressed(
275 const ui::Animation* animation) {
276 if (animation == fade_animation_.get()) {
277 DCHECK(fade_animation_->is_animating());
278 unsigned char opacity = fade_animation_->GetCurrentValue() * 255;
279 #if defined(OS_WIN) && !defined(USE_AURA)
280 // Explicitly set the content Widget's layered style and set transparency
281 // via SetLayeredWindowAttributes. This is done because initializing the
282 // Widget as transparent and setting opacity via UpdateLayeredWindow doesn't
283 // support hosting child native Windows controls.
284 const HWND hwnd = GetWidget()->GetNativeView();
285 const DWORD style = GetWindowLong(hwnd, GWL_EXSTYLE);
286 if ((opacity == 255) == !!(style & WS_EX_LAYERED))
287 SetWindowLong(hwnd, GWL_EXSTYLE, style ^ WS_EX_LAYERED);
288 SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA);
289 #endif
290 GetWidget()->SetOpacity(opacity);
291 }
292 MessageCenterView::AnimationProgressed(animation);
293 }
294
295 gfx::Point MessageCenterWidgetDelegate::GetCorrectedAnchor(
296 gfx::Size calculated_size) {
297 gfx::Point corrected_anchor = inital_anchor_point_;
298
299 // Inset the width slightly so that the click point is not exactly on the edge
300 // of the message center but somewhere within the middle 60 %.
301 int insetted_width = (calculated_size.width() * 4) / 5;
302
303 if (systray_alignment_ == ALIGNMENT_TOP ||
304 systray_alignment_ == ALIGNMENT_BOTTOM) {
305 int click_point_x = tray_->mouse_click_point().x();
306
307 if (bubble_alignment_ & ALIGNMENT_RIGHT) {
308 int opposite_x_corner = inital_anchor_point_.x() - insetted_width;
309
310 // If the click point is outside the x axis length of the message center,
311 // push the message center towards the LEFT to align with the click point.
312 if (opposite_x_corner > click_point_x)
313 corrected_anchor.set_x(inital_anchor_point_.x() -
314 (opposite_x_corner - click_point_x));
315 } else {
316 int opposite_x_corner = inital_anchor_point_.x() + insetted_width;
317
318 if (opposite_x_corner < click_point_x)
319 corrected_anchor.set_x(inital_anchor_point_.x() +
320 (click_point_x - opposite_x_corner));
321 }
322 } else if (systray_alignment_ == ALIGNMENT_LEFT ||
323 systray_alignment_ == ALIGNMENT_RIGHT) {
324 int click_point_y = tray_->mouse_click_point().y();
325
326 if (bubble_alignment_ & ALIGNMENT_BOTTOM) {
327 int opposite_y_corner = inital_anchor_point_.y() - insetted_width;
328
329 // If the click point is outside the y axis length of the message center,
330 // push the message center UPWARDS to align with the click point.
331 if (opposite_y_corner > click_point_y)
332 corrected_anchor.set_y(inital_anchor_point_.y() -
333 (opposite_y_corner - click_point_y));
334 } else {
335 int opposite_y_corner = inital_anchor_point_.y() + insetted_width;
336
337 if (opposite_y_corner < click_point_y)
338 corrected_anchor.set_y(inital_anchor_point_.y() +
339 (click_point_y - opposite_y_corner));
340 }
341 }
342 return corrected_anchor;
343 }
344
345 void MessageCenterWidgetDelegate::PositionAnchor() {
346 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
347 gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
348 gfx::Point mouse_click_point = tray_->mouse_click_point();
349 gfx::Point corner = internal::GetClosestCorner(work_area, mouse_click_point);
350
351 systray_alignment_ = internal::GetSystrayAlignment();
352
353 // We assume the systray and taskbar are either at the top or at the bottom
354 // if we are not able to find it.
355 if (systray_alignment_ == ALIGNMENT_NONE) {
356 if (mouse_click_point.y() > corner.y())
357 systray_alignment_ = ALIGNMENT_TOP;
358 else
359 systray_alignment_ = ALIGNMENT_BOTTOM;
360 }
361
362 bubble_alignment_ = internal::GetAnchorAlignment(work_area, corner);
363
364 inital_anchor_point_ = corner;
365 max_height_ = work_area.height();
366
367 if (work_area.Contains(mouse_click_point)) {
368 inital_anchor_point_.set_y(mouse_click_point.y());
369 max_height_ -= std::abs(mouse_click_point.y() - corner.y());
dewittj 2013/06/28 01:13:18 #include <complex>
sidharthms 2013/07/02 18:09:51 Done.
370 }
371 }
372
373 } // namespace message_center
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698