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

Unified 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, 6 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/message_center/message_center_widget_delegate.cc
diff --git a/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc b/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6bcb8d7c54004c46bda9723a001efc7f4e5ee00d
--- /dev/null
+++ b/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc
@@ -0,0 +1,373 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/message_center/message_center_widget_delegate.h"
+
+#include "chrome/browser/ui/views/message_center/message_center_frame_view.h"
+#include "content/public/browser/user_metrics.h"
+#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/gfx/screen.h"
+#include "ui/message_center/message_center_style.h"
+#include "ui/message_center/message_center_util.h"
+#include "ui/message_center/views/message_center_view.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/views/border.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+const int kBorderWidth = 1;
+
+} // namespace
+
+namespace message_center {
+
+namespace internal {
+
+// Gets the position of the systray (same as position of taskbar) from the
+// work area bounds. Returns ALIGNMENT_NONE if position cannot be found.
+Alignment GetSystrayAlignment() {
+ gfx::Screen* screen = gfx::Screen::GetNativeScreen();
+ // TODO(dewittj): It's possible GetPrimaryDisplay is wrong.
+ gfx::Rect screen_bounds = screen->GetPrimaryDisplay().bounds();
+ gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
+
+ // Comparing the work area to the screen bounds gives us the location of the
+ // taskbar. If the work area is exactly the same as the screen bounds,
+ // we are unable to locate the systray so we say we don't know it's alignment.
+ if (work_area.height() < screen_bounds.height()) {
+ if (work_area.y() > screen_bounds.y())
+ return ALIGNMENT_TOP;
+ return ALIGNMENT_BOTTOM;
+ }
+ if (work_area.width() < screen_bounds.width()) {
+ if (work_area.x() > screen_bounds.x())
+ return ALIGNMENT_LEFT;
+ return ALIGNMENT_RIGHT;
+ }
+
+ return ALIGNMENT_NONE;
+}
+
+gfx::Point GetClosestCorner(const gfx::Rect& rect, const gfx::Point& query) {
+ gfx::Point center_point = rect.CenterPoint();
+ gfx::Point rv;
+
+ if (query.x() > center_point.x())
+ rv.set_x(rect.right());
+ else
+ rv.set_x(rect.x());
+
+ if (query.y() > center_point.y())
+ rv.set_y(rect.bottom());
+ else
+ rv.set_y(rect.y());
+
+ return rv;
+}
+
+// Gets the corner of the screen where the message center should pop up.
+Alignment GetAnchorAlignment(const gfx::Rect& work_area, gfx::Point corner) {
+ gfx::Point center = work_area.CenterPoint();
+
+ Alignment anchor_alignment =
+ center.y() > corner.y() ? ALIGNMENT_TOP : ALIGNMENT_BOTTOM;
+ anchor_alignment =
+ (Alignment)(anchor_alignment |
+ (center.x() > corner.x() ? ALIGNMENT_LEFT : ALIGNMENT_RIGHT));
+
+ return anchor_alignment;
+}
+
+} // namespace internal
+
+MessageCenterWidgetDelegate::MessageCenterWidgetDelegate(
+ WebNotificationTray* tray,
+ MessageCenterTray* mc_tray,
+ bool initially_settings_visible)
+ : MessageCenterView(tray->message_center(),
+ mc_tray,
+ initially_settings_visible),
+ color_explicitly_set_(false),
+ close_on_esc_(true),
+ close_on_deactivate_(true),
+ tray_(tray) {
+
+ PositionAnchor();
+ MessageCenterView::Init(max_height_);
+
+ 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.
+ if (IsRichNotificationEnabled()) {
+ min_width_ += kMarginBetweenItems * 2;
+ max_width_ += kMarginBetweenItems * 2;
+ }
+ preferred_width_ = min_width_;
+
+ views::BoxLayout* layout =
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
+ layout->set_spread_blank_space(true);
+ SetLayoutManager(layout);
+
+ AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
+ UpdateColorsFromTheme(GetNativeTheme());
+
+ if (get_use_acceleration_when_possible()) {
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(true);
+ }
+
+ InitWidget();
+ UpdateNotifications();
+}
+
+MessageCenterWidgetDelegate::~MessageCenterWidgetDelegate() {
+ views::Widget* widget = GetWidget();
+ if (widget) {
+ widget->RemoveObserver(this);
+ }
+}
+
+views::View* MessageCenterWidgetDelegate::GetContentsView() {
+ return this;
+}
+
+views::NonClientFrameView*
+MessageCenterWidgetDelegate::CreateNonClientFrameView(views::Widget* widget) {
+ return new MessageCenterFrameView(kBorderWidth);
+}
+
+views::Widget* MessageCenterWidgetDelegate::GetWidget() {
+ return View::GetWidget();
+}
+
+const views::Widget* MessageCenterWidgetDelegate::GetWidget() const {
+ return View::GetWidget();
+}
+
+void MessageCenterWidgetDelegate::OnWidgetActivationChanged(
+ views::Widget* widget,
+ bool active) {
+ if (close_on_deactivate() && !active)
+ tray_->HideBubble();
+}
+
+void MessageCenterWidgetDelegate::PreferredSizeChanged() {
+ GetWidget()->SetBounds(GetBubbleBounds());
+ views::View::PreferredSizeChanged();
+}
+
+gfx::Size MessageCenterWidgetDelegate::GetPreferredSize() {
+ gfx::Size size =
+ gfx::Size(preferred_width_, GetHeightForWidth(preferred_width_));
+
+ // Make space for borders on sides.
+ size.Enlarge(2 * kBorderWidth, 2 * kBorderWidth);
+ return size;
+}
+
+gfx::Size MessageCenterWidgetDelegate::GetMaximumSize() {
+ gfx::Size size = GetPreferredSize();
+ size.set_width(max_width_);
+ return size;
+}
+
+int MessageCenterWidgetDelegate::GetHeightForWidth(int width) {
+ int height = MessageCenterView::GetHeightForWidth(width);
+ return (max_height_ != 0) ? std::min(height, max_height_) : height;
+}
+bool MessageCenterWidgetDelegate::AcceleratorPressed(
+ const ui::Accelerator& accelerator) {
+ if (!close_on_esc() || accelerator.key_code() != ui::VKEY_ESCAPE)
+ return false;
+ if (fade_animation_.get())
+ fade_animation_->Reset();
+ GetWidget()->Close();
+ return true;
+}
+
+void MessageCenterWidgetDelegate::OnNativeThemeChanged(
+ const ui::NativeTheme* theme) {
+ UpdateColorsFromTheme(theme);
+}
+
+void MessageCenterWidgetDelegate::InitWidget() {
+ views::Widget* widget = new views::Widget();
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_BUBBLE);
+ params.delegate = this;
+ params.keep_on_top = true;
+ params.top_level = true;
+#if defined(OS_WIN) && !defined(USE_AURA)
+ params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
+#endif
+ widget->Init(params);
+
+ widget->AddObserver(this);
+ widget->StackAtTop();
+
+ // Popups should appear on top of everything, but not disturb the user's
+ // focus since they could appear at any time. Message Center is always
+ // shown as a result of user action so it can be activated here.
+ widget->SetAlwaysOnTop(true);
+ widget->Activate();
+}
+
+void MessageCenterWidgetDelegate::CloseWidget() {
+ GetWidget()->Close();
+}
+
+void MessageCenterWidgetDelegate::UpdateColorsFromTheme(
+ const ui::NativeTheme* theme) {
+ if (!color_explicitly_set_) {
+ color_ = GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_WindowBackground);
+ }
+ set_background(views::Background::CreateSolidBackground(color()));
+}
+
+void MessageCenterWidgetDelegate::UpdateNotifications() {
+ const NotificationList::Notifications& notifications =
+ tray_->message_center()->GetNotifications();
+ SetNotifications(notifications);
+ GetWidget()->Show();
+ GetWidget()->SetBounds(GetBubbleBounds());
+ GetWidget()->GetRootView()->SchedulePaint();
+}
+
+MessageCenterFrameView* MessageCenterWidgetDelegate::GetBubbleFrameView()
+ const {
+ const views::Widget* widget = GetWidget();
+ const views::NonClientView* view = widget ? widget->non_client_view() : NULL;
+ return view ? static_cast<MessageCenterFrameView*>(view->frame_view()) : NULL;
+}
+
+gfx::Rect MessageCenterWidgetDelegate::GetBubbleBounds() {
+ const gfx::Size size = GetPreferredSize();
+ gfx::Rect bounds(size);
+
+ gfx::Point corrected_anchor = GetCorrectedAnchor(size);
+
+ if (bubble_alignment_ & ALIGNMENT_TOP)
+ bounds.set_y(corrected_anchor.y());
+ if (bubble_alignment_ & ALIGNMENT_BOTTOM)
+ bounds.set_y(corrected_anchor.y() - size.height());
+ if (bubble_alignment_ & ALIGNMENT_LEFT)
+ bounds.set_x(corrected_anchor.x());
+ if (bubble_alignment_ & ALIGNMENT_RIGHT)
+ bounds.set_x(corrected_anchor.x() - size.width());
+
+ return bounds;
+}
+
+void MessageCenterWidgetDelegate::AnimationEnded(
+ const ui::Animation* animation) {
+ if (animation == fade_animation_.get()) {
+ bool closed = fade_animation_->GetCurrentValue() == 0;
+ fade_animation_->Reset();
+ if (closed)
+ GetWidget()->Close();
+ }
+ MessageCenterView::AnimationEnded(animation);
+}
+
+void MessageCenterWidgetDelegate::AnimationProgressed(
+ const ui::Animation* animation) {
+ if (animation == fade_animation_.get()) {
+ DCHECK(fade_animation_->is_animating());
+ unsigned char opacity = fade_animation_->GetCurrentValue() * 255;
+#if defined(OS_WIN) && !defined(USE_AURA)
+ // Explicitly set the content Widget's layered style and set transparency
+ // via SetLayeredWindowAttributes. This is done because initializing the
+ // Widget as transparent and setting opacity via UpdateLayeredWindow doesn't
+ // support hosting child native Windows controls.
+ const HWND hwnd = GetWidget()->GetNativeView();
+ const DWORD style = GetWindowLong(hwnd, GWL_EXSTYLE);
+ if ((opacity == 255) == !!(style & WS_EX_LAYERED))
+ SetWindowLong(hwnd, GWL_EXSTYLE, style ^ WS_EX_LAYERED);
+ SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA);
+#endif
+ GetWidget()->SetOpacity(opacity);
+ }
+ MessageCenterView::AnimationProgressed(animation);
+}
+
+gfx::Point MessageCenterWidgetDelegate::GetCorrectedAnchor(
+ gfx::Size calculated_size) {
+ gfx::Point corrected_anchor = inital_anchor_point_;
+
+ // Inset the width slightly so that the click point is not exactly on the edge
+ // of the message center but somewhere within the middle 60 %.
+ int insetted_width = (calculated_size.width() * 4) / 5;
+
+ if (systray_alignment_ == ALIGNMENT_TOP ||
+ systray_alignment_ == ALIGNMENT_BOTTOM) {
+ int click_point_x = tray_->mouse_click_point().x();
+
+ if (bubble_alignment_ & ALIGNMENT_RIGHT) {
+ int opposite_x_corner = inital_anchor_point_.x() - insetted_width;
+
+ // If the click point is outside the x axis length of the message center,
+ // push the message center towards the LEFT to align with the click point.
+ if (opposite_x_corner > click_point_x)
+ corrected_anchor.set_x(inital_anchor_point_.x() -
+ (opposite_x_corner - click_point_x));
+ } else {
+ int opposite_x_corner = inital_anchor_point_.x() + insetted_width;
+
+ if (opposite_x_corner < click_point_x)
+ corrected_anchor.set_x(inital_anchor_point_.x() +
+ (click_point_x - opposite_x_corner));
+ }
+ } else if (systray_alignment_ == ALIGNMENT_LEFT ||
+ systray_alignment_ == ALIGNMENT_RIGHT) {
+ int click_point_y = tray_->mouse_click_point().y();
+
+ if (bubble_alignment_ & ALIGNMENT_BOTTOM) {
+ int opposite_y_corner = inital_anchor_point_.y() - insetted_width;
+
+ // If the click point is outside the y axis length of the message center,
+ // push the message center UPWARDS to align with the click point.
+ if (opposite_y_corner > click_point_y)
+ corrected_anchor.set_y(inital_anchor_point_.y() -
+ (opposite_y_corner - click_point_y));
+ } else {
+ int opposite_y_corner = inital_anchor_point_.y() + insetted_width;
+
+ if (opposite_y_corner < click_point_y)
+ corrected_anchor.set_y(inital_anchor_point_.y() +
+ (click_point_y - opposite_y_corner));
+ }
+ }
+ return corrected_anchor;
+}
+
+void MessageCenterWidgetDelegate::PositionAnchor() {
+ gfx::Screen* screen = gfx::Screen::GetNativeScreen();
+ gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
+ gfx::Point mouse_click_point = tray_->mouse_click_point();
+ gfx::Point corner = internal::GetClosestCorner(work_area, mouse_click_point);
+
+ systray_alignment_ = internal::GetSystrayAlignment();
+
+ // We assume the systray and taskbar are either at the top or at the bottom
+ // if we are not able to find it.
+ if (systray_alignment_ == ALIGNMENT_NONE) {
+ if (mouse_click_point.y() > corner.y())
+ systray_alignment_ = ALIGNMENT_TOP;
+ else
+ systray_alignment_ = ALIGNMENT_BOTTOM;
+ }
+
+ bubble_alignment_ = internal::GetAnchorAlignment(work_area, corner);
+
+ inital_anchor_point_ = corner;
+ max_height_ = work_area.height();
+
+ if (work_area.Contains(mouse_click_point)) {
+ inital_anchor_point_.set_y(mouse_click_point.y());
+ 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.
+ }
+}
+
+} // namespace message_center

Powered by Google App Engine
This is Rietveld 408576698