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

Unified Diff: chrome/browser/ui/views/notifications/balloon_view_views.cc

Issue 231213003: notification balloons: Remove views and cocoa implementations of BalloonCollection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 8 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
« no previous file with comments | « chrome/browser/ui/views/notifications/balloon_view_views.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/views/notifications/balloon_view_views.cc
diff --git a/chrome/browser/ui/views/notifications/balloon_view_views.cc b/chrome/browser/ui/views/notifications/balloon_view_views.cc
deleted file mode 100644
index 551a68198d93edafc8a9d24f196013b82c9a70e8..0000000000000000000000000000000000000000
--- a/chrome/browser/ui/views/notifications/balloon_view_views.cc
+++ /dev/null
@@ -1,531 +0,0 @@
-// Copyright (c) 2012 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/notifications/balloon_view_views.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/notifications/balloon_collection.h"
-#include "chrome/browser/notifications/desktop_notification_service.h"
-#include "chrome/browser/notifications/notification.h"
-#include "chrome/browser/notifications/notification_options_menu_model.h"
-#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/animation/slide_animation.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/path.h"
-#include "ui/views/bubble/bubble_border.h"
-#include "ui/views/controls/button/image_button.h"
-#include "ui/views/controls/button/menu_button.h"
-#include "ui/views/controls/button/text_button.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/controls/menu/menu_item_view.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/native/native_view_host.h"
-#include "ui/views/widget/widget.h"
-
-namespace {
-
-const int kTopMargin = 2;
-const int kBottomMargin = 0;
-const int kLeftMargin = 4;
-const int kRightMargin = 4;
-
-// Margin between various shelf buttons/label and the shelf border.
-const int kShelfMargin = 2;
-
-// Spacing between the options and close buttons.
-const int kOptionsDismissSpacing = 4;
-
-// Spacing between the options button and label text.
-const int kLabelOptionsSpacing = 4;
-
-// Margin between shelf border and title label.
-const int kLabelLeftMargin = 6;
-
-// Size of the drop shadow. The shadow is provided by BubbleBorder,
-// not this class.
-const int kLeftShadowWidth = 0;
-const int kRightShadowWidth = 0;
-const int kTopShadowWidth = 0;
-const int kBottomShadowWidth = 6;
-
-// Optional animation.
-const bool kAnimateEnabled = true;
-
-// Colors
-const SkColor kControlBarBackgroundColor = SkColorSetRGB(245, 245, 245);
-const SkColor kControlBarTextColor = SkColorSetRGB(125, 125, 125);
-const SkColor kControlBarSeparatorLineColor = SkColorSetRGB(180, 180, 180);
-
-} // namespace
-
-// static
-int BalloonView::GetHorizontalMargin() {
- return kLeftMargin + kRightMargin + kLeftShadowWidth + kRightShadowWidth;
-}
-
-BalloonViewImpl::BalloonViewImpl(BalloonCollection* collection)
- : balloon_(NULL),
- collection_(collection),
- frame_container_(NULL),
- html_container_(NULL),
- close_button_(NULL),
- options_menu_button_(NULL),
- enable_web_ui_(false),
- closed_by_user_(false),
- closed_(false) {
- // We're owned by Balloon and don't want to be deleted by our parent View.
- set_owned_by_client();
-
- SetBorder(scoped_ptr<views::Border>(
- new views::BubbleBorder(views::BubbleBorder::FLOAT,
- views::BubbleBorder::NO_SHADOW,
- SK_ColorWHITE)));
-}
-
-BalloonViewImpl::~BalloonViewImpl() {
-}
-
-void BalloonViewImpl::Close(bool by_user) {
- if (closed_)
- return;
-
- closed_ = true;
- animation_->Stop();
- html_contents_->Shutdown();
- // Detach contents from the widget before they close.
- // This is necessary because a widget may be deleted
- // after this when chrome is shutting down.
- html_container_->GetRootView()->RemoveAllChildViews(true);
- html_container_->Close();
- frame_container_->GetRootView()->RemoveAllChildViews(true);
- frame_container_->Close();
- closed_by_user_ = by_user;
- // |frame_container_->::Close()| is async. When processed it'll call back to
- // DeleteDelegate() and we'll cleanup.
-}
-
-gfx::Size BalloonViewImpl::GetSize() const {
- // BalloonView has no size if it hasn't been shown yet (which is when
- // balloon_ is set).
- if (!balloon_)
- return gfx::Size(0, 0);
-
- return gfx::Size(GetTotalWidth(), GetTotalHeight());
-}
-
-BalloonHost* BalloonViewImpl::GetHost() const {
- return html_contents_.get();
-}
-
-void BalloonViewImpl::OnMenuButtonClicked(views::View* source,
- const gfx::Point& point) {
- CreateOptionsMenu();
-
- menu_runner_.reset(new views::MenuRunner(options_menu_model_.get()));
-
- gfx::Point screen_location;
- views::View::ConvertPointToScreen(options_menu_button_, &screen_location);
- if (menu_runner_->RunMenuAt(
- source->GetWidget()->GetTopLevelWidget(),
- options_menu_button_,
- gfx::Rect(screen_location, options_menu_button_->size()),
- views::MenuItemView::TOPRIGHT,
- ui::MENU_SOURCE_NONE,
- views::MenuRunner::HAS_MNEMONICS) == views::MenuRunner::MENU_DELETED)
- return;
-}
-
-void BalloonViewImpl::OnDisplayChanged() {
- collection_->DisplayChanged();
-}
-
-void BalloonViewImpl::OnWorkAreaChanged() {
- collection_->DisplayChanged();
-}
-
-void BalloonViewImpl::DeleteDelegate() {
- balloon_->OnClose(closed_by_user_);
-}
-
-void BalloonViewImpl::ButtonPressed(views::Button* sender, const ui::Event&) {
- // The only button currently is the close button.
- DCHECK_EQ(close_button_, sender);
- Close(true);
-}
-
-gfx::Size BalloonViewImpl::GetPreferredSize() {
- return gfx::Size(1000, 1000);
-}
-
-void BalloonViewImpl::SizeContentsWindow() {
- if (!html_container_ || !frame_container_)
- return;
-
- gfx::Rect contents_rect = GetContentsRectangle();
- html_container_->SetBounds(contents_rect);
- html_container_->StackAboveWidget(frame_container_);
-
- gfx::Path path;
- GetContentsMask(contents_rect, &path);
- html_container_->SetShape(path.CreateNativeRegion());
-
- close_button_->SetBoundsRect(GetCloseButtonBounds());
- options_menu_button_->SetBoundsRect(GetOptionsButtonBounds());
- source_label_->SetBoundsRect(GetLabelBounds());
-}
-
-void BalloonViewImpl::RepositionToBalloon() {
- if (closed_)
- return;
-
- DCHECK(frame_container_);
- DCHECK(html_container_);
- DCHECK(balloon_);
-
- if (!kAnimateEnabled) {
- frame_container_->SetBounds(GetBoundsForFrameContainer());
- gfx::Rect contents_rect = GetContentsRectangle();
- html_container_->SetBounds(contents_rect);
- html_contents_->SetPreferredSize(contents_rect.size());
- content::RenderWidgetHostView* view =
- html_contents_->web_contents()->GetRenderWidgetHostView();
- if (view)
- view->SetSize(contents_rect.size());
- return;
- }
-
- anim_frame_end_ = GetBoundsForFrameContainer();
- anim_frame_start_ = frame_container_->GetClientAreaBoundsInScreen();
- animation_.reset(new gfx::SlideAnimation(this));
- animation_->Show();
-}
-
-void BalloonViewImpl::Update() {
- if (closed_)
- return;
-
- // Tls might get called before html_contents_ is set in Show() if more than
- // one update with the same replace_id occurs, or if an update occurs after
- // the ballon has been closed (e.g. during shutdown) but before this has been
- // destroyed.
- if (!html_contents_.get() || !html_contents_->web_contents())
- return;
- html_contents_->web_contents()->GetController().LoadURL(
- balloon_->notification().content_url(), content::Referrer(),
- content::PAGE_TRANSITION_LINK, std::string());
-}
-
-void BalloonViewImpl::AnimationProgressed(const gfx::Animation* animation) {
- DCHECK_EQ(animation_.get(), animation);
-
- // Linear interpolation from start to end position.
- gfx::Rect frame_position(animation_->CurrentValueBetween(
- anim_frame_start_, anim_frame_end_));
- frame_container_->SetBounds(frame_position);
-
- gfx::Path path;
- gfx::Rect contents_rect = GetContentsRectangle();
- html_container_->SetBounds(contents_rect);
- GetContentsMask(contents_rect, &path);
- html_container_->SetShape(path.CreateNativeRegion());
-
- html_contents_->SetPreferredSize(contents_rect.size());
- content::RenderWidgetHostView* view =
- html_contents_->web_contents()->GetRenderWidgetHostView();
- if (view)
- view->SetSize(contents_rect.size());
-}
-
-gfx::Rect BalloonViewImpl::GetCloseButtonBounds() const {
- gfx::Rect bounds(GetContentsBounds());
- bounds.set_height(GetShelfHeight());
- const gfx::Size& pref_size(close_button_->GetPreferredSize());
- bounds.Inset(bounds.width() - kShelfMargin - pref_size.width(), 0,
- kShelfMargin, 0);
- bounds.ClampToCenteredSize(pref_size);
- return bounds;
-}
-
-gfx::Rect BalloonViewImpl::GetOptionsButtonBounds() const {
- gfx::Rect bounds(GetContentsBounds());
- bounds.set_height(GetShelfHeight());
- const gfx::Size& pref_size(options_menu_button_->GetPreferredSize());
- bounds.set_x(GetCloseButtonBounds().x() - kOptionsDismissSpacing -
- pref_size.width());
- bounds.set_width(pref_size.width());
- bounds.ClampToCenteredSize(pref_size);
- return bounds;
-}
-
-gfx::Rect BalloonViewImpl::GetLabelBounds() const {
- gfx::Rect bounds(GetContentsBounds());
- bounds.set_height(GetShelfHeight());
- gfx::Size pref_size(source_label_->GetPreferredSize());
- bounds.Inset(kLabelLeftMargin, 0, bounds.width() -
- GetOptionsButtonBounds().x() + kLabelOptionsSpacing, 0);
- pref_size.set_width(bounds.width());
- bounds.ClampToCenteredSize(pref_size);
- return bounds;
-}
-
-void BalloonViewImpl::Show(Balloon* balloon) {
- if (closed_)
- return;
-
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-
- balloon_ = balloon;
-
- const base::string16 source_label_text = l10n_util::GetStringFUTF16(
- IDS_NOTIFICATION_BALLOON_SOURCE_LABEL,
- balloon->notification().display_source());
-
- source_label_ = new views::Label(source_label_text);
- AddChildView(source_label_);
- options_menu_button_ =
- new views::MenuButton(NULL, base::string16(), this, false);
- AddChildView(options_menu_button_);
- close_button_ = new views::ImageButton(this);
- close_button_->SetTooltipText(l10n_util::GetStringUTF16(
- IDS_NOTIFICATION_BALLOON_DISMISS_LABEL));
- AddChildView(close_button_);
-
- // We have to create two windows: one for the contents and one for the
- // frame. Why?
- // * The contents is an html window which cannot be a
- // layered window (because it may have child windows for instance).
- // * The frame is a layered window so that we can have nicely rounded
- // corners using alpha blending (and we may do other alpha blending
- // effects).
- // Unfortunately, layered windows cannot have child windows. (Well, they can
- // but the child windows don't render).
- //
- // We carefully keep these two windows in sync to present the illusion of
- // one window to the user.
- //
- // We don't let the OS manage the RTL layout of these widgets, because
- // this code is already taking care of correctly reversing the layout.
- html_contents_.reset(new BalloonViewHost(balloon));
- html_contents_->SetPreferredSize(gfx::Size(10000, 10000));
- if (enable_web_ui_)
- html_contents_->EnableWebUI();
-
- html_container_ = new views::Widget;
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- html_container_->Init(params);
- html_container_->SetContentsView(html_contents_->view());
-
- frame_container_ = new views::Widget;
- params.delegate = this;
- params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
- params.bounds = GetBoundsForFrameContainer();
- frame_container_->Init(params);
- frame_container_->SetContentsView(this);
- frame_container_->StackAboveWidget(html_container_);
-
- // GetContentsRectangle() is calculated relative to |frame_container_|. Make
- // sure |frame_container_| has bounds before we ask for
- // GetContentsRectangle().
- html_container_->SetBounds(GetContentsRectangle());
-
- // SetAlwaysOnTop should be called after StackAboveWidget because otherwise
- // the top-most flag will be removed.
- html_container_->SetAlwaysOnTop(true);
- frame_container_->SetAlwaysOnTop(true);
-
- close_button_->SetImage(views::CustomButton::STATE_NORMAL,
- rb.GetImageSkiaNamed(IDR_CLOSE_1));
- close_button_->SetImage(views::CustomButton::STATE_HOVERED,
- rb.GetImageSkiaNamed(IDR_CLOSE_1_H));
- close_button_->SetImage(views::CustomButton::STATE_PRESSED,
- rb.GetImageSkiaNamed(IDR_CLOSE_1_P));
- close_button_->SetBoundsRect(GetCloseButtonBounds());
- close_button_->SetBackground(SK_ColorBLACK,
- rb.GetImageSkiaNamed(IDR_CLOSE_1),
- rb.GetImageSkiaNamed(IDR_CLOSE_1_MASK));
-
- options_menu_button_->SetIcon(*rb.GetImageSkiaNamed(IDR_BALLOON_WRENCH));
- options_menu_button_->SetHoverIcon(
- *rb.GetImageSkiaNamed(IDR_BALLOON_WRENCH_H));
- options_menu_button_->SetPushedIcon(*rb.GetImageSkiaNamed(
- IDR_BALLOON_WRENCH_P));
- options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER);
- options_menu_button_->SetBorder(views::Border::NullBorder());
- options_menu_button_->SetBoundsRect(GetOptionsButtonBounds());
-
- source_label_->SetFontList(rb.GetFontList(ui::ResourceBundle::SmallFont));
- source_label_->SetBackgroundColor(kControlBarBackgroundColor);
- source_label_->SetEnabledColor(kControlBarTextColor);
- source_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- source_label_->SetBoundsRect(GetLabelBounds());
-
- SizeContentsWindow();
- html_container_->Show();
- frame_container_->Show();
-
- notification_registrar_.Add(
- this, chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
- content::Source<Balloon>(balloon));
-}
-
-void BalloonViewImpl::CreateOptionsMenu() {
- if (options_menu_model_.get())
- return;
- options_menu_model_.reset(new NotificationOptionsMenuModel(balloon_));
-}
-
-void BalloonViewImpl::GetContentsMask(const gfx::Rect& rect,
- gfx::Path* path) const {
- // This rounds the corners, and we also cut out a circle for the close
- // button, since we can't guarantee the ordering of two top-most windows.
- SkScalar radius = SkIntToScalar(views::BubbleBorder::GetCornerRadius());
- SkScalar spline_radius = radius -
- SkScalarMul(radius, (SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3);
- SkScalar left = SkIntToScalar(0);
- SkScalar top = SkIntToScalar(0);
- SkScalar right = SkIntToScalar(rect.width());
- SkScalar bottom = SkIntToScalar(rect.height());
-
- path->moveTo(left, top);
- path->lineTo(right, top);
- path->lineTo(right, bottom - radius);
- path->cubicTo(right, bottom - spline_radius,
- right - spline_radius, bottom,
- right - radius, bottom);
- path->lineTo(left + radius, bottom);
- path->cubicTo(left + spline_radius, bottom,
- left, bottom - spline_radius,
- left, bottom - radius);
- path->lineTo(left, top);
- path->close();
-}
-
-void BalloonViewImpl::GetFrameMask(const gfx::Rect& rect,
- gfx::Path* path) const {
- SkScalar radius = SkIntToScalar(views::BubbleBorder::GetCornerRadius());
- SkScalar spline_radius = radius -
- SkScalarMul(radius, (SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3);
- SkScalar left = SkIntToScalar(rect.x());
- SkScalar top = SkIntToScalar(rect.y());
- SkScalar right = SkIntToScalar(rect.right());
- SkScalar bottom = SkIntToScalar(rect.bottom());
-
- path->moveTo(left, bottom);
- path->lineTo(left, top + radius);
- path->cubicTo(left, top + spline_radius,
- left + spline_radius, top,
- left + radius, top);
- path->lineTo(right - radius, top);
- path->cubicTo(right - spline_radius, top,
- right, top + spline_radius,
- right, top + radius);
- path->lineTo(right, bottom);
- path->lineTo(left, bottom);
- path->close();
-}
-
-gfx::Point BalloonViewImpl::GetContentsOffset() const {
- return gfx::Point(kLeftShadowWidth + kLeftMargin,
- kTopShadowWidth + kTopMargin);
-}
-
-gfx::Rect BalloonViewImpl::GetBoundsForFrameContainer() const {
- return gfx::Rect(balloon_->GetPosition().x(), balloon_->GetPosition().y(),
- GetTotalWidth(), GetTotalHeight());
-}
-
-int BalloonViewImpl::GetShelfHeight() const {
- // TODO(johnnyg): add scaling here.
- int max_button_height = std::max(std::max(
- close_button_->GetPreferredSize().height(),
- options_menu_button_->GetPreferredSize().height()),
- source_label_->GetPreferredSize().height());
- return max_button_height + kShelfMargin * 2;
-}
-
-int BalloonViewImpl::GetBalloonFrameHeight() const {
- return GetTotalHeight() - GetShelfHeight();
-}
-
-int BalloonViewImpl::GetTotalWidth() const {
- return balloon_->content_size().width() +
- kLeftMargin + kRightMargin + kLeftShadowWidth + kRightShadowWidth;
-}
-
-int BalloonViewImpl::GetTotalHeight() const {
- return balloon_->content_size().height() +
- kTopMargin + kBottomMargin + kTopShadowWidth + kBottomShadowWidth +
- GetShelfHeight();
-}
-
-gfx::Rect BalloonViewImpl::GetContentsRectangle() const {
- if (!frame_container_)
- return gfx::Rect();
-
- gfx::Size content_size = balloon_->content_size();
- gfx::Point offset = GetContentsOffset();
- gfx::Rect frame_rect = frame_container_->GetWindowBoundsInScreen();
- return gfx::Rect(frame_rect.x() + offset.x(),
- frame_rect.y() + GetShelfHeight() + offset.y(),
- content_size.width(),
- content_size.height());
-}
-
-void BalloonViewImpl::OnPaint(gfx::Canvas* canvas) {
- DCHECK(canvas);
- // Paint the menu bar area white, with proper rounded corners.
- gfx::Path path;
- gfx::Rect rect = GetContentsBounds();
- rect.set_height(GetShelfHeight());
- GetFrameMask(rect, &path);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(kControlBarBackgroundColor);
- canvas->DrawPath(path, paint);
-
- // Draw a 1-pixel gray line between the content and the menu bar.
- int line_width = GetTotalWidth() - kLeftMargin - kRightMargin;
- canvas->FillRect(gfx::Rect(kLeftMargin, rect.bottom(), line_width, 1),
- kControlBarSeparatorLineColor);
- View::OnPaint(canvas);
- OnPaintBorder(canvas);
-}
-
-void BalloonViewImpl::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- SizeContentsWindow();
-}
-
-void BalloonViewImpl::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- if (type != chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED) {
- NOTREACHED();
- return;
- }
-
- // If the renderer process attached to this balloon is disconnected
- // (e.g., because of a crash), we want to close the balloon.
- notification_registrar_.Remove(
- this, chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
- content::Source<Balloon>(balloon_));
- Close(false);
-}
« no previous file with comments | « chrome/browser/ui/views/notifications/balloon_view_views.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698