172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/notifications/balloon_view.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/balloon.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/balloon_collection.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/desktop_notification_service.h" 14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/notifications/notification.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/notification_options_menu_model.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/bubble_border.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/notifications/balloon_view_host.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h" 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host_view.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/slide_animation.h" 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h" 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/insets.h" 3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/native_widget_types.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/button.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/image_button.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/text_button.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/menu/menu_2.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/native/native_view_host.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/painter.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h" 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_win.h" 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_gtk.h" 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing views::Widget; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTopMargin = 2; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBottomMargin = 0; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kLeftMargin = 4; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRightMargin = 4; 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kShelfBorderTopOverlap = 0; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Properties of the dismiss button. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDismissButtonWidth = 14; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDismissButtonHeight = 14; 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kDismissButtonTopMargin = 6; 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kDismissButtonRightMargin = 6; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Properties of the options menu. 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kOptionsButtonWidth = 21; 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kOptionsButtonHeight = 14; 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kOptionsButtonTopMargin = 5; 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kOptionsButtonRightMargin = 4; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Properties of the origin label. 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kLabelLeftMargin = 10; 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kLabelTopMargin = 6; 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Size of the drop shadow. The shadow is provided by BubbleBorder, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// not this class. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kLeftShadowWidth = 0; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRightShadowWidth = 0; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTopShadowWidth = 0; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBottomShadowWidth = 6; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Optional animation. 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst bool kAnimateEnabled = true; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The shelf height for the system default font size. It is scaled 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// with changes in the default font size. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDefaultShelfHeight = 22; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Menu commands 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRevokePermissionCommand = 0; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Colors 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkColor kControlBarBackgroundColor = SkColorSetRGB(245, 245, 245); 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkColor kControlBarTextColor = SkColorSetRGB(125, 125, 125); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkColor kControlBarSeparatorLineColor = SkColorSetRGB(180, 180, 180); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBalloonViewImpl::BalloonViewImpl(BalloonCollection* collection) 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : balloon_(NULL), 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch collection_(collection), 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_(NULL), 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_(NULL), 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_(NULL), 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_(this), 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_(NULL), 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_(NULL), 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_model_(NULL), 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_menu_(NULL), 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_button_(NULL) { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This object is not to be deleted by the views hierarchy, 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as it is owned by the balloon. 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_parent_owned(false); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BubbleBorder* bubble_border = new BubbleBorder(BubbleBorder::FLOAT); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_border(bubble_border); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBalloonViewImpl::~BalloonViewImpl() { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::Close(bool by_user) { 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_.NewRunnableMethod( 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &BalloonViewImpl::DelayedClose, by_user)); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size BalloonViewImpl::GetSize() const { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // BalloonView has no size if it hasn't been shown yet (which is when 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // balloon_ is set). 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!balloon_) 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Size(0, 0); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Size(GetTotalWidth(), GetTotalHeight()); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenBalloonHost* BalloonViewImpl::GetHost() const { 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return html_contents_.get(); 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::RunMenu(views::View* source, const gfx::Point& pt) { 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RunOptionsMenu(pt); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BalloonViewImpl::OnDisplayChanged() { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch collection_->DisplayChanged(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BalloonViewImpl::OnWorkAreaChanged() { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch collection_->DisplayChanged(); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::ButtonPressed(views::Button* sender, 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const views::Event&) { 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The only button currently is the close button. 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(sender == close_button_); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Close(true); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::DelayedClose(bool by_user) { 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_->Shutdown(); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->CloseNow(); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The BalloonViewImpl has to be detached from frame_container_ now 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because CloseNow on linux/views destroys the view hierachy 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // asynchronously. 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->GetRootView()->RemoveAllChildViews(true); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->CloseNow(); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch balloon_->OnClose(by_user); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsengfx::Size BalloonViewImpl::GetPreferredSize() { 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return gfx::Size(1000, 1000); 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::SizeContentsWindow() { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!html_container_ || !frame_container_) 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect contents_rect = GetContentsRectangle(); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetBounds(contents_rect); 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen html_container_->MoveAboveWidget(frame_container_); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Path path; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetContentsMask(contents_rect, &path); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetShape(path.CreateNativeRegion()); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen close_button_->SetBoundsRect(GetCloseButtonBounds()); 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen options_menu_button_->SetBoundsRect(GetOptionsButtonBounds()); 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen source_label_->SetBoundsRect(GetLabelBounds()); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::RepositionToBalloon() { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(frame_container_); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(html_container_); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(balloon_); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!kAnimateEnabled) { 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->SetBounds( 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect(balloon_->GetPosition().x(), balloon_->GetPosition().y(), 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTotalWidth(), GetTotalHeight())); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect contents_rect = GetContentsRectangle(); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetBounds(contents_rect); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_->SetPreferredSize(contents_rect.size()); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderWidgetHostView* view = html_contents_->render_view_host()->view(); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (view) 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view->SetSize(contents_rect.size()); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch anim_frame_end_ = gfx::Rect( 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch balloon_->GetPosition().x(), balloon_->GetPosition().y(), 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTotalWidth(), GetTotalHeight()); 209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen anim_frame_start_ = frame_container_->GetClientAreaScreenBounds(); 2103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen animation_.reset(new ui::SlideAnimation(this)); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_->Show(); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::Update() { 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(html_contents_.get()) << "BalloonView::Update called before Show"; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (html_contents_->render_view_host()) 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_->render_view_host()->NavigateToURL( 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch balloon_->notification().content_url()); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BalloonViewImpl::AnimationProgressed(const ui::Animation* animation) { 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(animation == animation_.get()); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Linear interpolation from start to end position. 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double e = animation->GetCurrentValue(); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double s = (1.0 - e); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect frame_position( 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(s * anim_frame_start_.x() + 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch e * anim_frame_end_.x()), 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(s * anim_frame_start_.y() + 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch e * anim_frame_end_.y()), 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(s * anim_frame_start_.width() + 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch e * anim_frame_end_.width()), 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(s * anim_frame_start_.height() + 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch e * anim_frame_end_.height())); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->SetBounds(frame_position); 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Path path; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect contents_rect = GetContentsRectangle(); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetBounds(contents_rect); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetContentsMask(contents_rect, &path); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetShape(path.CreateNativeRegion()); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_->SetPreferredSize(contents_rect.size()); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderWidgetHostView* view = html_contents_->render_view_host()->view(); 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (view) 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view->SetSize(contents_rect.size()); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect BalloonViewImpl::GetCloseButtonBounds() const { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect( 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - kDismissButtonWidth - 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDismissButtonRightMargin - kRightShadowWidth, 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kDismissButtonTopMargin, 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDismissButtonWidth, 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDismissButtonHeight); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect BalloonViewImpl::GetOptionsButtonBounds() const { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect close_rect = GetCloseButtonBounds(); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect( 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_rect.x() - kOptionsButtonWidth - kOptionsButtonRightMargin, 2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kOptionsButtonTopMargin, 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kOptionsButtonWidth, 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kOptionsButtonHeight); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect BalloonViewImpl::GetLabelBounds() const { 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect( 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kLeftShadowWidth + kLabelLeftMargin, 2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kLabelTopMargin, 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, width() - kOptionsButtonWidth - 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kRightMargin), 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kOptionsButtonHeight); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::Show(Balloon* balloon) { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch balloon_ = balloon; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetBounds(balloon_->GetPosition().x(), balloon_->GetPosition().y(), 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTotalWidth(), GetTotalHeight()); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 source_label_text = l10n_util::GetStringFUTF16( 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDS_NOTIFICATION_BALLOON_SOURCE_LABEL, 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick balloon->notification().display_source()); 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick source_label_ = new views::Label(UTF16ToWide(source_label_text)); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(source_label_); 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_button_ = new views::MenuButton(NULL, L"", this, false); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(options_menu_button_); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_ = new views::ImageButton(this); 2963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen close_button_->SetTooltipText(UTF16ToWide(l10n_util::GetStringUTF16( 2973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen IDS_NOTIFICATION_BALLOON_DISMISS_LABEL))); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(close_button_); 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We have to create two windows: one for the contents and one for the 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // frame. Why? 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * The contents is an html window which cannot be a 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // layered window (because it may have child windows for instance). 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * The frame is a layered window so that we can have nicely rounded 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // corners using alpha blending (and we may do other alpha blending 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // effects). 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unfortunately, layered windows cannot have child windows. (Well, they can 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but the child windows don't render). 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We carefully keep these two windows in sync to present the illusion of 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // one window to the user. 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't let the OS manage the RTL layout of these widgets, because 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this code is already taking care of correctly reversing the layout. 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect contents_rect = GetContentsRectangle(); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_.reset(new BalloonViewHost(balloon)); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_contents_->SetPreferredSize(gfx::Size(10000, 10000)); 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Widget::CreateParams params(Widget::CreateParams::TYPE_POPUP); 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.mirror_origin_in_rtl = false; 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen html_container_ = Widget::CreateWidget(params); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetAlwaysOnTop(true); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->Init(NULL, contents_rect); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->SetContentsView(html_contents_->view()); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect balloon_rect(x(), y(), GetTotalWidth(), GetTotalHeight()); 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.transparent = true; 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen frame_container_ = Widget::CreateWidget(params); 328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen frame_container_->set_widget_delegate(this); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->SetAlwaysOnTop(true); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->Init(NULL, balloon_rect); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->SetContentsView(this); 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen frame_container_->MoveAboveWidget(html_container_); 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImage(views::CustomButton::BS_NORMAL, 3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rb.GetBitmapNamed(IDR_TAB_CLOSE)); 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImage(views::CustomButton::BS_HOT, 3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rb.GetBitmapNamed(IDR_TAB_CLOSE_H)); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImage(views::CustomButton::BS_PUSHED, 3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rb.GetBitmapNamed(IDR_TAB_CLOSE_P)); 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen close_button_->SetBoundsRect(GetCloseButtonBounds()); 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick close_button_->SetBackground(SK_ColorBLACK, 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rb.GetBitmapNamed(IDR_TAB_CLOSE), 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK)); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH)); 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick options_menu_button_->SetHoverIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH_H)); 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick options_menu_button_->SetPushedIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH_P)); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER); 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick options_menu_button_->set_border(NULL); 35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen options_menu_button_->SetBoundsRect(GetOptionsButtonBounds()); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont)); 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source_label_->SetColor(kControlBarTextColor); 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen source_label_->SetBoundsRect(GetLabelBounds()); 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SizeContentsWindow(); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch html_container_->Show(); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_container_->Show(); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch notification_registrar_.Add(this, 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon)); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::RunOptionsMenu(const gfx::Point& pt) { 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateOptionsMenu(); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::CreateOptionsMenu() { 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options_menu_model_.get()) 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_model_.reset(new NotificationOptionsMenuModel(balloon_)); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options_menu_menu_.reset(new views::Menu2(options_menu_model_.get())); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::GetContentsMask(const gfx::Rect& rect, 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Path* path) const { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This rounds the corners, and we also cut out a circle for the close 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // button, since we can't guarantee the ordering of two top-most windows. 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar spline_radius = radius - 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalarMul(radius, (SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar left = SkIntToScalar(0); 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar top = SkIntToScalar(0); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar right = SkIntToScalar(rect.width()); 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar bottom = SkIntToScalar(rect.height()); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->moveTo(left, top); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(right, top); 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(right, bottom - radius); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->cubicTo(right, bottom - spline_radius, 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right - spline_radius, bottom, 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right - radius, bottom); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(left + radius, bottom); 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->cubicTo(left + spline_radius, bottom, 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left, bottom - spline_radius, 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left, bottom - radius); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(left, top); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->close(); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::GetFrameMask(const gfx::Rect& rect, 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Path* path) const { 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar spline_radius = radius - 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalarMul(radius, (SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar left = SkIntToScalar(rect.x()); 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar top = SkIntToScalar(rect.y()); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar right = SkIntToScalar(rect.right()); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkScalar bottom = SkIntToScalar(rect.bottom()); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->moveTo(left, bottom); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(left, top + radius); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->cubicTo(left, top + spline_radius, 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left + spline_radius, top, 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left + radius, top); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(right - radius, top); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->cubicTo(right - spline_radius, top, 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right, top + spline_radius, 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right, top + radius); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(right, bottom); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->lineTo(left, bottom); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path->close(); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point BalloonViewImpl::GetContentsOffset() const { 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Point(kLeftShadowWidth + kLeftMargin, 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kTopShadowWidth + kTopMargin); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BalloonViewImpl::GetShelfHeight() const { 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(johnnyg): add scaling here. 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kDefaultShelfHeight; 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BalloonViewImpl::GetBalloonFrameHeight() const { 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetTotalHeight() - GetShelfHeight(); 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BalloonViewImpl::GetTotalWidth() const { 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return balloon_->content_size().width() 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch + kLeftMargin + kRightMargin + kLeftShadowWidth + kRightShadowWidth; 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BalloonViewImpl::GetTotalHeight() const { 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return balloon_->content_size().height() 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch + kTopMargin + kBottomMargin + kTopShadowWidth + kBottomShadowWidth 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch + GetShelfHeight(); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect BalloonViewImpl::GetContentsRectangle() const { 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!frame_container_) 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(); 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size content_size = balloon_->content_size(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point offset = GetContentsOffset(); 459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gfx::Rect frame_rect = frame_container_->GetWindowScreenBounds(); 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(frame_rect.x() + offset.x(), 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_rect.y() + GetShelfHeight() + offset.y(), 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_size.width(), 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_size.height()); 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid BalloonViewImpl::OnPaint(gfx::Canvas* canvas) { 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(canvas); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paint the menu bar area white, with proper rounded corners. 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Path path; 47072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::Rect rect = GetContentsBounds(); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rect.set_height(GetShelfHeight()); 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetFrameMask(rect, &path); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkPaint paint; 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setAntiAlias(true); 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setColor(kControlBarBackgroundColor); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->AsCanvasSkia()->drawPath(path, paint); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw a 1-pixel gray line between the content and the menu bar. 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int line_width = GetTotalWidth() - kLeftMargin - kRightMargin; 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->FillRectInt(kControlBarSeparatorLineColor, 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kLeftMargin, 1 + GetShelfHeight(), line_width, 1); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen View::OnPaint(canvas); 485dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnPaintBorder(canvas); 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BalloonViewImpl::OnBoundsChanged(const gfx::Rect& previous_bounds) { 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SizeContentsWindow(); 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BalloonViewImpl::Observe(NotificationType type, 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type != NotificationType::NOTIFY_BALLOON_DISCONNECTED) { 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the renderer process attached to this balloon is disconnected 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (e.g., because of a crash), we want to close the balloon. 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch notification_registrar_.Remove(this, 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon_)); 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Close(false); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 506