diff options
Diffstat (limited to 'chrome/browser/views/notifications/balloon_view.cc')
-rw-r--r-- | chrome/browser/views/notifications/balloon_view.cc | 502 |
1 files changed, 0 insertions, 502 deletions
diff --git a/chrome/browser/views/notifications/balloon_view.cc b/chrome/browser/views/notifications/balloon_view.cc deleted file mode 100644 index cf0442b..0000000 --- a/chrome/browser/views/notifications/balloon_view.cc +++ /dev/null @@ -1,502 +0,0 @@ -// Copyright (c) 2010 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/views/notifications/balloon_view.h" - -#include <vector> - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "base/message_loop.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/notifications/balloon.h" -#include "chrome/browser/notifications/balloon_collection.h" -#include "chrome/browser/notifications/desktop_notification_service.h" -#include "chrome/browser/notifications/notification_options_menu_model.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/browser/themes/browser_theme_provider.h" -#include "chrome/browser/views/bubble_border.h" -#include "chrome/browser/views/notifications/balloon_view_host.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/notification_type.h" -#include "gfx/canvas_skia.h" -#include "gfx/insets.h" -#include "gfx/native_widget_types.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "views/controls/button/button.h" -#include "views/controls/button/image_button.h" -#include "views/controls/button/text_button.h" -#include "views/controls/menu/menu_2.h" -#include "views/controls/native/native_view_host.h" -#include "views/painter.h" -#include "views/widget/root_view.h" -#if defined(OS_WIN) -#include "views/widget/widget_win.h" -#endif -#if defined(OS_LINUX) -#include "views/widget/widget_gtk.h" -#endif - -using views::Widget; - -namespace { - -const int kTopMargin = 2; -const int kBottomMargin = 0; -const int kLeftMargin = 4; -const int kRightMargin = 4; -const int kShelfBorderTopOverlap = 0; - -// Properties of the dismiss button. -const int kDismissButtonWidth = 14; -const int kDismissButtonHeight = 14; -const int kDismissButtonTopMargin = 6; -const int kDismissButtonRightMargin = 6; - -// Properties of the options menu. -const int kOptionsButtonWidth = 21; -const int kOptionsButtonHeight = 14; -const int kOptionsButtonTopMargin = 5; -const int kOptionsButtonRightMargin = 4; - -// Properties of the origin label. -const int kLabelLeftMargin = 10; -const int kLabelTopMargin = 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; - -// The shelf height for the system default font size. It is scaled -// with changes in the default font size. -const int kDefaultShelfHeight = 22; - -// Menu commands -const int kRevokePermissionCommand = 0; - -// Colors -const SkColor kControlBarBackgroundColor = SkColorSetRGB(245, 245, 245); -const SkColor kControlBarTextColor = SkColorSetRGB(125, 125, 125); -const SkColor kControlBarSeparatorLineColor = SkColorSetRGB(180, 180, 180); - -} // namespace - -BalloonViewImpl::BalloonViewImpl(BalloonCollection* collection) - : balloon_(NULL), - collection_(collection), - frame_container_(NULL), - html_container_(NULL), - html_contents_(NULL), - method_factory_(this), - close_button_(NULL), - animation_(NULL), - options_menu_model_(NULL), - options_menu_menu_(NULL), - options_menu_button_(NULL) { - // This object is not to be deleted by the views hierarchy, - // as it is owned by the balloon. - set_parent_owned(false); - - BubbleBorder* bubble_border = new BubbleBorder(BubbleBorder::FLOAT); - set_border(bubble_border); -} - -BalloonViewImpl::~BalloonViewImpl() { -} - -void BalloonViewImpl::Close(bool by_user) { - MessageLoop::current()->PostTask(FROM_HERE, - method_factory_.NewRunnableMethod( - &BalloonViewImpl::DelayedClose, by_user)); -} - -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()); -} - -void BalloonViewImpl::RunMenu(views::View* source, const gfx::Point& pt) { - RunOptionsMenu(pt); -} - -void BalloonViewImpl::DisplayChanged() { - collection_->DisplayChanged(); -} - -void BalloonViewImpl::WorkAreaChanged() { - collection_->DisplayChanged(); -} - -void BalloonViewImpl::ButtonPressed(views::Button* sender, - const views::Event&) { - // The only button currently is the close button. - DCHECK(sender == close_button_); - Close(true); -} - -void BalloonViewImpl::DelayedClose(bool by_user) { - html_contents_->Shutdown(); - html_container_->CloseNow(); - // The BalloonViewImpl has to be detached from frame_container_ now - // because CloseNow on linux/views destroys the view hierachy - // asynchronously. - frame_container_->GetRootView()->RemoveAllChildViews(true); - frame_container_->CloseNow(); - balloon_->OnClose(by_user); -} - -void BalloonViewImpl::DidChangeBounds(const gfx::Rect& previous, - const gfx::Rect& current) { - SizeContentsWindow(); -} - -void BalloonViewImpl::SizeContentsWindow() { - if (!html_container_ || !frame_container_) - return; - - gfx::Rect contents_rect = GetContentsRectangle(); - html_container_->SetBounds(contents_rect); - html_container_->MoveAbove(frame_container_); - - gfx::Path path; - GetContentsMask(contents_rect, &path); - html_container_->SetShape(path.CreateNativeRegion()); - - close_button_->SetBounds(GetCloseButtonBounds()); - options_menu_button_->SetBounds(GetOptionsButtonBounds()); - source_label_->SetBounds(GetLabelBounds()); -} - -void BalloonViewImpl::RepositionToBalloon() { - DCHECK(frame_container_); - DCHECK(html_container_); - DCHECK(balloon_); - - if (!kAnimateEnabled) { - frame_container_->SetBounds( - gfx::Rect(balloon_->GetPosition().x(), balloon_->GetPosition().y(), - GetTotalWidth(), GetTotalHeight())); - gfx::Rect contents_rect = GetContentsRectangle(); - html_container_->SetBounds(contents_rect); - html_contents_->SetPreferredSize(contents_rect.size()); - RenderWidgetHostView* view = html_contents_->render_view_host()->view(); - if (view) - view->SetSize(contents_rect.size()); - return; - } - - anim_frame_end_ = gfx::Rect( - balloon_->GetPosition().x(), balloon_->GetPosition().y(), - GetTotalWidth(), GetTotalHeight()); - frame_container_->GetBounds(&anim_frame_start_, false); - animation_.reset(new SlideAnimation(this)); - animation_->Show(); -} - -void BalloonViewImpl::Update() { - DCHECK(html_contents_.get()) << "BalloonView::Update called before Show"; - if (html_contents_->render_view_host()) - html_contents_->render_view_host()->NavigateToURL( - balloon_->notification().content_url()); -} - -void BalloonViewImpl::AnimationProgressed(const Animation* animation) { - DCHECK(animation == animation_.get()); - - // Linear interpolation from start to end position. - double e = animation->GetCurrentValue(); - double s = (1.0 - e); - - gfx::Rect frame_position( - static_cast<int>(s * anim_frame_start_.x() + - e * anim_frame_end_.x()), - static_cast<int>(s * anim_frame_start_.y() + - e * anim_frame_end_.y()), - static_cast<int>(s * anim_frame_start_.width() + - e * anim_frame_end_.width()), - static_cast<int>(s * anim_frame_start_.height() + - e * anim_frame_end_.height())); - 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()); - RenderWidgetHostView* view = html_contents_->render_view_host()->view(); - if (view) - view->SetSize(contents_rect.size()); -} - -gfx::Rect BalloonViewImpl::GetCloseButtonBounds() const { - return gfx::Rect( - width() - kDismissButtonWidth - - kDismissButtonRightMargin - kRightShadowWidth, - kDismissButtonTopMargin, - kDismissButtonWidth, - kDismissButtonHeight); -} - -gfx::Rect BalloonViewImpl::GetOptionsButtonBounds() const { - gfx::Rect close_rect = GetCloseButtonBounds(); - - return gfx::Rect( - close_rect.x() - kOptionsButtonWidth - kOptionsButtonRightMargin, - kOptionsButtonTopMargin, - kOptionsButtonWidth, - kOptionsButtonHeight); -} - -gfx::Rect BalloonViewImpl::GetLabelBounds() const { - return gfx::Rect( - kLeftShadowWidth + kLabelLeftMargin, - kLabelTopMargin, - std::max(0, width() - kOptionsButtonWidth - - kRightMargin), - kOptionsButtonHeight); -} - -void BalloonViewImpl::Show(Balloon* balloon) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - - balloon_ = balloon; - - SetBounds(balloon_->GetPosition().x(), balloon_->GetPosition().y(), - GetTotalWidth(), GetTotalHeight()); - - const string16 source_label_text = l10n_util::GetStringFUTF16( - IDS_NOTIFICATION_BALLOON_SOURCE_LABEL, - balloon->notification().display_source()); - - source_label_ = new views::Label(UTF16ToWide(source_label_text)); - AddChildView(source_label_); - options_menu_button_ = new views::MenuButton(NULL, L"", this, false); - AddChildView(options_menu_button_); - close_button_ = new views::ImageButton(this); - close_button_->SetTooltipText(l10n_util::GetString( - 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. - gfx::Rect contents_rect = GetContentsRectangle(); - html_contents_.reset(new BalloonViewHost(balloon)); - html_contents_->SetPreferredSize(gfx::Size(10000, 10000)); - html_container_ = Widget::CreatePopupWidget(Widget::NotTransparent, - Widget::AcceptEvents, - Widget::DeleteOnDestroy, - Widget::DontMirrorOriginInRTL); - html_container_->SetAlwaysOnTop(true); - html_container_->Init(NULL, contents_rect); - html_container_->SetContentsView(html_contents_->view()); - - gfx::Rect balloon_rect(x(), y(), GetTotalWidth(), GetTotalHeight()); - frame_container_ = Widget::CreatePopupWidget(Widget::Transparent, - Widget::AcceptEvents, - Widget::DeleteOnDestroy, - Widget::DontMirrorOriginInRTL); - frame_container_->SetWidgetDelegate(this); - frame_container_->SetAlwaysOnTop(true); - frame_container_->Init(NULL, balloon_rect); - frame_container_->SetContentsView(this); - frame_container_->MoveAbove(html_container_); - - close_button_->SetImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_TAB_CLOSE)); - close_button_->SetImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_TAB_CLOSE_H)); - close_button_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_TAB_CLOSE_P)); - close_button_->SetBounds(GetCloseButtonBounds()); - close_button_->SetBackground(SK_ColorBLACK, - rb.GetBitmapNamed(IDR_TAB_CLOSE), - rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK)); - - options_menu_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH)); - options_menu_button_->SetHoverIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH_H)); - options_menu_button_->SetPushedIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH_P)); - options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER); - options_menu_button_->set_border(NULL); - options_menu_button_->SetBounds(GetOptionsButtonBounds()); - - source_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont)); - source_label_->SetColor(kControlBarTextColor); - source_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - source_label_->SetBounds(GetLabelBounds()); - - SizeContentsWindow(); - html_container_->Show(); - frame_container_->Show(); - - notification_registrar_.Add(this, - NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon)); -} - -void BalloonViewImpl::RunOptionsMenu(const gfx::Point& pt) { - CreateOptionsMenu(); - options_menu_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); -} - -void BalloonViewImpl::CreateOptionsMenu() { - if (options_menu_model_.get()) - return; - - options_menu_model_.reset(new NotificationOptionsMenuModel(balloon_)); - options_menu_menu_.reset(new views::Menu2(options_menu_model_.get())); -} - -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(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(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); -} - -int BalloonViewImpl::GetShelfHeight() const { - // TODO(johnnyg): add scaling here. - return kDefaultShelfHeight; -} - -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_->GetBounds(&frame_rect, true); - return gfx::Rect(frame_rect.x() + offset.x(), - frame_rect.y() + GetShelfHeight() + offset.y(), - content_size.width(), - content_size.height()); -} - -void BalloonViewImpl::Paint(gfx::Canvas* canvas) { - DCHECK(canvas); - // Paint the menu bar area white, with proper rounded corners. - gfx::Path path; - gfx::Rect rect = GetLocalBounds(false); - rect.set_height(GetShelfHeight()); - GetFrameMask(rect, &path); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setColor(kControlBarBackgroundColor); - canvas->AsCanvasSkia()->drawPath(path, paint); - - // Draw a 1-pixel gray line between the content and the menu bar. - int line_width = GetTotalWidth() - kLeftMargin - kRightMargin; - canvas->FillRectInt(kControlBarSeparatorLineColor, - kLeftMargin, 1 + GetShelfHeight(), line_width, 1); - - View::Paint(canvas); - PaintBorder(canvas); -} - -void BalloonViewImpl::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type != NotificationType::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, - NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon_)); - Close(false); -} |