diff options
author | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 22:12:54 +0000 |
---|---|---|
committer | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 22:12:54 +0000 |
commit | be0a73ff53ca0554a180228f364e535552eaff76 (patch) | |
tree | 293ac37f2aeb1dfcf3c08140260598e43349512e /chrome/browser | |
parent | 14bcec307d7ec6b13e90fe5e5ac8ca5aaa397b4b (diff) | |
download | chromium_src-be0a73ff53ca0554a180228f364e535552eaff76.zip chromium_src-be0a73ff53ca0554a180228f364e535552eaff76.tar.gz chromium_src-be0a73ff53ca0554a180228f364e535552eaff76.tar.bz2 |
Update Panel UI looks on Windows.
1) Add back wrench menu.
2) Remove about panel bubble.
3) Differentiate active and inactive panel by using different chrome theme.
BUG=none
TEST=panel_browser_view_browsertest
Review URL: http://codereview.chromium.org/6975062
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87703 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/ui/panels/about_panel_bubble.cc | 213 | ||||
-rw-r--r-- | chrome/browser/ui/panels/about_panel_bubble.h | 79 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel.cc | 15 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel.h | 4 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_frame_view.cc | 222 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_frame_view.h | 48 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_view.h | 2 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_view_browsertest.cc | 224 |
8 files changed, 352 insertions, 455 deletions
diff --git a/chrome/browser/ui/panels/about_panel_bubble.cc b/chrome/browser/ui/panels/about_panel_bubble.cc deleted file mode 100644 index 07ff668..0000000 --- a/chrome/browser/ui/panels/about_panel_bubble.cc +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2011 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/panels/about_panel_bubble.h" - -#include "base/i18n/time_formatting.h" -#include "base/logging.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/extensions/extension_prefs.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/web_applications/web_app.h" -#include "chrome/common/extensions/extension.h" -#include "grit/generated_resources.h" -#include "grit/locale_settings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "views/controls/image_view.h" -#include "views/controls/label.h" -#include "views/controls/link.h" -#include "views/controls/textfield/textfield.h" -#include "views/window/window.h" - -namespace { - -// Extra padding to put around content over what the InfoBubble provides. -const int kBubblePadding = 4; - -// Horizontal spacing between the icon and the contents. -const int kIconHorizontalSpacing = 4; - -// Vertical spacing between two controls. -const int kControlVerticalSpacing = 10; - -// Horizontal spacing between the text and the left/right of a description. -const int kDescriptionHorizontalSpacing = 6; - -// Vertical spacing between the text and the top/bottom of a description. -const int kDescriptionVertialSpacing = 4; - -// Horizontal spacing between two links. -const int kLinksHorizontalSpacing = 20; - -// Text color of a description. -const SkColor kDescriptionTextColor = SK_ColorBLACK; - -// Background color of a description. -const SkColor kDescriptionBackgroundColor = 0xFFE8E8EE; - -} - -// AboutPanelBubbleView -------------------------------------------------------- - -AboutPanelBubble::AboutPanelBubbleView::AboutPanelBubbleView( - SkBitmap icon, Browser* browser, const Extension* extension) - : icon_(NULL), - title_(NULL), - install_date_(NULL), - description_(NULL), - uninstall_link_(NULL), - report_abuse_link_(NULL) { - const gfx::Font& font = - ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); - - icon_ = new views::ImageView(); - icon_->SetImage(icon); - AddChildView(icon_); - - title_ = new views::Label(UTF8ToWide(extension->name())); - title_->SetFont(font.DeriveFont(0, gfx::Font::BOLD)); - title_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - AddChildView(title_); - - base::Time install_time = browser->GetProfile()->GetExtensionService()-> - extension_prefs()->GetInstallTime(extension->id()); - install_date_ = new views::Label(UTF16ToWide( - l10n_util::GetStringFUTF16( - IDS_ABOUT_PANEL_BUBBLE_EXTENSION_INSTALL_DATE, - base::TimeFormatFriendlyDate(install_time)))); - install_date_->SetMultiLine(true); - install_date_->SetFont(font); - install_date_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - install_date_->SizeToFit(GetPreferredSize().width() - kBubblePadding * 2); - AddChildView(install_date_); - - description_ = new views::Textfield(views::Textfield::STYLE_MULTILINE); - description_->SetText(UTF8ToUTF16(extension->description())); - description_->SetHeightInLines(2); - description_->SetHorizontalMargins(kDescriptionHorizontalSpacing, - kDescriptionHorizontalSpacing); - description_->SetVerticalMargins(kDescriptionVertialSpacing, - kDescriptionVertialSpacing); - description_->SetFont(font); - description_->SetTextColor(kDescriptionTextColor); - description_->SetBackgroundColor(kDescriptionBackgroundColor); - description_->RemoveBorder(); - description_->SetReadOnly(true); - AddChildView(description_); - - uninstall_link_ = new views::Link(UTF16ToWide( - l10n_util::GetStringFUTF16(IDS_ABOUT_PANEL_BUBBLE_UNINSTALL_EXTENSION, - UTF8ToUTF16(extension->name())))); - AddChildView(uninstall_link_); - - report_abuse_link_ = new views::Link(UTF16ToWide( - l10n_util::GetStringUTF16(IDS_ABOUT_PANEL_BUBBLE_REPORT_ABUSE))); - AddChildView(report_abuse_link_); -} - -void AboutPanelBubble::AboutPanelBubbleView::Layout() { - gfx::Size icon_size = icon_->GetPreferredSize(); - icon_->SetBounds(kBubblePadding, - kBubblePadding, - icon_size.width(), - icon_size.height()); - - gfx::Size canvas = GetPreferredSize(); - int content_left_margin = - kBubblePadding + icon_size.width() + kIconHorizontalSpacing; - int content_width = canvas.width() - kBubblePadding - content_left_margin; - - gfx::Size pref_size = title_->GetPreferredSize(); - title_->SetBounds(content_left_margin, - kBubblePadding, - content_width, - pref_size.height()); - - int next_y = title_->bounds().bottom() + kControlVerticalSpacing; - - pref_size = install_date_->GetPreferredSize(); - install_date_->SetBounds(content_left_margin, - next_y, - content_width, - pref_size.height()); - - next_y = install_date_->bounds().bottom() + kControlVerticalSpacing; - - pref_size = description_->GetPreferredSize(); - description_->SetBounds( - content_left_margin, - next_y, - content_width, - pref_size.height() + kDescriptionVertialSpacing * 2); - - next_y = description_->bounds().bottom() + kControlVerticalSpacing; - - pref_size = uninstall_link_->GetPreferredSize(); - uninstall_link_->SetBounds(content_left_margin, - next_y, - pref_size.width(), - pref_size.height()); - - pref_size = report_abuse_link_->GetPreferredSize(); - report_abuse_link_->SetBounds( - content_left_margin + uninstall_link_->width() + kLinksHorizontalSpacing, - next_y, - pref_size.width(), - pref_size.height()); -} - -gfx::Size AboutPanelBubble::AboutPanelBubbleView::GetPreferredSize() { - return views::Window::GetLocalizedContentsSize( - IDS_ABOUTPANELBUBBLE_WIDTH_CHARS, - IDS_ABOUTPANELBUBBLE_HEIGHT_LINES); -} - -void AboutPanelBubble::AboutPanelBubbleView::LinkClicked(views::Link* source, - int event_flags) { - NOTIMPLEMENTED(); -} - -// AboutPanelBubble ------------------------------------------------------------ - -// static -AboutPanelBubble* AboutPanelBubble::Show( - views::Widget* parent, - const gfx::Rect& position_relative_to, - BubbleBorder::ArrowLocation arrow_location, - SkBitmap icon, - Browser* browser) { - // Find the extension. When we create a panel from an extension, the extension - // ID is passed as the app name to the Browser. - ExtensionService* extension_service = - browser->GetProfile()->GetExtensionService(); - const Extension* extension = extension_service->GetExtensionById( - web_app::GetExtensionIdFromApplicationName(browser->app_name()), false); - if (!extension) - return NULL; - - AboutPanelBubble* bubble = new AboutPanelBubble(); - AboutPanelBubbleView* view = new AboutPanelBubbleView( - icon, browser, extension); - bubble->InitBubble( - parent, position_relative_to, arrow_location, view, bubble); - return bubble; -} - -AboutPanelBubble::AboutPanelBubble() { -} - -bool AboutPanelBubble::CloseOnEscape() { - return true; -} - -bool AboutPanelBubble::FadeInOnShow() { - return false; -} - -std::wstring AboutPanelBubble::accessible_name() { - return L"AboutPanelBubble"; -} diff --git a/chrome/browser/ui/panels/about_panel_bubble.h b/chrome/browser/ui/panels/about_panel_bubble.h deleted file mode 100644 index 6f6ddcc..0000000 --- a/chrome/browser/ui/panels/about_panel_bubble.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CHROME_BROWSER_UI_PANELS_ABOUT_PANEL_BUBBLE_H_ -#define CHROME_BROWSER_UI_PANELS_ABOUT_PANEL_BUBBLE_H_ -#pragma once - -#include "base/gtest_prod_util.h" -#include "chrome/browser/ui/views/bubble/bubble.h" -#include "views/controls/link_listener.h" - -class Browser; -class Extension; -namespace views { -class ImageView; -class Label; -class Link; -class Textfield; -} - -class AboutPanelBubble : public Bubble, - public BubbleDelegate { - public: - // Returns NULL if no extension can be found for |browser|. - static AboutPanelBubble* Show(views::Widget* parent, - const gfx::Rect& position_relative_to, - BubbleBorder::ArrowLocation arrow_location, - SkBitmap icon, - Browser* browser); - - private: - friend class PanelBrowserViewTest; - FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, AboutPanelBubble); - - class AboutPanelBubbleView : public views::View, - public views::LinkListener { - public: - AboutPanelBubbleView(SkBitmap icon, - Browser* browser, - const Extension* extension); - - private: - friend class PanelBrowserViewTest; - FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, AboutPanelBubble); - - virtual ~AboutPanelBubbleView() { } - - // Overridden from View: - virtual void Layout() OVERRIDE; - virtual gfx::Size GetPreferredSize() OVERRIDE; - - // Overridden from LinkListener: - virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; - - views::ImageView* icon_; - views::Label* title_; - views::Label* install_date_; - views::Textfield* description_; - views::Link* uninstall_link_; - views::Link* report_abuse_link_; - - DISALLOW_COPY_AND_ASSIGN(AboutPanelBubbleView); - }; - - AboutPanelBubble(); - virtual ~AboutPanelBubble() { } - - // Overridden from BubbleDelegate: - virtual void BubbleClosing(Bubble* info_bubble, bool closed_by_escape) - OVERRIDE {} - virtual bool CloseOnEscape() OVERRIDE; - virtual bool FadeInOnShow() OVERRIDE; - virtual std::wstring accessible_name() OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(AboutPanelBubble); -}; - -#endif // CHROME_BROWSER_UI_PANELS_ABOUT_PANEL_BUBBLE_H_ diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc index d246a5a..9aefef0 100644 --- a/chrome/browser/ui/panels/panel.cc +++ b/chrome/browser/ui/panels/panel.cc @@ -5,10 +5,25 @@ #include "chrome/browser/ui/panels/panel.h" #include "base/logging.h" +#include "chrome/browser/extensions/extension_prefs.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/panels/panel_manager.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/common/extensions/extension.h" #include "ui/gfx/rect.h" +// static +const Extension* Panel::GetExtension(Browser* browser) { + // Find the extension. When we create a panel from an extension, the extension + // ID is passed as the app name to the Browser. + ExtensionService* extension_service = + browser->GetProfile()->GetExtensionService(); + return extension_service->GetExtensionById( + web_app::GetExtensionIdFromApplicationName(browser->app_name()), false); +} + Panel::Panel(Browser* browser, const gfx::Rect& bounds) : bounds_(bounds), #ifndef NDEBUG diff --git a/chrome/browser/ui/panels/panel.h b/chrome/browser/ui/panels/panel.h index d65e5e0..676d081 100644 --- a/chrome/browser/ui/panels/panel.h +++ b/chrome/browser/ui/panels/panel.h @@ -133,6 +133,10 @@ class Panel : public BrowserWindow { // |browser|. static BrowserWindow* CreateNativePanel(Browser* browser, Panel* panel); + // Gets the extension from the browser that a panel is created from. + // Returns NULL if it cannot be found. + static const Extension* GetExtension(Browser* browser); + #ifdef UNIT_TEST BrowserWindow* browser_window() { return browser_window_.get(); } #endif diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.cc b/chrome/browser/ui/panels/panel_browser_frame_view.cc index 0e0b764..c2ff574 100644 --- a/chrome/browser/ui/panels/panel_browser_frame_view.cc +++ b/chrome/browser/ui/panels/panel_browser_frame_view.cc @@ -4,11 +4,14 @@ #include "chrome/browser/ui/panels/panel_browser_frame_view.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service.h" -#include "chrome/browser/ui/panels/about_panel_bubble.h" #include "chrome/browser/ui/panels/panel.h" #include "chrome/browser/ui/panels/panel_browser_view.h" #include "chrome/browser/ui/panels/panel_manager.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/url_constants.h" #include "content/browser/tab_contents/tab_contents.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -20,7 +23,9 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas_skia.h" #include "views/controls/button/image_button.h" +#include "views/controls/button/menu_button.h" #include "views/controls/label.h" +#include "views/controls/menu/menu_2.h" #include "views/painter.h" #include "views/screen.h" #include "views/window/window.h" @@ -88,7 +93,7 @@ struct EdgeResources { } }; -ButtonResources info_button_resources; +ButtonResources settings_button_resources; ButtonResources close_button_resources; EdgeResources frame_edges; EdgeResources client_edges; @@ -96,8 +101,7 @@ gfx::Font* active_font = NULL; gfx::Font* inactive_font = NULL; void LoadImageResources() { - // TODO(jianli): Use the right icon for the info button. - info_button_resources.SetResources( + settings_button_resources.SetResources( IDR_BALLOON_WRENCH, 0, IDR_BALLOON_WRENCH_H, IDR_BALLOON_WRENCH_P); close_button_resources.SetResources( @@ -191,26 +195,25 @@ PanelBrowserFrameView::PanelBrowserFrameView(BrowserFrame* frame, frame_(frame), browser_view_(browser_view), paint_state_(NOT_PAINTED), - info_button_(NULL), + settings_button_(NULL), close_button_(NULL), title_icon_(NULL), title_label_(NULL) { EnsureResourcesInitialized(); frame_->set_frame_type(views::Window::FRAME_TYPE_FORCE_CUSTOM); - info_button_ = new views::ImageButton(this); - info_button_->SetImage(views::CustomButton::BS_NORMAL, - info_button_resources.normal_image); - info_button_->SetImage(views::CustomButton::BS_HOT, - info_button_resources.hover_image); - info_button_->SetImage(views::CustomButton::BS_PUSHED, - info_button_resources.pushed_image); - info_button_->SetTooltipText( - UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_ABOUT_PANEL))); - info_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_ACCNAME_ABOUT_PANEL)); - info_button_->SetVisible(false); - AddChildView(info_button_); + settings_button_ = new views::MenuButton(NULL, std::wstring(), this, false); + settings_button_->SetIcon(*(settings_button_resources.normal_image)); + settings_button_->SetHoverIcon(*(settings_button_resources.hover_image)); + settings_button_->SetPushedIcon(*(settings_button_resources.pushed_image)); + settings_button_->set_alignment(views::TextButton::ALIGN_CENTER); + settings_button_->set_border(NULL); + settings_button_->SetTooltipText( + UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_SETTINGS))); + settings_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_SETTINGS)); + settings_button_->SetVisible(false); + AddChildView(settings_button_); close_button_ = new views::ImageButton(this); close_button_->SetImage(views::CustomButton::BS_NORMAL, @@ -324,14 +327,6 @@ void PanelBrowserFrameView::OnThemeChanged() { } void PanelBrowserFrameView::Layout() { - // Now that we know we have a parent, we can safely set our theme colors. - SkColor title_color = - GetThemeProvider()->GetColor(ThemeService::COLOR_TAB_TEXT); - title_label_->SetColor(title_color); - close_button_->SetBackground(title_color, - close_button_resources.normal_image, - close_button_resources.mask_image); - // Layout the close button. gfx::Size close_button_size = close_button_->GetPreferredSize(); close_button_->SetBounds( @@ -341,13 +336,13 @@ void PanelBrowserFrameView::Layout() { close_button_size.width(), close_button_size.height()); - // Layout the info button. - gfx::Size info_button_size = info_button_->GetPreferredSize(); - info_button_->SetBounds( - close_button_->x() - kButtonSpacing - info_button_size.width(), - (NonClientTopBorderHeight() - info_button_size.height()) / 2, - info_button_size.width(), - info_button_size.height()); + // Layout the settings button. + gfx::Size settings_button_size = settings_button_->GetPreferredSize(); + settings_button_->SetBounds( + close_button_->x() - kButtonSpacing - settings_button_size.width(), + (NonClientTopBorderHeight() - settings_button_size.height()) / 2, + settings_button_size.width(), + settings_button_size.height()); // Layout the icon. int icon_y = (NonClientTopBorderHeight() - kIconSize) / 2; @@ -363,7 +358,7 @@ void PanelBrowserFrameView::Layout() { title_label_->SetBounds( title_x, icon_y + ((kIconSize - title_height - 1) / 2), - std::max(0, info_button_->x() - kButtonSpacing - title_x), + std::max(0, settings_button_->x() - kButtonSpacing - title_x), title_height); // Calculate the client area bounds. @@ -408,15 +403,85 @@ void PanelBrowserFrameView::ButtonPressed(views::Button* sender, const views::Event& event) { if (sender == close_button_) frame_->Close(); - else if (sender == info_button_) { - gfx::Point origin(info_button_->bounds().origin()); - views::View::ConvertPointToScreen(this, &origin); - AboutPanelBubble::Show( - GetWidget(), - gfx::Rect(origin, info_button_->bounds().size()), - BubbleBorder::BOTTOM_RIGHT, - GetFaviconForTabIconView(), - browser_view_->browser()); +} + +void PanelBrowserFrameView::RunMenu(View* source, const gfx::Point& pt) { + EnsureSettingsMenuCreated(); + settings_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); +} + +bool PanelBrowserFrameView::IsCommandIdChecked(int command_id) const { + // Nothing in the menu is checked. + return false; +} + +bool PanelBrowserFrameView::IsCommandIdEnabled(int command_id) const { + const Extension* extension = GetExtension(); + if (!extension) + return false; + + switch (command_id) { + case COMMAND_NAME: + // The NAME links to the Homepage URL. If the extension doesn't have a + // homepage, we just disable this menu item. + return extension->GetHomepageURL().is_valid(); + case COMMAND_CONFIGURE: + return extension->options_url().spec().length() > 0; + case COMMAND_DISABLE: + case COMMAND_UNINSTALL: + // Some extension types can not be disabled or uninstalled. + return Extension::UserMayDisable(extension->location()); + case COMMAND_MANAGE: + return true; + default: + NOTREACHED(); + return false; + } +} + +bool PanelBrowserFrameView::GetAcceleratorForCommandId( + int command_id, ui::Accelerator* accelerator) { + return false; +} + +void PanelBrowserFrameView::ExecuteCommand(int command_id) { + const Extension* extension = GetExtension(); + if (!extension) + return; + + Browser* browser = browser_view_->browser(); + switch (command_id) { + case COMMAND_NAME: + browser->OpenURL(extension->GetHomepageURL(), + GURL(), + NEW_FOREGROUND_TAB, + PageTransition::LINK); + break; + case COMMAND_CONFIGURE: + DCHECK(!extension->options_url().is_empty()); + browser->GetProfile()->GetExtensionProcessManager()->OpenOptionsPage( + extension, browser); + break; + case COMMAND_DISABLE: + browser->GetProfile()->GetExtensionService()->DisableExtension( + extension->id()); + break; + case COMMAND_UNINSTALL: + // TODO(jianli): Need to handle the case that the extension API requests + // the panel to be closed when the uninstall dialog is still showing. + extension_uninstall_dialog_.reset(new ExtensionUninstallDialog( + browser->GetProfile())); + extension_uninstall_dialog_->ConfirmUninstall(this, extension); + break; + case COMMAND_MANAGE: + browser->OpenURL(GURL(chrome::kChromeUIExtensionsURL), + GURL(), + SINGLETON_TAB, + PageTransition::LINK); + break; + default: + NOTREACHED(); + break; } } @@ -432,6 +497,17 @@ SkBitmap PanelBrowserFrameView::GetFaviconForTabIconView() { return frame_->window_delegate()->GetWindowIcon(); } +void PanelBrowserFrameView::ExtensionDialogAccepted() { + const Extension* extension = GetExtension(); + if (extension) { + browser_view_->browser()->GetProfile()->GetExtensionService()-> + UninstallExtension(extension->id(), false, NULL); + } +} + +void PanelBrowserFrameView::ExtensionDialogCanceled() { +} + int PanelBrowserFrameView::NonClientBorderThickness() const { return kFrameBorderThickness + kClientEdgeThickness; } @@ -447,13 +523,23 @@ void PanelBrowserFrameView::UpdateControlStyles(PaintState paint_state) { return; paint_state_ = paint_state; - // For now, the only indication is whether the font is bold or not. + SkColor title_color = GetThemeProvider()-> + GetColor(paint_state == PAINT_AS_ACTIVE ? + ThemeService::COLOR_TAB_TEXT : + ThemeService::COLOR_BACKGROUND_TAB_TEXT); + title_label_->SetColor(title_color); title_label_->SetFont( paint_state == PAINT_AS_ACTIVE ? *active_font : *inactive_font); + + close_button_->SetBackground(title_color, + close_button_resources.normal_image, + close_button_resources.mask_image); } void PanelBrowserFrameView::PaintFrameBorder(gfx::Canvas* canvas) { - SkBitmap* theme_frame = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR); + SkBitmap* theme_frame = GetThemeProvider()->GetBitmapNamed( + (paint_state_ == PAINT_AS_ACTIVE) ? IDR_THEME_TOOLBAR + : IDR_THEME_TAB_BACKGROUND); // Draw the theme frame. canvas->TileImageInt(*theme_frame, 0, 0, width(), height()); @@ -545,16 +631,50 @@ void PanelBrowserFrameView::UpdateTitleBar() { } void PanelBrowserFrameView::OnActivationChanged(bool active) { - UpdateInfoButtonVisibility(active, mouse_watcher_->IsCursorInViewBounds()); + UpdateSettingsButtonVisibility(active, + mouse_watcher_->IsCursorInViewBounds()); SchedulePaint(); } void PanelBrowserFrameView::OnMouseEnterOrLeaveWindow(bool mouse_entered) { - UpdateInfoButtonVisibility(browser_view_->panel()->IsActive(), - mouse_entered); + // Panel might be closed when we still watch the mouse event. + if (!browser_view_->panel()) + return; + UpdateSettingsButtonVisibility(browser_view_->panel()->IsActive(), + mouse_entered); } -void PanelBrowserFrameView::UpdateInfoButtonVisibility(bool active, - bool cursor_in_view) { - info_button_->SetVisible(active || cursor_in_view); +void PanelBrowserFrameView::UpdateSettingsButtonVisibility( + bool active, bool cursor_in_view) { + settings_button_->SetVisible(active || cursor_in_view); +} + +const Extension* PanelBrowserFrameView::GetExtension() const { + return Panel::GetExtension(browser_view_->browser()); +} + +void PanelBrowserFrameView::EnsureSettingsMenuCreated() { + if (settings_menu_.get()) + return; + + const Extension* extension = GetExtension(); + if (!extension) + return; + + settings_menu_contents_.reset(new ui::SimpleMenuModel(this)); + + settings_menu_contents_->AddItem( + COMMAND_NAME, UTF8ToUTF16(extension->name())); + settings_menu_contents_->AddSeparator(); + settings_menu_contents_->AddItem( + COMMAND_CONFIGURE, l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS)); + settings_menu_contents_->AddItem( + COMMAND_DISABLE, l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE)); + settings_menu_contents_->AddItem( + COMMAND_UNINSTALL, l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNINSTALL)); + settings_menu_contents_->AddSeparator(); + settings_menu_contents_->AddItem( + COMMAND_MANAGE, l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS)); + + settings_menu_.reset(new views::Menu2(settings_menu_contents_.get())); } diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.h b/chrome/browser/ui/panels/panel_browser_frame_view.h index 2923208..09d1db4 100644 --- a/chrome/browser/ui/panels/panel_browser_frame_view.h +++ b/chrome/browser/ui/panels/panel_browser_frame_view.h @@ -9,19 +9,28 @@ #include "base/gtest_prod_util.h" #include "base/message_loop.h" #include "base/scoped_ptr.h" +#include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/tab_icon_view.h" +#include "ui/base/models/simple_menu_model.h" #include "views/controls/button/button.h" +#include "views/controls/menu/view_menu_delegate.h" +class Extension; class PanelBrowserView; namespace views { class ImageButton; class Label; +class Menu2; +class MenuButton; } class PanelBrowserFrameView : public BrowserNonClientFrameView, public views::ButtonListener, - public TabIconView::TabIconViewModel { + public views::ViewMenuDelegate, + public ui::SimpleMenuModel::Delegate, + public TabIconView::TabIconViewModel, + public ExtensionUninstallDialog::Delegate { public: PanelBrowserFrameView(BrowserFrame* frame, PanelBrowserView* browser_view); virtual ~PanelBrowserFrameView(); @@ -60,14 +69,28 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, virtual void ButtonPressed(views::Button* sender, const views::Event& event) OVERRIDE; + // Overridden from views::ViewMenuDelegate: + virtual void RunMenu(View* source, const gfx::Point& pt) OVERRIDE; + + // Overridden from ui::SimpleMenuModel::Delegate: + virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; + virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; + virtual bool GetAcceleratorForCommandId( + int command_id, ui::Accelerator* accelerator) OVERRIDE; + virtual void ExecuteCommand(int command_id) OVERRIDE; + // Overridden from TabIconView::TabIconViewModel: virtual bool ShouldTabIconViewAnimate() const OVERRIDE; virtual SkBitmap GetFaviconForTabIconView() OVERRIDE; + // ExtensionUninstallDialog::Delegate: + virtual void ExtensionDialogAccepted() OVERRIDE; + virtual void ExtensionDialogCanceled() OVERRIDE; + private: friend class PanelBrowserViewTest; FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, CreatePanel); - FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, ShowOrHideInfoButton); + FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, ShowOrHideSettingsButton); enum PaintState { NOT_PAINTED, @@ -75,6 +98,14 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, PAINT_AS_ACTIVE }; + enum { + COMMAND_NAME = 0, + COMMAND_CONFIGURE, + COMMAND_DISABLE, + COMMAND_UNINSTALL, + COMMAND_MANAGE + }; + class MouseWatcher : public MessageLoopForUI::Observer { public: explicit MouseWatcher(PanelBrowserFrameView* view); @@ -117,10 +148,14 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, // Called by MouseWatcher to notify if the mouse enters or leaves the window. void OnMouseEnterOrLeaveWindow(bool mouse_entered); - // Make info button visible if either of the conditions is met: + // Make settings button visible if either of the conditions is met: // 1) The panel is active, i.e. having focus. // 2) The mouse is over the panel. - void UpdateInfoButtonVisibility(bool active, bool cursor_in_view); + void UpdateSettingsButtonVisibility(bool active, bool cursor_in_view); + + const Extension* GetExtension() const; + + void EnsureSettingsMenuCreated(); #ifdef UNIT_TEST void set_mouse_watcher(MouseWatcher* mouse_watcher) { @@ -138,12 +173,15 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, PanelBrowserView* browser_view_; PaintState paint_state_; - views::ImageButton* info_button_; + views::MenuButton* settings_button_; views::ImageButton* close_button_; TabIconView* title_icon_; views::Label* title_label_; gfx::Rect client_view_bounds_; scoped_ptr<MouseWatcher> mouse_watcher_; + scoped_ptr<views::Menu2> settings_menu_; + scoped_ptr<ui::SimpleMenuModel> settings_menu_contents_; + scoped_ptr<ExtensionUninstallDialog> extension_uninstall_dialog_; DISALLOW_COPY_AND_ASSIGN(PanelBrowserFrameView); }; diff --git a/chrome/browser/ui/panels/panel_browser_view.h b/chrome/browser/ui/panels/panel_browser_view.h index a7ad350..aff1210 100644 --- a/chrome/browser/ui/panels/panel_browser_view.h +++ b/chrome/browser/ui/panels/panel_browser_view.h @@ -36,7 +36,7 @@ class PanelBrowserView : public ::BrowserView, private: friend class PanelBrowserViewTest; FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, CreatePanel); - FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, ShowOrHideInfoButton); + FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, ShowOrHideSettingsButton); FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, SetBoundsAnimation); // Overridden from BrowserView: diff --git a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc index 3258e15..b044678 100644 --- a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc +++ b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc @@ -8,7 +8,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/panels/about_panel_bubble.h" #include "chrome/browser/ui/panels/panel.h" #include "chrome/browser/ui/panels/panel_browser_frame_view.h" #include "chrome/browser/ui/panels/panel_browser_view.h" @@ -21,9 +20,11 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/animation/slide_animation.h" #include "views/controls/button/image_button.h" +#include "views/controls/button/menu_button.h" #include "views/controls/image_view.h" #include "views/controls/label.h" #include "views/controls/link.h" +#include "views/controls/menu/menu_2.h" #include "views/controls/textfield/textfield.h" class PanelBrowserViewTest : public InProcessBrowserTest { @@ -35,6 +36,11 @@ class PanelBrowserViewTest : public InProcessBrowserTest { } protected: + struct MenuItem { + int id; + bool enabled; + }; + class MockMouseWatcher : public PanelBrowserFrameView::MouseWatcher { public: explicit MockMouseWatcher(PanelBrowserFrameView* view) @@ -161,6 +167,94 @@ class PanelBrowserViewTest : public InProcessBrowserTest { } } } + + void ValidateSettingsMenuItems(ui::SimpleMenuModel* settings_menu_contents, + size_t num_expected_menu_items, + const MenuItem* expected_menu_items) { + ASSERT_TRUE(settings_menu_contents); + EXPECT_EQ(static_cast<int>(num_expected_menu_items), + settings_menu_contents->GetItemCount()); + for (size_t i = 0; i < num_expected_menu_items; ++i) { + if (expected_menu_items[i].id == -1) { + EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, + settings_menu_contents->GetTypeAt(i)); + } else { + EXPECT_EQ(expected_menu_items[i].id, + settings_menu_contents->GetCommandIdAt(i)); + EXPECT_EQ(expected_menu_items[i].enabled, + settings_menu_contents->IsEnabledAt(i)); + } + } + } + + void TestCreateSettingsMenuForExtension(const FilePath::StringType& path, + Extension::Location location, + const std::string& homepage_url, + const std::string& options_page) { + // Creates a testing extension. +#if defined(OS_WIN) + FilePath full_path(FILE_PATH_LITERAL("c:\\")); +#else + FilePath full_path(FILE_PATH_LITERAL("/")); +#endif + full_path.Append(path); + DictionaryValue input_value; + input_value.SetString(extension_manifest_keys::kVersion, "1.0.0.0"); + input_value.SetString(extension_manifest_keys::kName, "Sample Extension"); + if (!homepage_url.empty()) { + input_value.SetString(extension_manifest_keys::kHomepageURL, + homepage_url); + } + if (!options_page.empty()) { + input_value.SetString(extension_manifest_keys::kOptionsPage, + options_page); + } + std::string error; + scoped_refptr<Extension> extension = Extension::Create( + full_path, location, input_value, Extension::STRICT_ERROR_CHECKS, + &error); + ASSERT_TRUE(extension.get()); + EXPECT_STREQ("", error.c_str()); + browser()->GetProfile()->GetExtensionService()->AddExtension( + extension.get()); + + // Makes sure that async task ExtensionPrefs::OnExtensionInstalled gets a + // chance to be procesed. + MessageLoop::current()->RunAllPending(); + + // Creates a panel with the app name that comes from the extension ID. + PanelBrowserView* browser_view = CreatePanelBrowserView( + web_app::GenerateApplicationNameFromExtensionId(extension->id())); + PanelBrowserFrameView* frame_view = browser_view->GetFrameView(); + + frame_view->EnsureSettingsMenuCreated(); + ASSERT_TRUE(frame_view->settings_menu_.get()); + ASSERT_TRUE(frame_view->settings_menu_contents_.get()); + + // Validates the settings menu items. + MenuItem expected_panel_menu_items[] = { + { PanelBrowserFrameView::COMMAND_NAME, false }, + { -1, false }, // Separator + { PanelBrowserFrameView::COMMAND_CONFIGURE, false }, + { PanelBrowserFrameView::COMMAND_DISABLE, false }, + { PanelBrowserFrameView::COMMAND_UNINSTALL, false }, + { -1, false }, // Separator + { PanelBrowserFrameView::COMMAND_MANAGE, true } + }; + if (!homepage_url.empty()) + expected_panel_menu_items[0].enabled = true; + if (!options_page.empty()) + expected_panel_menu_items[2].enabled = true; + if (location != Extension::EXTERNAL_POLICY_DOWNLOAD) { + expected_panel_menu_items[3].enabled = true; + expected_panel_menu_items[4].enabled = true; + } + ValidateSettingsMenuItems(frame_view->settings_menu_contents_.get(), + arraysize(expected_panel_menu_items), + expected_panel_menu_items); + + browser_view->panel()->Close(); + } }; // Panel is not supported for Linux view yet. @@ -173,11 +267,11 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) { // first time. EXPECT_FALSE(browser_view->bounds_animator_.get()); - // We should have icon, text, options button and close button. + // We should have icon, text, settings button and close button. EXPECT_EQ(4, frame_view->child_count()); EXPECT_TRUE(frame_view->Contains(frame_view->title_icon_)); EXPECT_TRUE(frame_view->Contains(frame_view->title_label_)); - EXPECT_TRUE(frame_view->Contains(frame_view->info_button_)); + EXPECT_TRUE(frame_view->Contains(frame_view->settings_button_)); EXPECT_TRUE(frame_view->Contains(frame_view->close_button_)); // These controls should be visible. @@ -194,18 +288,18 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) { EXPECT_GT(frame_view->title_label_->width(), 0); EXPECT_GT(frame_view->title_label_->height(), 0); EXPECT_LT(frame_view->title_label_->height(), title_bar_height); - EXPECT_GT(frame_view->info_button_->width(), 0); - EXPECT_GT(frame_view->info_button_->height(), 0); - EXPECT_LT(frame_view->info_button_->height(), title_bar_height); + EXPECT_GT(frame_view->settings_button_->width(), 0); + EXPECT_GT(frame_view->settings_button_->height(), 0); + EXPECT_LT(frame_view->settings_button_->height(), title_bar_height); EXPECT_GT(frame_view->close_button_->width(), 0); EXPECT_GT(frame_view->close_button_->height(), 0); EXPECT_LT(frame_view->close_button_->height(), title_bar_height); EXPECT_LT(frame_view->title_icon_->x() + frame_view->title_icon_->width(), frame_view->title_label_->x()); EXPECT_LT(frame_view->title_label_->x() + frame_view->title_label_->width(), - frame_view->info_button_->x()); + frame_view->settings_button_->x()); EXPECT_LT( - frame_view->info_button_->x() + frame_view->info_button_->width(), + frame_view->settings_button_->x() + frame_view->settings_button_->width(), frame_view->close_button_->x()); // Validate that the controls should be updated when the activation state is @@ -217,7 +311,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) { EXPECT_NE(title_label_font1.GetStyle(), title_label_font2.GetStyle()); } -IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideInfoButton) { +IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideSettingsButton) { PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest"); PanelBrowserFrameView* frame_view = browser_view->GetFrameView(); @@ -231,21 +325,21 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideInfoButton) { // test the cases that the panel is active first. EXPECT_TRUE(browser_view->panel()->IsActive()); - // When the panel is active, the info button should always be visible. + // When the panel is active, the settings button should always be visible. mouse_watcher->MoveMouse(true); - EXPECT_TRUE(frame_view->info_button_->IsVisible()); + EXPECT_TRUE(frame_view->settings_button_->IsVisible()); mouse_watcher->MoveMouse(false); - EXPECT_TRUE(frame_view->info_button_->IsVisible()); + EXPECT_TRUE(frame_view->settings_button_->IsVisible()); - // When the panel is inactive, the info button is active per the mouse over + // When the panel is inactive, the options button is active per the mouse over // the panel or not. browser_view->panel()->Deactivate(); EXPECT_FALSE(browser_view->panel()->IsActive()); mouse_watcher->MoveMouse(true); - EXPECT_TRUE(frame_view->info_button_->IsVisible()); + EXPECT_TRUE(frame_view->settings_button_->IsVisible()); mouse_watcher->MoveMouse(false); - EXPECT_FALSE(frame_view->info_button_->IsVisible()); + EXPECT_FALSE(frame_view->settings_button_->IsVisible()); } IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, TitleBarMouseEvent) { @@ -423,97 +517,6 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, TitleBarMouseEvent) { } } -IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, AboutPanelBubble) { - ExtensionService* extension_service = - browser()->GetProfile()->GetExtensionService(); - - // Create a testing extension. -#if defined(OS_WIN) - FilePath path(FILE_PATH_LITERAL("c:\\foo")); -#else - FilePath path(FILE_PATH_LITERAL("/foo")); -#endif - DictionaryValue input_value; - input_value.SetString(extension_manifest_keys::kVersion, "1.0.0.0"); - input_value.SetString(extension_manifest_keys::kName, "Sample Extension"); - input_value.SetString(extension_manifest_keys::kDescription, - "Sample Description"); - scoped_refptr<Extension> extension(Extension::Create(path, Extension::INVALID, - input_value, Extension::STRICT_ERROR_CHECKS, NULL)); - ASSERT_TRUE(extension.get()); - extension_service->AddExtension(extension.get()); - // Make sure that async task ExtensionPrefs::OnExtensionInstalled gets a - // chance to be procesed. - MessageLoop::current()->RunAllPending(); - - extension_service->extension_prefs()->OnExtensionInstalled( - extension, Extension::ENABLED); - - // Create a panel with the app name that comes from the extension ID. - PanelBrowserView* browser_view = CreatePanelBrowserView( - web_app::GenerateApplicationNameFromExtensionId(extension->id())); - - AboutPanelBubble* bubble = AboutPanelBubble::Show( - browser_view->GetWidget(), - gfx::Rect(), - BubbleBorder::BOTTOM_RIGHT, - SkBitmap(), - browser_view->browser()); - AboutPanelBubble::AboutPanelBubbleView* contents = - static_cast<AboutPanelBubble::AboutPanelBubbleView*>(bubble->contents()); - - // We should have the expected controls. - EXPECT_EQ(6, contents->child_count()); - EXPECT_TRUE(contents->Contains(contents->icon_)); - EXPECT_TRUE(contents->Contains(contents->title_)); - EXPECT_TRUE(contents->Contains(contents->install_date_)); - EXPECT_TRUE(contents->Contains(contents->description_)); - EXPECT_TRUE(contents->Contains(contents->uninstall_link_)); - EXPECT_TRUE(contents->Contains(contents->report_abuse_link_)); - - // These controls should be visible. - EXPECT_TRUE(contents->icon_->IsVisible()); - EXPECT_TRUE(contents->title_->IsVisible()); - EXPECT_TRUE(contents->install_date_->IsVisible()); - EXPECT_TRUE(contents->description_->IsVisible()); - EXPECT_TRUE(contents->uninstall_link_->IsVisible()); - EXPECT_TRUE(contents->report_abuse_link_->IsVisible()); - - // Validate their layouts. - EXPECT_GT(contents->title_->x(), contents->icon_->x()); - EXPECT_GT(contents->title_->width(), 0); - EXPECT_GT(contents->title_->height(), 0); - EXPECT_EQ(contents->install_date_->x(), contents->title_->x()); - EXPECT_GT(contents->install_date_->y(), contents->title_->y()); - EXPECT_GT(contents->install_date_->width(), 0); - EXPECT_GT(contents->install_date_->height(), 0); - EXPECT_EQ(contents->description_->x(), contents->install_date_->x()); - EXPECT_GT(contents->description_->y(), contents->install_date_->y()); - EXPECT_GT(contents->description_->width(), 0); - EXPECT_GT(contents->description_->height(), 0); - EXPECT_EQ(contents->uninstall_link_->x(), contents->description_->x()); - EXPECT_GT(contents->uninstall_link_->y(), contents->description_->y()); - EXPECT_GT(contents->uninstall_link_->width(), 0); - EXPECT_GT(contents->uninstall_link_->height(), 0); - EXPECT_GT(contents->report_abuse_link_->x(), contents->uninstall_link_->x()); - EXPECT_EQ(contents->report_abuse_link_->y(), contents->uninstall_link_->y()); - EXPECT_GT(contents->report_abuse_link_->width(), 0); - EXPECT_GT(contents->report_abuse_link_->height(), 0); - - // Validates the texts. - base::Time install_time = - extension_service->extension_prefs()->GetInstallTime(extension->id()); - string16 time_text = l10n_util::GetStringFUTF16( - IDS_ABOUT_PANEL_BUBBLE_EXTENSION_INSTALL_DATE, - base::TimeFormatFriendlyDate( - extension_service->extension_prefs()->GetInstallTime( - extension->id()))); - EXPECT_STREQ(UTF16ToUTF8(time_text).c_str(), - WideToUTF8(contents->install_date_->GetText()).c_str()); - EXPECT_STREQ(extension->description().c_str(), - UTF16ToUTF8(contents->description_->text()).c_str()); -} - IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, SetBoundsAnimation) { PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest"); @@ -550,4 +553,13 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, SetBoundsAnimation) { browser_view->panel()->Close(); } + +IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreateSettingsMenu) { + TestCreateSettingsMenuForExtension( + FILE_PATH_LITERAL("extension1"), Extension::EXTERNAL_POLICY_DOWNLOAD, + "", ""); + TestCreateSettingsMenuForExtension( + FILE_PATH_LITERAL("extension2"), Extension::INVALID, + "http://home", "options.html"); +} #endif |