diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-15 19:34:21 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-15 19:34:21 +0000 |
commit | 2f3db93f70663ad66499152f03a9b41bcfb054a1 (patch) | |
tree | 16f6250e5a6d4ee7cea0e81677115e1648c9d0de /chrome | |
parent | b8960f46192e177a28927ccf843daa4657da546a (diff) | |
download | chromium_src-2f3db93f70663ad66499152f03a9b41bcfb054a1.zip chromium_src-2f3db93f70663ad66499152f03a9b41bcfb054a1.tar.gz chromium_src-2f3db93f70663ad66499152f03a9b41bcfb054a1.tar.bz2 |
fix bustage
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29167 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/views/blocked_popup_container_view_views.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/blocked_popup_container_view_win.cc | 457 |
2 files changed, 458 insertions, 1 deletions
diff --git a/chrome/browser/views/blocked_popup_container_view_views.cc b/chrome/browser/views/blocked_popup_container_view_views.cc index f344299..832447e 100644 --- a/chrome/browser/views/blocked_popup_container_view_views.cc +++ b/chrome/browser/views/blocked_popup_container_view_views.cc @@ -130,7 +130,7 @@ gfx::Size BlockedPopupContainerViewWidget::GetParentSize() { void BlockedPopupContainerViewWidget::OnSize(UINT param, const CSize& size) { container_->UpdateWidgetShape(this, gfx::Size(size.cx, size.cy)); - ChangeSize(param, size); + LayoutRootView(); } #elif defined(OS_LINUX) diff --git a/chrome/browser/views/blocked_popup_container_view_win.cc b/chrome/browser/views/blocked_popup_container_view_win.cc new file mode 100644 index 0000000..eeb7e09 --- /dev/null +++ b/chrome/browser/views/blocked_popup_container_view_win.cc @@ -0,0 +1,457 @@ +// Copyright (c) 2009 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/blocked_popup_container_view_win.h" + +#include <math.h> +#include <windows.h> + +#include "app/gfx/canvas.h" +#include "app/gfx/path.h" +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/string_util.h" +#include "chrome/browser/extensions/extension_function_dispatcher.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/notification_service.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "views/background.h" +#include "views/controls/button/image_button.h" + +#include "views/controls/scrollbar/native_scroll_bar.h" + +namespace { +// The minimal border around the edge of the notification. +const int kSmallPadding = 2; + +// The background color of the blocked popup notification. +const SkColor kBackgroundColorTop = SkColorSetRGB(255, 242, 183); +const SkColor kBackgroundColorBottom = SkColorSetRGB(250, 230, 145); + +// The border color of the blocked popup notification. This is the same as the +// border around the inside of the tab contents. +const SkColor kBorderColor = SkColorSetRGB(190, 205, 223); + +// So that the MenuButton doesn't change its size as its text changes, during +// construction we feed it the strings it will be displaying, so it can set the +// max text width to the right value. "99" should preallocate enough space for +// all numbers we'd show. +const int kWidestNumber = 99; + +// Rounded corner radius (in pixels). +const int kBackgroundCornerRadius = 4; + +// Rounded corner definition so the top corners are rounded, and the bottom are +// normal 90 degree angles. +const SkScalar kRoundedCornerRad[8] = { + // Top left corner + SkIntToScalar(kBackgroundCornerRadius), + SkIntToScalar(kBackgroundCornerRadius), + // Top right corner + SkIntToScalar(kBackgroundCornerRadius), + SkIntToScalar(kBackgroundCornerRadius), + // Bottom right corner + 0, + 0, + // Bottom left corner + 0, + 0 +}; + +} // namespace + + +// The view presented to the user notifying them of the number of popups +// blocked. This view should only be used inside of BlockedPopupContainer. +class BlockedPopupContainerInternalView : public views::View, + public views::ButtonListener, + public views::Menu::Delegate { + public: + explicit BlockedPopupContainerInternalView( + BlockedPopupContainerViewWin* container); + ~BlockedPopupContainerInternalView(); + + // Sets the label on the menu button. + void UpdateLabel(); + + std::wstring label() const { return popup_count_label_->text(); } + + // Overridden from views::View: + + // Paints our border and background. (Does not paint children.) + virtual void Paint(gfx::Canvas* canvas); + // Sets positions of all child views. + virtual void Layout(); + // Gets the desired size of the popup notification. + virtual gfx::Size GetPreferredSize(); + + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // Overridden from Menu::Delegate: + + // Displays the status of the "Show Blocked Popup Notification" item. + virtual bool IsItemChecked(int id) const; + // Called after user clicks a menu item. + virtual void ExecuteCommand(int id); + + private: + // Our owner and HWND parent. + BlockedPopupContainerViewWin* container_; + + // The button which brings up the popup menu. + views::MenuButton* popup_count_label_; + + // Our "X" button. + views::ImageButton* close_button_; + + // Popup menu shown to user. + scoped_ptr<views::Menu> launch_menu_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(BlockedPopupContainerInternalView); +}; + + +BlockedPopupContainerInternalView::BlockedPopupContainerInternalView( + BlockedPopupContainerViewWin* container) + : container_(container) { + ResourceBundle &resource_bundle = ResourceBundle::GetSharedInstance(); + + // Create a button with a multidigit number to reserve space. + popup_count_label_ = new views::MenuButton( + this, + l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, + IntToWString(kWidestNumber)), + NULL, true); + // Now set the text to the other possible display strings so that the button + // will update its max text width (in case one of these string is longer). + popup_count_label_->SetText(l10n_util::GetString(IDS_POPUPS_UNBLOCKED)); + popup_count_label_->SetText(l10n_util::GetString(IDS_BLOCKED_NOTICE_COUNT)); + popup_count_label_->set_alignment(views::TextButton::ALIGN_CENTER); + AddChildView(popup_count_label_); + + // For now, we steal the Find close button, since it looks OK. + close_button_ = new views::ImageButton(this); + close_button_->SetFocusable(true); + close_button_->SetImage(views::CustomButton::BS_NORMAL, + resource_bundle.GetBitmapNamed(IDR_CLOSE_BAR)); + close_button_->SetImage(views::CustomButton::BS_HOT, + resource_bundle.GetBitmapNamed(IDR_CLOSE_BAR_H)); + close_button_->SetImage(views::CustomButton::BS_PUSHED, + resource_bundle.GetBitmapNamed(IDR_CLOSE_BAR_P)); + AddChildView(close_button_); + + set_background(views::Background::CreateStandardPanelBackground()); + UpdateLabel(); +} + +BlockedPopupContainerInternalView::~BlockedPopupContainerInternalView() { +} + +void BlockedPopupContainerInternalView::UpdateLabel() { + size_t blocked_notices = container_->model()->GetBlockedNoticeCount(); + size_t blocked_items = container_->model()->GetBlockedPopupCount() + + blocked_notices; + + std::wstring label; + if (blocked_items == 0) { + label = l10n_util::GetString(IDS_POPUPS_UNBLOCKED); + } else if (blocked_notices == 0) { + label = l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, + UintToWString(blocked_items)); + } else { + label = l10n_util::GetStringF(IDS_BLOCKED_NOTICE_COUNT, + UintToWString(blocked_items)); + } + popup_count_label_->SetText(label); + + Layout(); + SchedulePaint(); +} + +void BlockedPopupContainerInternalView::Paint(gfx::Canvas* canvas) { + // Draw the standard background. + View::Paint(canvas); + + SkRect rect; + rect.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height())); + + // Draw the border + SkPaint border_paint; + border_paint.setFlags(SkPaint::kAntiAlias_Flag); + border_paint.setStyle(SkPaint::kStroke_Style); + border_paint.setColor(kBorderColor); + SkPath border_path; + border_path.addRoundRect(rect, kRoundedCornerRad, SkPath::kCW_Direction); + canvas->drawPath(border_path, border_paint); +} + +void BlockedPopupContainerInternalView::Layout() { + gfx::Size panel_size = GetPreferredSize(); + gfx::Size button_size = close_button_->GetPreferredSize(); + gfx::Size size = popup_count_label_->GetPreferredSize(); + + popup_count_label_->SetBounds(kSmallPadding, kSmallPadding, + size.width(), + size.height()); + + int close_button_padding = + static_cast<int>(ceil(panel_size.height() / 2.0) - + ceil(button_size.height() / 2.0)); + close_button_->SetBounds(width() - button_size.width() - close_button_padding, + close_button_padding, + button_size.width(), + button_size.height()); +} + +gfx::Size BlockedPopupContainerInternalView::GetPreferredSize() { + gfx::Size preferred_size = popup_count_label_->GetPreferredSize(); + preferred_size.Enlarge(close_button_->GetPreferredSize().width(), 0); + // Add padding to all sides of the |popup_count_label_| except the right. + preferred_size.Enlarge(kSmallPadding, 2 * kSmallPadding); + + // Add padding to the left and right side of |close_button_| equal to its + // horizontal/vertical spacing. + gfx::Size button_size = close_button_->GetPreferredSize(); + int close_button_padding = + static_cast<int>(ceil(preferred_size.height() / 2.0) - + ceil(button_size.height() / 2.0)); + preferred_size.Enlarge(2 * close_button_padding, 0); + + return preferred_size; +} + +void BlockedPopupContainerInternalView::ButtonPressed( + views::Button* sender, const views::Event& event) { + if (sender == close_button_) { + container_->model()->set_dismissed(); + container_->model()->CloseAll(); + } + + if (sender != popup_count_label_) + return; + + launch_menu_.reset(views::Menu::Create(this, views::Menu::TOPLEFT, + container_->GetNativeView())); + + // Set items 1 .. popup_count as individual popups. + size_t popup_count = container_->model()->GetBlockedPopupCount(); + for (size_t i = 0; i < popup_count; ++i) { + std::wstring url, title; + container_->GetURLAndTitleForPopup(i, &url, &title); + // We can't just use the index into container_ here because Menu reserves + // the value 0 as the nop command. + launch_menu_->AppendMenuItem(i + 1, + l10n_util::GetStringF(IDS_POPUP_TITLE_FORMAT, url, title), + views::Menu::NORMAL); + } + + // Set items (kImpossibleNumberOfPopups + 1) .. + // (kImpossibleNumberOfPopups + hosts.size()) as hosts. + std::vector<std::string> hosts(container_->model()->GetHosts()); + if (!hosts.empty() && (popup_count > 0)) + launch_menu_->AppendSeparator(); + size_t first_host = BlockedPopupContainer::kImpossibleNumberOfPopups + 1; + for (size_t i = 0; i < hosts.size(); ++i) { + launch_menu_->AppendMenuItem(first_host + i, + l10n_util::GetStringF(IDS_POPUP_HOST_FORMAT, UTF8ToWide(hosts[i])), + views::Menu::NORMAL); + } + + // Set items (kImpossibleNumberOfPopups + hosts.size() + 2) .. + // (kImpossibleNumberOfPopups + hosts.size() + 1 + notice_count) as notices. + size_t notice_count = container_->model()->GetBlockedNoticeCount(); + if (notice_count && (!hosts.empty() || (popup_count > 0))) + launch_menu_->AppendSeparator(); + size_t first_notice = first_host + hosts.size() + 1; + for (size_t i = 0; i < notice_count; ++i) { + std::string host; + string16 reason; + container_->model()->GetHostAndReasonForNotice(i, &host, &reason); + launch_menu_->AppendMenuItem(first_notice + i, + l10n_util::GetStringF(IDS_NOTICE_TITLE_FORMAT, ASCIIToWide(host), + reason), + views::Menu::NORMAL); + } + + CPoint cursor_position; + GetCursorPos(&cursor_position); + launch_menu_->RunMenuAt(cursor_position.x, cursor_position.y); +} + +bool BlockedPopupContainerInternalView::IsItemChecked(int id) const { + // |id| should be > 0 since all index based commands have 1 added to them. + DCHECK_GT(id, 0); + size_t id_size_t = static_cast<size_t>(id); + + if (id_size_t > BlockedPopupContainer::kImpossibleNumberOfPopups) { + id_size_t -= BlockedPopupContainer::kImpossibleNumberOfPopups + 1; + if (id_size_t < container_->model()->GetPopupHostCount()) + return container_->model()->IsHostWhitelisted(id_size_t); + } + + return false; +} + +void BlockedPopupContainerInternalView::ExecuteCommand(int id) { + // |id| should be > 0 since all index based commands have 1 added to them. + DCHECK_GT(id, 0); + size_t id_size_t = static_cast<size_t>(id); + + // Is this a click on a popup? + if (id_size_t < BlockedPopupContainer::kImpossibleNumberOfPopups) { + container_->model()->LaunchPopupAtIndex(id_size_t - 1); + return; + } + + // |id| shouldn't be == kImpossibleNumberOfPopups since the popups end before + // this and the hosts start after it. (If it is used, it is as a separator.) + DCHECK_NE(id_size_t, BlockedPopupContainer::kImpossibleNumberOfPopups); + id_size_t -= BlockedPopupContainer::kImpossibleNumberOfPopups + 1; + + // Is this a click on a host? + size_t host_count = container_->model()->GetPopupHostCount(); + if (id_size_t < host_count) { + container_->model()->ToggleWhitelistingForHost(id_size_t); + return; + } + + // |id shouldn't be == host_count since this is the separator between hosts + // and notices. + DCHECK_NE(id_size_t, host_count); + id_size_t -= host_count + 1; + + // Nothing to do for now for notices. +} + + +// static +BlockedPopupContainerView* BlockedPopupContainerView::Create( + BlockedPopupContainer* container) { + return new BlockedPopupContainerViewWin(container); +} + + +BlockedPopupContainerViewWin::~BlockedPopupContainerViewWin() { +} + +void BlockedPopupContainerViewWin::GetURLAndTitleForPopup( + size_t index, std::wstring* url, std::wstring* title) const { + DCHECK(url); + DCHECK(title); + TabContents* tab_contents = model()->GetTabContentsAt(index); + const GURL& tab_contents_url = tab_contents->GetURL().GetOrigin(); + *url = UTF8ToWide(tab_contents_url.possibly_invalid_spec()); + *title = UTF16ToWideHack(tab_contents->GetTitle()); +} + +// Overridden from AnimationDelegate: + +void BlockedPopupContainerViewWin::AnimationStarted( + const Animation* animation) { + SetPosition(); +} + +void BlockedPopupContainerViewWin::AnimationEnded(const Animation* animation) { + SetPosition(); +} + +void BlockedPopupContainerViewWin::AnimationProgressed( + const Animation* animation) { + SetPosition(); +} + +// Overridden from BlockedPopupContainerView: + +void BlockedPopupContainerViewWin::SetPosition() { + // Get our parent's rect and size ourselves inside of it. + HWND parent = GetParent(); + CRect client_rect; + ::GetClientRect(parent, &client_rect); + + // TODO(erg): There's no way to detect whether scroll bars are + // visible, so for beta, we're just going to assume that the + // vertical scroll bar is visible, and not care about covering up + // the horizontal scroll bar. Fixing this is half of + // http://b/1118139. + gfx::Point anchor_point( + client_rect.Width() - + views::NativeScrollBar::GetVerticalScrollBarWidth(), + client_rect.Height()); + + gfx::Size size = container_view_->GetPreferredSize(); + int base_x = anchor_point.x() - size.width(); + int base_y = anchor_point.y() - size.height(); + + int real_height = + static_cast<int>(size.height() * slide_animation_->GetCurrentValue()); + int real_y = anchor_point.y() - real_height; + + if (real_height > 0) { + int x; + if (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT) { + // Size this window using the anchor point as top-right corner. + x = base_x; + } else { + // Size this window to the bottom left corner of top client window. In + // Chrome, scrollbars always appear on the right, even for a RTL page or + // when the UI is RTL (see http://crbug.com/6113 for more detail). Thus 0 + // is always a safe value for x-axis. + x = 0; + } + SetWindowPos(HWND_TOP, x, real_y, size.width(), real_height, + SWP_SHOWWINDOW); + container_view_->SchedulePaint(); + } else { + SetWindowPos(HWND_TOP, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); + } +} + +void BlockedPopupContainerViewWin::ShowView() { + SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + slide_animation_->Show(); +} + +void BlockedPopupContainerViewWin::UpdateLabel() { + container_view_->UpdateLabel(); +} + +void BlockedPopupContainerViewWin::HideView() { + slide_animation_->Hide(); +} + +void BlockedPopupContainerViewWin::Destroy() { + Close(); +} + +// private: + +BlockedPopupContainerViewWin::BlockedPopupContainerViewWin( + BlockedPopupContainer* container) + : slide_animation_(new SlideAnimation(this)), + model_(container), + container_view_(NULL) { + container_view_ = new BlockedPopupContainerInternalView(this); + container_view_->SetVisible(true); + + set_window_style(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); + WidgetWin::Init(model_->GetConstrainingContents(NULL)->GetNativeView(), + gfx::Rect()); + SetContentsView(container_view_); + SetPosition(); +} + +void BlockedPopupContainerViewWin::OnSize(UINT param, const CSize& size) { + // Set the window region so we have rounded corners on the top. + SkRect rect; + rect.set(0, 0, SkIntToScalar(size.cx), SkIntToScalar(size.cy)); + gfx::Path path; + path.addRoundRect(rect, kRoundedCornerRad, SkPath::kCW_Direction); + SetWindowRgn(path.CreateHRGN(), TRUE); + + LayoutRootView(); +} |