diff options
Diffstat (limited to 'chrome/browser/views')
31 files changed, 2569 insertions, 2246 deletions
diff --git a/chrome/browser/views/accelerator_table_gtk.cc b/chrome/browser/views/accelerator_table_gtk.cc index 9e1f6c9..c8b54f7 100644 --- a/chrome/browser/views/accelerator_table_gtk.cc +++ b/chrome/browser/views/accelerator_table_gtk.cc @@ -115,6 +115,7 @@ const AcceleratorMapping kAcceleratorMap[] = { // Miscellany. { base::VKEY_D, false, true, false, IDC_BOOKMARK_PAGE }, { base::VKEY_D, true, true, false, IDC_BOOKMARK_ALL_TABS }, + { base::VKEY_B, false, true, false, IDC_SHOW_BOOKMARK_BAR }, { base::VKEY_DELETE, true, true, false, IDC_CLEAR_BROWSING_DATA }, { base::VKEY_H, false, true, false, IDC_SHOW_HISTORY }, { base::VKEY_J, false, true, false, IDC_SHOW_DOWNLOADS }, @@ -128,7 +129,7 @@ const AcceleratorMapping kAcceleratorMap[] = { { base::VKEY_F11, false, true, true, IDC_FULLSCREEN }, { base::VKEY_DELETE, false, true, true, IDC_TASK_MANAGER }, { base::VKEY_OEM_COMMA, false, true, false, IDC_SYSTEM_OPTIONS }, - { base::VKEY_B, true, true, false, IDC_SHOW_BOOKMARK_BAR }, + { base::VKEY_B, true, true, false, IDC_SHOW_BOOKMARK_MANAGER }, #if !defined(OS_CHROMEOS) { base::VKEY_F1, false, false, false, IDC_HELP_PAGE }, #endif diff --git a/chrome/browser/views/app_launcher.cc b/chrome/browser/views/app_launcher.cc index a074f84..d1e87aa 100644 --- a/chrome/browser/views/app_launcher.cc +++ b/chrome/browser/views/app_launcher.cc @@ -16,13 +16,12 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/bubble_positioner.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/view_ids.h" #include "chrome/browser/views/dom_view.h" #include "chrome/browser/views/info_bubble.h" #include "chrome/browser/views/frame/browser_view.h" -#include "chrome/browser/views/toolbar_view.h" #include "chrome/common/url_constants.h" #include "views/widget/root_view.h" #include "views/widget/widget.h" @@ -46,11 +45,10 @@ const int kNavigationEntryYMargin = 1; // Padding between the navigation bar and the render view contents. const int kNavigationBarBottomPadding = 3; -// NavigationBar constants. -const int kNavigationBarHeight = 23; -const int kNavigationBarBorderThickness = 1; +// NavigationBar size. +const int kNavigationBarHeight = 25; -// The delta applied to the default font size for the Omnibox. +// The delta applied to the default font size for the omnibox. const int kAutocompleteEditFontDelta = 3; // Command line switch for specifying url of the page. @@ -74,7 +72,8 @@ static GURL GetMenuURL() { // mode. class NavigationBar : public views::View, - public AutocompleteEditController { + public AutocompleteEditController, + public BubblePositioner { public: explicit NavigationBar(AppLauncher* app_launcher) : app_launcher_(app_launcher), @@ -82,12 +81,7 @@ class NavigationBar : public views::View, SetFocusable(true); location_entry_view_ = new views::NativeViewHost; AddChildView(location_entry_view_); - set_border(views::Border::CreateSolidBorder(kNavigationBarBorderThickness, - SK_ColorGRAY)); - - AddChildView(&popup_positioning_view_); - popup_positioning_view_.SetVisible(false); - popup_positioning_view_.set_parent_owned(false); + set_border(views::Border::CreateSolidBorder(1, SK_ColorGRAY)); } virtual ~NavigationBar() { @@ -117,8 +111,7 @@ class NavigationBar : public views::View, new AutocompleteEditViewWin(font, this, browser->toolbar_model(), this, GetWidget()->GetNativeView(), browser->profile(), - browser->command_updater(), false, - &popup_positioning_view_); + browser->command_updater(), false, this); location_entry_.reset(autocomplete_view); autocomplete_view->Update(NULL); // The Update call above sets the autocomplete text to the current one in @@ -128,11 +121,10 @@ class NavigationBar : public views::View, AutocompleteEditViewGtk* autocomplete_view = new AutocompleteEditViewGtk(this, browser->toolbar_model(), browser->profile(), - browser->command_updater(), false, - &popup_positioning_view_); + browser->command_updater(), false, this); autocomplete_view->Init(); - gtk_widget_show_all(autocomplete_view->GetNativeView()); - gtk_widget_hide(autocomplete_view->GetNativeView()); + gtk_widget_show_all(autocomplete_view->widget()); + gtk_widget_hide(autocomplete_view->widget()); location_entry_.reset(autocomplete_view); #else NOTIMPLEMENTED(); @@ -149,10 +141,21 @@ class NavigationBar : public views::View, bounds.width() - 2 * (kNavigationEntryPadding + kNavigationEntryXMargin), bounds.height() - kNavigationEntryYMargin * 2); + } - gfx::Rect popup_positioning_bounds(bounds); - popup_positioning_bounds.Inset(0, -(kNavigationBarBorderThickness + 1)); - popup_positioning_view_.SetBounds(popup_positioning_bounds); + // BubblePositioner implementation. + virtual gfx::Rect GetLocationStackBounds() const { + gfx::Rect bounds = location_entry_view_->GetBounds( + views::View::APPLY_MIRRORING_TRANSFORMATION); + gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding); + views::View::ConvertPointToScreen(this, &origin); + gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0)); + if (UILayoutIsRightToLeft()) { + // Align the window to the right side of the entry view when + // UI is RTL mode. + rect.set_x(rect.x() - (rect.width() - location_entry_view_->width())); + } + return rect; } // AutocompleteController implementation. @@ -192,11 +195,6 @@ class NavigationBar : public views::View, NOTIMPLEMENTED(); #endif - // This invisible view is provided to the popup in place of |this|, so the - // popup can size itself against it using the same offsets it does with the - // LocationBarView. - views::View popup_positioning_view_; - DISALLOW_COPY_AND_ASSIGN(NavigationBar); }; @@ -239,7 +237,6 @@ InfoBubbleContentsView::InfoBubbleContentsView(AppLauncher* app_launcher) : app_launcher_(app_launcher), navigation_bar_(NULL), dom_view_(NULL) { - DCHECK(app_launcher); } InfoBubbleContentsView::~InfoBubbleContentsView() { @@ -302,7 +299,6 @@ void InfoBubbleContentsView::Layout() { AppLauncher::AppLauncher(Browser* browser) : browser_(browser), info_bubble_(NULL) { - DCHECK(browser); info_bubble_content_ = new InfoBubbleContentsView(this); } @@ -310,15 +306,12 @@ AppLauncher::~AppLauncher() { } // static -AppLauncher* AppLauncher::Show(Browser* browser, - const gfx::Rect& bounds, - const gfx::Point& bubble_anchor) { +AppLauncher* AppLauncher::Show(Browser* browser, const gfx::Rect& bounds) { AppLauncher* app_launcher = new AppLauncher(browser); BrowserView* browser_view = static_cast<BrowserView*>(browser->window()); app_launcher->info_bubble_ = - PinnedContentsInfoBubble::Show(browser_view->frame()->GetWindow(), - bounds, bubble_anchor, app_launcher->info_bubble_content_, - app_launcher); + InfoBubble::Show(browser_view->frame()->GetWindow(), bounds, + app_launcher->info_bubble_content_, app_launcher); app_launcher->info_bubble_content_->BubbleShown(); return app_launcher; } @@ -333,17 +326,7 @@ AppLauncher* AppLauncher::ShowForNewTab(Browser* browser) { gfx::Point origin = bounds.origin(); views::RootView::ConvertPointToScreen(tabstrip, &origin); bounds.set_origin(origin); - - // Figure out where the location bar is, so we can pin the bubble to - // make our url bar appear exactly over it. - views::RootView* root_view = views::Widget::GetWidgetFromNativeWindow( - browser_view->GetNativeHandle())->GetRootView(); - views::View* location_bar = root_view->GetViewByID(VIEW_ID_LOCATION_BAR); - gfx::Point location_bar_origin = location_bar->bounds().origin(); - views::RootView::ConvertPointToScreen(location_bar->GetParent(), - &location_bar_origin); - - return Show(browser, bounds, location_bar_origin); + return Show(browser, bounds); } void AppLauncher::Hide() { @@ -369,6 +352,7 @@ void AppLauncher::InfoBubbleClosing(InfoBubble* info_bubble, new DeleteTask<AppLauncher>(this)); } + void AppLauncher::AddTabWithURL(const GURL& url, PageTransition::Type transition) { #if defined(OS_CHROMEOS) diff --git a/chrome/browser/views/app_launcher.h b/chrome/browser/views/app_launcher.h index fa5cc03..229f265 100644 --- a/chrome/browser/views/app_launcher.h +++ b/chrome/browser/views/app_launcher.h @@ -7,7 +7,7 @@ #include "base/scoped_ptr.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" -#include "chrome/browser/views/pinned_contents_info_bubble.h" +#include "chrome/browser/views/info_bubble.h" #include "views/view.h" class Browser; @@ -49,17 +49,13 @@ class TabContentsDelegateImpl; // When a new url is opened, or the user clicks outsides the bounds of the // widget the app launcher is closed. class AppLauncher : public InfoBubbleDelegate, - public TabContentsDelegate { + public TabContentsDelegate { public: // Shows an application launcher bubble pointing to the |bounds| (which should - // be in screen coordinates). |bubble_anchor| specifies at which coordinates - // the bubble contents should appear (in screen coordinates). The bubble will - // be moved accordingly. + // be in screen coordinates). // The caller DOES NOT OWN the AppLauncher returned. It is deleted // automatically when the AppLauncher is closed. - static AppLauncher* Show(Browser* browser, - const gfx::Rect& bounds, - const gfx::Point& bubble_anchor); + static AppLauncher* Show(Browser* browser, const gfx::Rect& bounds); // Shows an application launcher bubble pointing to the new tab button. // The caller DOES NOT OWN the AppLauncher returned. It is deleted @@ -111,8 +107,8 @@ class AppLauncher : public InfoBubbleDelegate, // The currently active browser. We use this to open urls. Browser* browser_; - // The InfoBubble displaying the Omnibox and app contents. - PinnedContentsInfoBubble* info_bubble_; + // The InfoBubble displaying the omnibox and app contents. + InfoBubble* info_bubble_; // The view with the navigation bar and render view, shown in the info-bubble. InfoBubbleContentsView* info_bubble_content_; diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc index de0464e..d5eb1f3 100644 --- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc +++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc @@ -12,6 +12,7 @@ #include "base/i18n/rtl.h" #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/bubble_positioner.h" #include "chrome/browser/views/bubble_border.h" #include "gfx/canvas.h" #include "gfx/color_utils.h" @@ -90,8 +91,13 @@ const int kIconVerticalPadding = 2; // bottom of the row. See comment about the use of "minimum" for // kIconVerticalPadding. const int kTextVerticalPadding = 3; -// The padding between horizontally adjacent items (including row edges). -const int kHorizontalPadding = 3; +// The padding at the left edge of the row, left of the icon. +const int kRowLeftPadding = 6; +// The padding on the right edge of the row, right of the text. +const int kRowRightPadding = 3; +// The horizontal distance between the right edge of the icon and the left edge +// of the text. +const int kIconTextSpacing = 9; // The size delta between the font used for the edit and the result rows. Passed // to gfx::Font::DeriveFont. #if !defined(OS_CHROMEOS) @@ -164,15 +170,40 @@ class AutocompleteResultView : public views::View { gfx::Rect icon_bounds_; gfx::Rect text_bounds_; + // Icons for rows. + static SkBitmap* icon_url_; + static SkBitmap* icon_url_selected_; + static SkBitmap* icon_history_; + static SkBitmap* icon_history_selected_; + static SkBitmap* icon_search_; + static SkBitmap* icon_search_selected_; + static SkBitmap* icon_more_; + static SkBitmap* icon_more_selected_; + static SkBitmap* icon_star_; + static SkBitmap* icon_star_selected_; static int icon_size_; AutocompleteMatch match_; + static bool initialized_; + static void InitClass(); + DISALLOW_COPY_AND_ASSIGN(AutocompleteResultView); }; // static +SkBitmap* AutocompleteResultView::icon_url_ = NULL; +SkBitmap* AutocompleteResultView::icon_url_selected_ = NULL; +SkBitmap* AutocompleteResultView::icon_history_ = NULL; +SkBitmap* AutocompleteResultView::icon_history_selected_ = NULL; +SkBitmap* AutocompleteResultView::icon_search_ = NULL; +SkBitmap* AutocompleteResultView::icon_search_selected_ = NULL; +SkBitmap* AutocompleteResultView::icon_star_ = NULL; +SkBitmap* AutocompleteResultView::icon_star_selected_ = NULL; +SkBitmap* AutocompleteResultView::icon_more_ = NULL; +SkBitmap* AutocompleteResultView::icon_more_selected_ = NULL; int AutocompleteResultView::icon_size_ = 0; +bool AutocompleteResultView::initialized_ = false; // This class is a utility class which mirrors an x position, calculates the // index of the i-th run of a text, and calculates the index of the i-th @@ -291,11 +322,7 @@ AutocompleteResultView::AutocompleteResultView( mirroring_context_(new MirroringContext()), match_(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED) { CHECK(model_index >= 0); - if (icon_size_ == 0) { - icon_size_ = ResourceBundle::GetSharedInstance().GetBitmapNamed( - AutocompleteMatch::TypeToIcon(AutocompleteMatch::URL_WHAT_YOU_TYPED))-> - width(); - } + InitClass(); } AutocompleteResultView::~AutocompleteResultView() { @@ -317,8 +344,7 @@ void AutocompleteResultView::Paint(gfx::Canvas* canvas) { // position of an input text. bool text_mirroring = View::UILayoutIsRightToLeft(); int text_left = MirroredLeftPointForRect(text_bounds_); - int text_right = - text_mirroring ? (x - kHorizontalPadding) : text_bounds_.right(); + int text_right = text_mirroring ? x - kIconTextSpacing : text_bounds_.right(); x = mirroring_context_->Initialize(text_left, text_right, text_mirroring); x = DrawString(canvas, match_.contents, match_.contents_class, false, x, text_bounds_.y()); @@ -339,11 +365,13 @@ void AutocompleteResultView::Paint(gfx::Canvas* canvas) { } void AutocompleteResultView::Layout() { - icon_bounds_.SetRect(kHorizontalPadding, (height() - icon_size_) / 2, + icon_bounds_.SetRect(kRowLeftPadding, (height() - icon_size_) / 2, icon_size_, icon_size_); - int text_x = icon_bounds_.right() + kHorizontalPadding; - text_bounds_.SetRect(text_x, std::max(0, (height() - font_.height()) / 2), - std::max(0, bounds().right() - text_x - kHorizontalPadding), + int text_x = icon_bounds_.right() + kIconTextSpacing; + text_bounds_.SetRect( + text_x, + std::max(0, (height() - font_.height()) / 2), + std::max(0, bounds().right() - text_x - kRowRightPadding), font_.height()); } @@ -361,19 +389,29 @@ ResultViewState AutocompleteResultView::GetState() const { } SkBitmap* AutocompleteResultView::GetIcon() const { - int icon = match_.starred ? - IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type); - if (model_->IsSelectedIndex(model_index_)) { - switch (icon) { - case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_SELECTED; break; - case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_SELECTED; break; - case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_SELECTED; break; - case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_SELECTED; break; - case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_SELECTED; break; - default: NOTREACHED(); break; - } + bool selected = model_->IsSelectedIndex(model_index_); + if (match_.starred) + return selected ? icon_star_selected_ : icon_star_; + switch (match_.type) { + case AutocompleteMatch::URL_WHAT_YOU_TYPED: + case AutocompleteMatch::HISTORY_URL: + case AutocompleteMatch::NAVSUGGEST: + return selected ? icon_url_selected_ : icon_url_; + case AutocompleteMatch::HISTORY_TITLE: + case AutocompleteMatch::HISTORY_BODY: + case AutocompleteMatch::HISTORY_KEYWORD: + return selected ? icon_history_selected_ : icon_history_; + case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: + case AutocompleteMatch::SEARCH_HISTORY: + case AutocompleteMatch::SEARCH_SUGGEST: + case AutocompleteMatch::SEARCH_OTHER_ENGINE: + return selected ? icon_search_selected_ : icon_search_; + case AutocompleteMatch::OPEN_HISTORY_PAGE: + return selected ? icon_more_selected_ : icon_more_; + default: + NOTREACHED(); + return NULL; } - return ResourceBundle::GetSharedInstance().GetBitmapNamed(icon); } int AutocompleteResultView::DrawString( @@ -470,7 +508,7 @@ int AutocompleteResultView::DrawStringFragment( // Clamp text width to the available width within the popup so we elide if // necessary. int string_width = std::min(display_font.GetStringWidth(text), - width() - kHorizontalPadding - x); + width() - kRowRightPadding - x); int string_left = mirroring_context_->GetLeft(x, x + string_width); const int flags = force_rtl_directionality ? gfx::Canvas::FORCE_RTL_DIRECTIONALITY : 0; @@ -493,6 +531,25 @@ SkColor AutocompleteResultView::GetFragmentTextColor(int style) const { (style & ACMatchClassification::DIM) ? DIMMED_TEXT : TEXT); } +void AutocompleteResultView::InitClass() { + if (!initialized_) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + icon_url_ = rb.GetBitmapNamed(IDR_O2_GLOBE); + icon_url_selected_ = rb.GetBitmapNamed(IDR_O2_GLOBE_SELECTED); + icon_history_ = rb.GetBitmapNamed(IDR_O2_HISTORY); + icon_history_selected_ = rb.GetBitmapNamed(IDR_O2_HISTORY_SELECTED); + icon_search_ = rb.GetBitmapNamed(IDR_O2_SEARCH); + icon_search_selected_ = rb.GetBitmapNamed(IDR_O2_SEARCH_SELECTED); + icon_star_ = rb.GetBitmapNamed(IDR_O2_STAR); + icon_star_selected_ = rb.GetBitmapNamed(IDR_O2_STAR_SELECTED); + icon_more_ = rb.GetBitmapNamed(IDR_O2_MORE); + icon_more_selected_ = rb.GetBitmapNamed(IDR_O2_MORE_SELECTED); + // All icons are assumed to be square, and the same size. + icon_size_ = icon_url_->width(); + initialized_ = true; + } +} + //////////////////////////////////////////////////////////////////////////////// // AutocompletePopupContentsView, public: @@ -501,10 +558,10 @@ AutocompletePopupContentsView::AutocompletePopupContentsView( AutocompleteEditView* edit_view, AutocompleteEditModel* edit_model, Profile* profile, - const views::View* location_bar) + const BubblePositioner* bubble_positioner) : model_(new AutocompletePopupModel(this, edit_model, profile)), edit_view_(edit_view), - location_bar_(location_bar), + bubble_positioner_(bubble_positioner), result_font_(font.DeriveFont(kEditFontAdjust)), ignore_mouse_drag_(false), ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { @@ -580,13 +637,10 @@ void AutocompletePopupContentsView::UpdatePopupAppearance() { } // Calculate desired bounds. - gfx::Rect location_bar_bounds(location_bar_->bounds()); - gfx::Point location; - views::View::ConvertPointToScreen(location_bar_, &location); - location_bar_bounds.set_origin(location); - location_bar_bounds.set_height(location_bar_bounds.height() - 1); - gfx::Rect new_target_bounds(bubble_border_->GetBounds(location_bar_bounds, - gfx::Size(location_bar_bounds.width(), total_child_height))); + gfx::Rect location_stack_bounds = + bubble_positioner_->GetLocationStackBounds(); + gfx::Rect new_target_bounds(bubble_border_->GetBounds(location_stack_bounds, + gfx::Size(location_stack_bounds.width(), total_child_height))); // If we're animating and our target height changes, reset the animation. // NOTE: If we just reset blindly on _every_ update, then when the user types @@ -793,19 +847,7 @@ void AutocompletePopupContentsView::MakeContentsPath( SkIntToScalar(bounding_rect.bottom())); SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); - SkScalar scaled_radius = - SkScalarMul(radius, (SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3); - path->moveTo(rect.fRight, rect.fTop); - path->lineTo(rect.fRight, rect.fBottom - radius); - path->cubicTo(rect.fRight, rect.fBottom - radius + scaled_radius, - rect.fRight - radius + scaled_radius, rect.fBottom, - rect.fRight - radius, rect.fBottom); - path->lineTo(rect.fLeft + radius, rect.fBottom); - path->cubicTo(rect.fLeft + radius - scaled_radius, rect.fBottom, - rect.fLeft, rect.fBottom - radius + scaled_radius, - rect.fLeft, rect.fBottom - radius); - path->lineTo(rect.fLeft, rect.fTop); - path->close(); + path->addRoundRect(rect, radius, radius); } void AutocompletePopupContentsView::UpdateBlurRegion() { @@ -878,3 +920,14 @@ size_t AutocompletePopupContentsView::GetIndexForPoint( } return AutocompletePopupModel::kNoMatch; } + +// static +AutocompletePopupView* AutocompletePopupView::CreatePopupView( + const gfx::Font& font, + AutocompleteEditView* edit_view, + AutocompleteEditModel* edit_model, + Profile* profile, + const BubblePositioner* bubble_positioner) { + return new AutocompletePopupContentsView(font, edit_view, edit_model, + profile, bubble_positioner); +} diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h index d814206..30a9bf1 100644 --- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h +++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h @@ -45,7 +45,7 @@ class AutocompletePopupContentsView : public views::View, AutocompleteEditView* edit_view, AutocompleteEditModel* edit_model, Profile* profile, - const views::View* location_bar); + const BubblePositioner* bubble_positioner); virtual ~AutocompletePopupContentsView(); // Returns the bounds the popup should be shown at. This is the display bounds @@ -125,8 +125,8 @@ class AutocompletePopupContentsView : public views::View, // The edit view that invokes us. AutocompleteEditView* edit_view_; - // An object that the popup positions itself against. - const views::View* location_bar_; + // An object that tells the popup how to position itself. + const BubblePositioner* bubble_positioner_; // Our border, which can compute our desired bounds. const BubbleBorder* bubble_border_; diff --git a/chrome/browser/views/bookmark_editor_view.cc b/chrome/browser/views/bookmark_editor_view.cc index bd61ab3..34f8e91 100644 --- a/chrome/browser/views/bookmark_editor_view.cc +++ b/chrome/browser/views/bookmark_editor_view.cc @@ -282,9 +282,10 @@ void BookmarkEditorView::Init() { std::wstring languages = profile_ ? profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::wstring(); - // The following URL is user-editable, so we don't strip anything from it. + // The following URL is user-editable. We specify omit_username_password= + // false and unescape=false to show the original URL except IDN. url_text = net::FormatUrl(details_.existing_node->GetURL(), languages, - net::kFormatUrlOmitNothing, UnescapeRule::NONE, NULL, NULL, NULL); + false, UnescapeRule::NONE, NULL, NULL, NULL); } url_tf_.SetText(url_text); url_tf_.SetController(this); diff --git a/chrome/browser/views/browser_views_accessibility_browsertest.cc b/chrome/browser/views/browser_views_accessibility_browsertest.cc index 6a5bcf1..ac20277 100644 --- a/chrome/browser/views/browser_views_accessibility_browsertest.cc +++ b/chrome/browser/views/browser_views_accessibility_browsertest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -218,8 +218,7 @@ IN_PROC_BROWSER_TEST_F(BrowserViewsAccessibilityTest, TestHomeButtonAccObj) { } // Retrieve accessibility object for Star button and verify accessibility info. -IN_PROC_BROWSER_TEST_F(BrowserViewsAccessibilityTest, - TestStarButtonAccObj) { +IN_PROC_BROWSER_TEST_F(BrowserViewsAccessibilityTest, TestStarButtonAccObj) { // Verify Star button MSAA name and role. TestViewAccessibilityObject( GetToolbarView()->GetViewByID(VIEW_ID_STAR_BUTTON), diff --git a/chrome/browser/views/bubble_border.cc b/chrome/browser/views/bubble_border.cc index 3548286..230a0f4 100644 --- a/chrome/browser/views/bubble_border.cc +++ b/chrome/browser/views/bubble_border.cc @@ -1,6 +1,6 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// 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/bubble_border.h" @@ -31,6 +31,10 @@ static const int kArrowInteriorHeight = 7; gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, const gfx::Size& contents_size) const { + // The spacing (in pixels) between |position_relative_to| and the bubble + // content. + const int kBubbleSpacing = 2; + // Desired size is size of contents enlarged by the size of the border images. gfx::Size border_size(contents_size); gfx::Insets insets; @@ -39,40 +43,33 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, insets.top() + insets.bottom()); // Screen position depends on the arrow location. - // The arrow should overlap the target by some amount since the bottom arrow - // has lots of shadow below it and the top arrow is given an equivalent amount - // of padding. - const int kArrowOverlap = 3; int x = position_relative_to.x() + (position_relative_to.width() / 2); - int arrow_offset = override_arrow_x_offset_ ? override_arrow_x_offset_ : - arrow_x_offset_; if (arrow_is_left()) - x -= arrow_offset; + x -= arrow_x_offset_; else if (arrow_location_ == NONE) x -= ((contents_size.width() / 2) + insets.left()); else - x += (arrow_offset - border_size.width() + 1); + x += (arrow_x_offset_ - border_size.width() + 1); int y = position_relative_to.y(); - if (arrow_is_bottom()) - y += (kArrowOverlap - border_size.height()); - else if (arrow_location_ == NONE) - y += position_relative_to.height(); - else - y += (position_relative_to.height() - kArrowOverlap); + if (arrow_is_top()) { + y += (position_relative_to.height() - + (top_arrow_->height() - kBubbleSpacing)); + } else if (arrow_location_ == NONE) { + y += (position_relative_to.height() - (top_->height() - kBubbleSpacing)); + } else { + y += ((bottom_arrow_->height() - kBubbleSpacing) - border_size.height()); + } return gfx::Rect(x, y, border_size.width(), border_size.height()); } void BubbleBorder::GetInsets(gfx::Insets* insets) const { - int top, bottom; - if (arrow_is_bottom()) { - top = top_->height(); - bottom = std::max(bottom_->height(), bottom_arrow_->height()); - } else { - top = (arrow_location_ == NONE) ? - 0 : std::max(top_->height(), top_arrow_->height()); - bottom = bottom_->height(); - } + int top = top_->height(); + int bottom = bottom_->height(); + if (arrow_is_top()) + top = std::max(top, top_arrow_->height()); + else if (arrow_location_ != NONE) + bottom = std::max(bottom, bottom_arrow_->height()); insets->Set(top, left_->width(), bottom, right_->width()); } @@ -105,7 +102,7 @@ void BubbleBorder::InitClass() { } void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { - // Convenience shorthand variables. + // Convenience shorthand variables int width = view.width(); int tl_width = top_left_->width(); int tl_height = top_left_->height(); @@ -135,33 +132,25 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { * border_bottom∙∙∙∙└────┴─┤ ▼ ├──────┤ ▼ ├─┴────┘ * view.height()∙∙∙∙∙∙∙∙∙∙∙└───┘ └───┘ * - * If |arrow_location_| == NONE, the entire top edge is ommitted, and - * |tl_bottom| == |tr_bottom| == 0. Otherwise, one of the four arrows will be - * drawn. + * (At most one of the arrows will be drawn) */ gfx::Insets insets; GetInsets(&insets); int top = insets.top(); + int border_top = top - t_height; + int tl_bottom = border_top + tl_height; + int tr_bottom = border_top + tr_height; int bottom = view.height() - insets.bottom(); int border_bottom = bottom + b_height; int bl_y = border_bottom - bl_height; int br_y = border_bottom - br_height; - int border_top, tl_bottom, tr_bottom; - if (arrow_location_ == NONE) { - border_top = tl_bottom = tr_bottom = 0; - } else { - border_top = top - t_height; - tl_bottom = border_top + tl_height; - tr_bottom = border_top + tr_height; - - // Top left corner - canvas->DrawBitmapInt(*top_left_, 0, border_top); + // Top left corner + canvas->DrawBitmapInt(*top_left_, 0, border_top); - // Top right corner - canvas->DrawBitmapInt(*top_right_, width - tr_width, border_top); - } + // Top right corner + canvas->DrawBitmapInt(*top_right_, width - tr_width, border_top); // Right edge canvas->TileImageInt(*right_, width - r_width, tr_bottom, r_width, @@ -178,7 +167,7 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { canvas->TileImageInt(*left_, 0, tl_bottom, left_->width(), bl_y - tl_bottom); // Arrow edge, if necessary - bool should_draw_top_edge = false; + bool should_draw_top_edge = true; bool should_draw_bottom_edge = true; if (arrow_location_ != NONE) { /* Here's what the variables below mean (without loss of generality): @@ -205,17 +194,8 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { SkBitmap* arrow; int left_of_edge, right_of_edge, edge_y, arrow_y; SkScalar border_y, tip_y; - if (arrow_is_bottom()) { - should_draw_top_edge = true; - should_draw_bottom_edge = false; - edge = bottom_; - arrow = bottom_arrow_; - left_of_edge = bl_width; - right_of_edge = br_width; - edge_y = arrow_y = bottom; - border_y = SkIntToScalar(bottom); - tip_y = SkIntToScalar(bottom + kArrowInteriorHeight); - } else { + if (arrow_is_top()) { + should_draw_top_edge = false; edge = top_; arrow = top_arrow_; left_of_edge = tl_width; @@ -224,12 +204,19 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { arrow_y = top - top_arrow_->height(); border_y = SkIntToScalar(top); tip_y = SkIntToScalar(top - kArrowInteriorHeight); + } else { + should_draw_bottom_edge = false; + edge = bottom_; + arrow = bottom_arrow_; + left_of_edge = bl_width; + right_of_edge = br_width; + edge_y = arrow_y = bottom; + border_y = SkIntToScalar(bottom); + tip_y = SkIntToScalar(bottom + kArrowInteriorHeight); } - int arrow_offset = override_arrow_x_offset_ ? override_arrow_x_offset_ : - arrow_x_offset_; - int arrow_width = arrow->width(); + int arrow_width = (arrow_is_top() ? top_arrow_ : bottom_arrow_)->width(); int arrow_center = arrow_is_left() ? - arrow_offset : width - arrow_offset - 1; + arrow_x_offset_ : width - arrow_x_offset_ - 1; int arrow_x = arrow_center - (arrow_width / 2); SkScalar arrow_interior_x = SkIntToScalar(arrow_center - kArrowInteriorHeight); @@ -284,8 +271,6 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { // The border of this view creates an anti-aliased round-rect region for the // contents, which we need to fill with the background color. - // NOTE: This doesn't handle an arrow location of "NONE", which has square top - // corners. SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kFill_Style); diff --git a/chrome/browser/views/bubble_border.h b/chrome/browser/views/bubble_border.h index 3670503..3b48048 100644 --- a/chrome/browser/views/bubble_border.h +++ b/chrome/browser/views/bubble_border.h @@ -1,6 +1,6 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// 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. #ifndef CHROME_BROWSER_VIEWS_BUBBLE_BORDER_H_ #define CHROME_BROWSER_VIEWS_BUBBLE_BORDER_H_ @@ -11,11 +11,8 @@ class SkBitmap; -// Renders a border, with optional arrow (off by default), and a custom -// dropshadow. This can be used to produce floating "bubble" objects. -// -// If the arrow is on, the bubble has four round corner. If not, it has round -// corners on the bottom and square corners on the top, and lacks a top border. +// Renders a round-rect border, with optional arrow (off by default), and a +// custom dropshadow. This can be used to produce floating "bubble" objects. class BubbleBorder : public views::Border { public: // Possible locations for the (optional) arrow. @@ -27,9 +24,7 @@ class BubbleBorder : public views::Border { BOTTOM_RIGHT }; - BubbleBorder() : override_arrow_x_offset_(0), - arrow_location_(NONE), - background_color_(SK_ColorWHITE) { + BubbleBorder() : arrow_location_(NONE), background_color_(SK_ColorWHITE) { InitClass(); } @@ -47,12 +42,6 @@ class BubbleBorder : public views::Border { arrow_location_ = arrow_location; } - // Sets a fixed x offset for the arrow. The arrow will still point to the - // same location but the bubble will shift horizontally to make that happen. - void set_arrow_offset(int offset) { - override_arrow_x_offset_ = offset; - } - // Sets the background color for the arrow body. This is irrelevant if you do // not also set the arrow location to something other than NONE. void set_background_color(SkColor background_color) { @@ -79,10 +68,9 @@ class BubbleBorder : public views::Border { virtual ~BubbleBorder() { } - // Returns true if there is an arrow and it is positioned on the bottom edge. - bool arrow_is_bottom() const { - return (arrow_location_ == BOTTOM_LEFT) || - (arrow_location_ == BOTTOM_RIGHT); + // Returns true if there is an arrow and it is positioned on the top edge. + bool arrow_is_top() const { + return (arrow_location_ == TOP_LEFT) || (arrow_location_ == TOP_RIGHT); } // Returns true if there is an arrow and it is positioned on the left side. @@ -107,9 +95,6 @@ class BubbleBorder : public views::Border { static int arrow_x_offset_; - // If specified, overrides the pre-calculated |arrow_x_offset_| of the arrow. - int override_arrow_x_offset_; - ArrowLocation arrow_location_; SkColor background_color_; diff --git a/chrome/browser/views/constrained_window_win.cc b/chrome/browser/views/constrained_window_win.cc index c70ec75..488f1a4 100644 --- a/chrome/browser/views/constrained_window_win.cc +++ b/chrome/browser/views/constrained_window_win.cc @@ -34,7 +34,6 @@ #include "views/window/client_view.h" #include "views/window/non_client_view.h" #include "views/window/window_resources.h" -#include "views/window/window_shape.h" using base::TimeDelta; @@ -350,7 +349,24 @@ int ConstrainedWindowFrameView::NonClientHitTest(const gfx::Point& point) { void ConstrainedWindowFrameView::GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) { DCHECK(window_mask); - views::GetDefaultWindowMask(size, window_mask); + + // Redefine the window visible region for the new size. + window_mask->moveTo(0, 3); + window_mask->lineTo(1, 2); + window_mask->lineTo(1, 1); + window_mask->lineTo(2, 1); + window_mask->lineTo(3, 0); + + window_mask->lineTo(SkIntToScalar(size.width() - 3), 0); + window_mask->lineTo(SkIntToScalar(size.width() - 2), 1); + window_mask->lineTo(SkIntToScalar(size.width() - 1), 1); + window_mask->lineTo(SkIntToScalar(size.width() - 1), 2); + window_mask->lineTo(SkIntToScalar(size.width()), 3); + + window_mask->lineTo(SkIntToScalar(size.width()), + SkIntToScalar(size.height())); + window_mask->lineTo(0, SkIntToScalar(size.height())); + window_mask->close(); } void ConstrainedWindowFrameView::EnableClose(bool enable) { diff --git a/chrome/browser/views/frame/browser_frame_win.cc b/chrome/browser/views/frame/browser_frame_win.cc index 0092fa7..d12963f 100644 --- a/chrome/browser/views/frame/browser_frame_win.cc +++ b/chrome/browser/views/frame/browser_frame_win.cc @@ -28,9 +28,6 @@ // static static const int kClientEdgeThickness = 3; static const int kTabDragWindowAlpha = 200; -// We need to offset the DWMFrame into the toolbar so that the blackness -// doesn't show up on our rounded corners. -static const int kDWMFrameTopOffset = 3; // static (Factory method.) BrowserFrame* BrowserFrame::Create(BrowserView* browser_view, @@ -306,8 +303,7 @@ void BrowserFrameWin::UpdateDWMFrame() { margins.cyTopHeight += GetSystemMetrics(SM_CYSIZEFRAME); } else { margins.cyTopHeight = - GetBoundsForTabStrip(browser_view_->tabstrip()).bottom() + - kDWMFrameTopOffset; + GetBoundsForTabStrip(browser_view_->tabstrip()).bottom(); } } } else { diff --git a/chrome/browser/views/frame/browser_root_view.cc b/chrome/browser/views/frame/browser_root_view.cc index d2985dd..d789b94 100644 --- a/chrome/browser/views/frame/browser_root_view.cc +++ b/chrome/browser/views/frame/browser_root_view.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -7,10 +7,9 @@ #include "app/drag_drop_types.h" #include "app/l10n_util.h" #include "app/os_exchange_data.h" -#include "chrome/browser/autocomplete/autocomplete.h" -#include "chrome/browser/autocomplete/autocomplete_classifier.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/profile.h" +#include "chrome/browser/search_versus_navigate_classifier.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/frame/browser_frame.h" #include "chrome/browser/views/tabs/tab_strip.h" @@ -142,13 +141,13 @@ bool BrowserRootView::GetPasteAndGoURL(const OSExchangeData& data, GURL* url) { if (!data.GetString(&text) || text.empty()) return false; - AutocompleteMatch match; - browser_view_->browser()->profile()->GetAutocompleteClassifier()->Classify( - text, std::wstring(), &match, NULL); - if (!match.destination_url.is_valid()) + GURL destination_url; + browser_view_->browser()->profile()->GetSearchVersusNavigateClassifier()-> + Classify(text, std::wstring(), NULL, &destination_url, NULL, NULL, NULL); + if (!destination_url.is_valid()) return false; if (url) - *url = match.destination_url; + *url = destination_url; return true; } diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index f96964a..cc77bc6 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -8,13 +8,20 @@ #include <gtk/gtk.h> #endif +#include "app/drag_drop_types.h" #include "app/l10n_util.h" +#include "app/os_exchange_data.h" #include "app/resource_bundle.h" +#include "base/command_line.h" #include "base/i18n/rtl.h" +#include "base/keyboard_codes.h" +#include "base/time.h" +#include "build/build_config.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/app_modal_dialog_queue.h" #include "chrome/browser/automation/ui_controls.h" #include "chrome/browser/bookmarks/bookmark_utils.h" +#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_theme_provider.h" @@ -23,30 +30,40 @@ #include "chrome/browser/ntp_background_util.h" #include "chrome/browser/page_info_window.h" #include "chrome/browser/pref_service.h" -#include "chrome/browser/sessions/tab_restore_service.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/profile.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/accessible_view_helper.h" #include "chrome/browser/views/bookmark_bar_view.h" +#include "chrome/browser/views/browser_bubble.h" #include "chrome/browser/views/browser_dialogs.h" +#include "chrome/browser/views/chrome_views_delegate.h" #include "chrome/browser/views/download_shelf_view.h" #include "chrome/browser/views/extensions/extension_shelf.h" -#include "chrome/browser/views/frame/browser_extender.h" #include "chrome/browser/views/frame/browser_view_layout.h" +#include "chrome/browser/views/frame/browser_extender.h" +#include "chrome/browser/views/frame/browser_frame.h" #include "chrome/browser/views/fullscreen_exit_bubble.h" +#include "chrome/browser/views/infobars/infobar_container.h" #include "chrome/browser/views/status_bubble_views.h" #include "chrome/browser/views/tab_contents/tab_contents_container.h" #include "chrome/browser/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/views/tabs/side_tab_strip.h" +#include "chrome/browser/views/tabs/tab_strip.h" #include "chrome/browser/views/theme_install_bubble_view.h" +#include "chrome/browser/views/toolbar_star_toggle.h" #include "chrome/browser/views/toolbar_view.h" +#include "chrome/browser/sessions/tab_restore_service.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/native_window_notification_source.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "gfx/canvas.h" +#include "gfx/scrollbar_size.h" #include "grit/app_resources.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -54,11 +71,14 @@ #include "grit/theme_resources.h" #include "grit/webkit_resources.h" #include "views/controls/single_split_view.h" +#include "views/fill_layout.h" #include "views/focus/external_focus_tracker.h" #include "views/focus/view_storage.h" #include "views/grid_layout.h" +#include "views/view.h" #include "views/widget/root_view.h" #include "views/window/dialog_delegate.h" +#include "views/window/non_client_view.h" #include "views/window/window.h" #if defined(OS_WIN) @@ -769,7 +789,7 @@ void BrowserView::UpdateLoadingAnimations(bool should_animate) { } void BrowserView::SetStarredState(bool is_starred) { - toolbar_->location_bar()->SetStarToggled(is_starred); + toolbar_->star_button()->SetToggled(is_starred); } gfx::Rect BrowserView::GetRestoredBounds() const { @@ -949,7 +969,7 @@ void BrowserView::ShowBookmarkManager() { } void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) { - toolbar_->location_bar()->ShowStarBubble(url, !already_bookmarked); + toolbar_->star_button()->ShowStarBubble(url, !already_bookmarked); } void BrowserView::SetDownloadShelfVisible(bool visible) { diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc index 9a665f7..608fea9 100644 --- a/chrome/browser/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/views/frame/glass_browser_frame_view.cc @@ -40,8 +40,6 @@ const int kOTRBottomSpacing = 2; // There are 2 px on each side of the OTR avatar (between the frame border and // it on the left, and between it and the tabstrip on the right). const int kOTRSideSpacing = 2; -// The content left/right images have a shadow built into them. -const int kContentEdgeShadowThickness = 2; // The top 1 px of the tabstrip is shadow; in maximized mode we push this off // the top of the screen so the tabs appear flush against the screen edge. const int kTabstripTopShadowThickness = 1; @@ -263,46 +261,19 @@ void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) { toolbar_bounds.x() - 1, toolbar_bounds.y() + 2, toolbar_bounds.width() + 2, theme_toolbar->height()); - // Draw rounded corners for the tab. - SkBitmap* toolbar_left_mask = - tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER_MASK); - SkBitmap* toolbar_right_mask = - tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER_MASK); - - // We mask out the corners by using the DestinationIn transfer mode, - // which keeps the RGB pixels from the destination and the alpha from - // the source. - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kDstIn_Mode); - - // Mask out the top left corner. - int left_x = toolbar_bounds.x() - kContentEdgeShadowThickness - - kClientEdgeThickness; - canvas->DrawBitmapInt(*toolbar_left_mask, - left_x, toolbar_bounds.y(), paint); - - // Mask out the top right corner. - int right_x = toolbar_bounds.right() - toolbar_right_mask->width() + - kContentEdgeShadowThickness + kClientEdgeThickness; - canvas->DrawBitmapInt(*toolbar_right_mask, - right_x, toolbar_bounds.y(), - paint); - - // Draw left edge. - SkBitmap* toolbar_left = tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER); - canvas->DrawBitmapInt(*toolbar_left, left_x, toolbar_bounds.y()); - - // Draw center edge. + SkBitmap* toolbar_left = + tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER); + canvas->DrawBitmapInt(*toolbar_left, + toolbar_bounds.x() - toolbar_left->width(), + toolbar_bounds.y()); + SkBitmap* toolbar_center = tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER); - canvas->TileImageInt(*toolbar_center, left_x + toolbar_left->width(), - toolbar_bounds.y(), - right_x - (left_x + toolbar_left->width()), - toolbar_center->height()); + canvas->TileImageInt(*toolbar_center, toolbar_bounds.x(), toolbar_bounds.y(), + toolbar_bounds.width(), toolbar_center->height()); - // Right edge. canvas->DrawBitmapInt(*tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER), - right_x, toolbar_bounds.y()); + toolbar_bounds.right(), toolbar_bounds.y()); // Draw the content/toolbar separator. canvas->DrawLineInt(ResourceBundle::toolbar_separator_color, diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc index c91cb51..e9276f8 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc @@ -26,7 +26,6 @@ #include "views/widget/root_view.h" #include "views/window/window.h" #include "views/window/window_resources.h" -#include "views/window/window_shape.h" #if defined(OS_WIN) #include "app/win_util.h" @@ -59,8 +58,6 @@ const int kResizeAreaCornerSize = 16; // The titlebar never shrinks too short to show the caption button plus some // padding below it. const int kCaptionButtonHeightWithPadding = 19; -// The content left/right images have a shadow built into them. -const int kContentEdgeShadowThickness = 2; // The titlebar has a 2 px 3D edge along the top and bottom. const int kTitlebarTopAndBottomEdgeThickness = 2; // The icon is inset 2 px from the left frame border. @@ -92,9 +89,6 @@ const int kNewTabCaptionRestoredSpacing = 5; // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid // looking too cluttered. const int kNewTabCaptionMaximizedSpacing = 16; -// How far to indent the tabstrip from the left side of the screen when there -// is no OTR icon. -const int kTabStripIndent = 1; } /////////////////////////////////////////////////////////////////////////////// @@ -194,7 +188,7 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( BaseTabStrip* tabstrip) const { int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? (otr_avatar_icon_->bounds().right() + kOTRSideSpacing) : - NonClientBorderThickness() + kTabStripIndent; + NonClientBorderThickness(); int tabstrip_width = minimize_button_->x() - tabstrip_x - (frame_->GetWindow()->IsMaximized() ? kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing); @@ -304,7 +298,23 @@ void OpaqueBrowserFrameView::GetWindowMask(const gfx::Size& size, if (frame_->GetWindow()->IsMaximized() || frame_->GetWindow()->IsFullscreen()) return; - views::GetDefaultWindowMask(size, window_mask); + // Redefine the window visible region for the new size. + window_mask->moveTo(0, 3); + window_mask->lineTo(1, 2); + window_mask->lineTo(1, 1); + window_mask->lineTo(2, 1); + window_mask->lineTo(3, 0); + + window_mask->lineTo(SkIntToScalar(size.width() - 3), 0); + window_mask->lineTo(SkIntToScalar(size.width() - 2), 1); + window_mask->lineTo(SkIntToScalar(size.width() - 1), 1); + window_mask->lineTo(SkIntToScalar(size.width() - 1), 2); + window_mask->lineTo(SkIntToScalar(size.width()), 3); + + window_mask->lineTo(SkIntToScalar(size.width()), + SkIntToScalar(size.height())); + window_mask->lineTo(0, SkIntToScalar(size.height())); + window_mask->close(); } void OpaqueBrowserFrameView::EnableClose(bool enable) { @@ -707,17 +717,6 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) { int bottom_edge_height = std::min(toolbar_left->height(), toolbar_bounds.height()) - split_point; - // Split our canvas out so we can mask out the corners of the toolbar - // without masking out the frame. - SkRect bounds; - bounds.set(SkIntToScalar(toolbar_bounds.x() - kClientEdgeThickness), - SkIntToScalar(toolbar_bounds.y()), - SkIntToScalar(toolbar_bounds.x() + toolbar_bounds.width() + - kClientEdgeThickness * 2), - SkIntToScalar(toolbar_bounds.y() + toolbar_bounds.height())); - canvas->saveLayerAlpha(&bounds, 255); - canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); - SkColor theme_toolbar_color = tp->GetColor(BrowserThemeProvider::COLOR_TOOLBAR); canvas->FillRectInt(theme_toolbar_color, toolbar_bounds.x(), bottom_y, @@ -733,65 +732,26 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) { toolbar_bounds.width() + (2 * kClientEdgeThickness), theme_toolbar->height()); - // Draw rounded corners for the tab. - SkBitmap* toolbar_left_mask = - tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER_MASK); - SkBitmap* toolbar_right_mask = - tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER_MASK); - - // We mask out the corners by using the DestinationIn transfer mode, - // which keeps the RGB pixels from the destination and the alpha from - // the source. - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kDstIn_Mode); - - // Make the left edge. - int left_x = toolbar_bounds.x() - kClientEdgeThickness - - kContentEdgeShadowThickness; - canvas->DrawBitmapInt(*toolbar_left_mask, 0, 0, - toolbar_left_mask->width(), split_point, - left_x, toolbar_bounds.y(), - toolbar_left_mask->width(), split_point, false, paint); - canvas->DrawBitmapInt(*toolbar_left_mask, 0, - toolbar_left_mask->height() - bottom_edge_height, - toolbar_left_mask->width(), bottom_edge_height, - left_x, bottom_y, - toolbar_left_mask->width(), bottom_edge_height, false, paint); - - // Mask the right edge. - int right_x = toolbar_bounds.right() - - toolbar_right_mask->width() + kClientEdgeThickness + - kContentEdgeShadowThickness; - canvas->DrawBitmapInt(*toolbar_right_mask, 0, 0, - toolbar_right_mask->width(), split_point, right_x, toolbar_bounds.y(), - toolbar_right_mask->width(), split_point, false, paint); - canvas->DrawBitmapInt(*toolbar_right_mask, 0, - toolbar_right_mask->height() - bottom_edge_height, - toolbar_right_mask->width(), bottom_edge_height, right_x, bottom_y, - toolbar_right_mask->width(), bottom_edge_height, false, paint); - canvas->restore(); - canvas->DrawBitmapInt(*toolbar_left, 0, 0, toolbar_left->width(), split_point, - left_x, toolbar_bounds.y(), + toolbar_bounds.x() - toolbar_left->width(), toolbar_bounds.y(), toolbar_left->width(), split_point, false); canvas->DrawBitmapInt(*toolbar_left, 0, toolbar_left->height() - bottom_edge_height, toolbar_left->width(), - bottom_edge_height, left_x, bottom_y, + bottom_edge_height, toolbar_bounds.x() - toolbar_left->width(), bottom_y, toolbar_left->width(), bottom_edge_height, false); SkBitmap* toolbar_center = tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER); - canvas->TileImageInt(*toolbar_center, 0, 0, left_x + toolbar_left->width(), - toolbar_bounds.y(), right_x - (left_x + toolbar_left->width()), - split_point); + canvas->TileImageInt(*toolbar_center, 0, 0, toolbar_bounds.x(), + toolbar_bounds.y(), toolbar_bounds.width(), split_point); SkBitmap* toolbar_right = tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER); canvas->DrawBitmapInt(*toolbar_right, 0, 0, toolbar_right->width(), - split_point, right_x, toolbar_bounds.y(), + split_point, toolbar_bounds.right(), toolbar_bounds.y(), toolbar_right->width(), split_point, false); canvas->DrawBitmapInt(*toolbar_right, 0, toolbar_right->height() - bottom_edge_height, toolbar_right->width(), - bottom_edge_height, right_x, bottom_y, + bottom_edge_height, toolbar_bounds.right(), bottom_y, toolbar_right->width(), bottom_edge_height, false); // Draw the content/toolbar separator. diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc index 8150db9..e5c4858 100644 --- a/chrome/browser/views/info_bubble.cc +++ b/chrome/browser/views/info_bubble.cc @@ -29,17 +29,55 @@ const SkColor InfoBubble::kBackgroundColor = const SkColor InfoBubble::kBackgroundColor = SK_ColorWHITE; #endif +// BorderContents ------------------------------------------------------------- + +// This is used to paint the border of the InfoBubble. Windows uses this via +// BorderWidget (see below), while others can use it directly in the bubble. +class BorderContents : public views::View { + public: + BorderContents() { } + + // Given the size of the contents and the rect to point at, initializes the + // bubble and returns the bounds of both the border + // and the contents inside the bubble. + // |prefer_arrow_on_right| specifies the preferred location for the arrow + // anchor. If the bubble does not fit on the monitor, the arrow location may + // changed so it can. + // + // TODO(pkasting): Maybe this should use mirroring transformations instead, + // which would hopefully simplify this code. + void InitAndGetBounds( + const gfx::Rect& position_relative_to, // In screen coordinates + const gfx::Size& contents_size, + bool prefer_arrow_on_right, + gfx::Rect* contents_bounds, // Returned in window coordinates + gfx::Rect* window_bounds); // Returned in screen coordinates + + private: + virtual ~BorderContents() { } + + // Overridden from View: + virtual void Paint(gfx::Canvas* canvas); + + DISALLOW_COPY_AND_ASSIGN(BorderContents); +}; + void BorderContents::InitAndGetBounds( const gfx::Rect& position_relative_to, const gfx::Size& contents_size, bool prefer_arrow_on_right, gfx::Rect* contents_bounds, gfx::Rect* window_bounds) { + // Margins between the contents and the inside of the border, in pixels. + const int kLeftMargin = 6; + const int kTopMargin = 6; + const int kRightMargin = 6; + const int kBottomMargin = 9; + // Set the border. - if (!bubble_border_) - bubble_border_ = new BubbleBorder; - set_border(bubble_border_); - bubble_border_->set_background_color(InfoBubble::kBackgroundColor); + BubbleBorder* bubble_border = new BubbleBorder; + set_border(bubble_border); + bubble_border->set_background_color(InfoBubble::kBackgroundColor); // Give the contents a margin. gfx::Size local_contents_size(contents_size); @@ -50,9 +88,9 @@ void BorderContents::InitAndGetBounds( // bounds. BubbleBorder::ArrowLocation arrow_location(prefer_arrow_on_right ? BubbleBorder::TOP_RIGHT : BubbleBorder::TOP_LEFT); - bubble_border_->set_arrow_location(arrow_location); + bubble_border->set_arrow_location(arrow_location); *window_bounds = - bubble_border_->GetBounds(position_relative_to, local_contents_size); + bubble_border->GetBounds(position_relative_to, local_contents_size); // See if those bounds will fit on the monitor. scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider( @@ -71,10 +109,10 @@ void BorderContents::InitAndGetBounds( arrow_location = arrow_on_left ? BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT; } - bubble_border_->set_arrow_location(arrow_location); + bubble_border->set_arrow_location(arrow_location); // Now get the recalculated bounds. - *window_bounds = bubble_border_->GetBounds(position_relative_to, + *window_bounds = bubble_border->GetBounds(position_relative_to, local_contents_size); } @@ -82,7 +120,7 @@ void BorderContents::InitAndGetBounds( // subtracting the border dimensions and margin amounts. *contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size()); gfx::Insets insets; - bubble_border_->GetInsets(&insets); + bubble_border->GetInsets(&insets); contents_bounds->Inset(insets.left() + kLeftMargin, insets.top() + kTopMargin, insets.right() + kRightMargin, insets.bottom() + kBottomMargin); } @@ -90,8 +128,6 @@ void BorderContents::InitAndGetBounds( void BorderContents::Paint(gfx::Canvas* canvas) { // The border of this view creates an anti-aliased round-rect region for the // contents, which we need to fill with the background color. - // NOTE: This doesn't handle an arrow location of "NONE", which has square top - // corners. SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kFill_Style); @@ -114,7 +150,7 @@ void BorderContents::Paint(gfx::Canvas* canvas) { #if defined(OS_WIN) // BorderWidget --------------------------------------------------------------- -BorderWidget::BorderWidget() : border_contents_(NULL) { +BorderWidget::BorderWidget() { set_delete_on_destroy(false); // Our owner will free us manually. set_window_style(WS_POPUP); set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED); @@ -127,16 +163,15 @@ gfx::Rect BorderWidget::InitAndGetBounds( bool prefer_arrow_on_right) { // Set up the border view and ask it to calculate our bounds (and our // contents'). - if (!border_contents_) - border_contents_ = new BorderContents; + BorderContents* border_contents = new BorderContents; gfx::Rect contents_bounds, window_bounds; - border_contents_->InitAndGetBounds(position_relative_to, contents_size, - prefer_arrow_on_right, &contents_bounds, - &window_bounds); + border_contents->InitAndGetBounds(position_relative_to, contents_size, + prefer_arrow_on_right, &contents_bounds, + &window_bounds); // Initialize ourselves. WidgetWin::Init(GetAncestor(owner, GA_ROOT), window_bounds); - SetContentsView(border_contents_); + SetContentsView(border_contents); SetWindowPos(owner, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW); @@ -233,8 +268,7 @@ void InfoBubble::Init(views::Window* parent, (contents->UILayoutIsRightToLeft() == delegate->PreferOriginSideAnchor()); #if defined(OS_WIN) - if (!border_.get()) - border_.reset(new BorderWidget); + border_.reset(new BorderWidget); // Initialize and position the border window. window_bounds = border_->InitAndGetBounds(GetNativeView(), position_relative_to, contents->GetPreferredSize(), diff --git a/chrome/browser/views/info_bubble.h b/chrome/browser/views/info_bubble.h index ea80b0f..90911b5 100644 --- a/chrome/browser/views/info_bubble.h +++ b/chrome/browser/views/info_bubble.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -7,7 +7,6 @@ #include "third_party/skia/include/core/SkColor.h" #include "views/accelerator.h" -#include "views/view.h" #if defined(OS_WIN) #include "views/widget/widget_win.h" #elif defined(OS_LINUX) @@ -24,7 +23,6 @@ // have any additional margins. class BorderWidget; -class BubbleBorder; class InfoBubble; namespace views { @@ -35,46 +33,6 @@ namespace gfx { class Path; } -// This is used to paint the border of the InfoBubble. Windows uses this via -// BorderWidget (see below), while others can use it directly in the bubble. -class BorderContents : public views::View { - public: - BorderContents() : bubble_border_(NULL) { } - - // Given the size of the contents and the rect to point at, initializes the - // bubble and returns the bounds of both the border - // and the contents inside the bubble. - // |prefer_arrow_on_right| specifies the preferred location for the arrow - // anchor. If the bubble does not fit on the monitor, the arrow location may - // changed so it can. - // - // TODO(pkasting): Maybe this should use mirroring transformations instead, - // which would hopefully simplify this code. - virtual void InitAndGetBounds( - const gfx::Rect& position_relative_to, // In screen coordinates - const gfx::Size& contents_size, - bool prefer_arrow_on_right, - gfx::Rect* contents_bounds, // Returned in window coordinates - gfx::Rect* window_bounds); // Returned in screen coordinates - - protected: - virtual ~BorderContents() { } - - // Margins between the contents and the inside of the border, in pixels. - static const int kLeftMargin = 6; - static const int kTopMargin = 6; - static const int kRightMargin = 6; - static const int kBottomMargin = 9; - - BubbleBorder* bubble_border_; - - private: - // Overridden from View: - virtual void Paint(gfx::Canvas* canvas); - - DISALLOW_COPY_AND_ASSIGN(BorderContents); -}; - #if defined(OS_WIN) // This is a window that surrounds the info bubble and paints the margin and // border. It is a separate window so that it can be a layered window, so that @@ -89,15 +47,12 @@ class BorderWidget : public views::WidgetWin { // Given the owning (parent) window, the size of the contained contents // (without margins), and the rect (in screen coordinates) to point to, // initializes the window and returns the bounds (in screen coordinates) the - // contents should use. |is_rtl| is supplied to + // contents should use. |is_rtl| is supplied to // BorderContents::InitAndGetBounds(), see its declaration for details. - virtual gfx::Rect InitAndGetBounds(HWND owner, - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size, - bool is_rtl); - - protected: - BorderContents* border_contents_; + gfx::Rect InitAndGetBounds(HWND owner, + const gfx::Rect& position_relative_to, + const gfx::Size& contents_size, + bool is_rtl); private: // Overridden from WidgetWin: @@ -127,7 +82,7 @@ class InfoBubbleDelegate { virtual bool PreferOriginSideAnchor() { return true; } }; -// TODO(sky): this code is ifdef-tastic. It might be cleaner to refactor the +// TODO: this code is ifdef-tastic. It might be cleaner to refactor the // WidgetFoo subclass into a separate class that calls into InfoBubble. // That way InfoBubble has no (or very few) ifdefs. class InfoBubble @@ -165,10 +120,10 @@ class InfoBubble virtual ~InfoBubble() {} // Creates the InfoBubble. - virtual void Init(views::Window* parent, - const gfx::Rect& position_relative_to, - views::View* contents, - InfoBubbleDelegate* delegate); + void Init(views::Window* parent, + const gfx::Rect& position_relative_to, + views::View* contents, + InfoBubbleDelegate* delegate); #if defined(OS_WIN) // Overridden from WidgetWin: @@ -178,11 +133,6 @@ class InfoBubble virtual void IsActiveChanged(); #endif -#if defined(OS_WIN) - // The window used to render the padding, border and arrow. - scoped_ptr<BorderWidget> border_; -#endif - private: // Closes the window notifying the delegate. |closed_by_escape| is true if // the close is the result of pressing escape. @@ -197,6 +147,11 @@ class InfoBubble // The window that this InfoBubble is parented to. views::Window* parent_; +#if defined(OS_WIN) + // The window used to render the padding, border and arrow. + scoped_ptr<BorderWidget> border_; +#endif + // Have we been closed? bool closed_; diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index a4e6da7..b9e36d5 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -8,7 +8,6 @@ #include <gtk/gtk.h> #endif -#include "app/drag_drop_types.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "app/theme_provider.h" @@ -17,6 +16,8 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/alternate_nav_url_fetcher.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/bubble_positioner.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/content_setting_bubble_model.h" #include "chrome/browser/content_setting_image_model.h" @@ -25,15 +26,17 @@ #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/view_ids.h" -#include "chrome/browser/views/browser_dialogs.h" -#include "chrome/browser/views/content_blocked_bubble_contents.h" +#include "chrome/browser/views/extensions/extension_popup.h" #include "chrome/browser/views/frame/browser_view.h" +#include "chrome/browser/views/content_blocked_bubble_contents.h" +#include "chrome/common/content_settings.h" #include "chrome/common/platform_util.h" +#include "chrome/common/pref_names.h" #include "gfx/canvas.h" #include "gfx/color_utils.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" -#include "views/drag_utils.h" +#include "net/base/net_util.h" #if defined(OS_WIN) #include "chrome/browser/views/first_run_bubble.h" @@ -44,31 +47,20 @@ using views::View; // static const int LocationBarView::kVertMargin = 2; -// Padding between items in the location bar. -static const int kViewPadding = 3; - -// Padding before the start of a bubble. -static const int kBubblePadding = kViewPadding - 1; - -// Padding between the location icon and the edit, if they're adjacent. -static const int kLocationIconEditPadding = kViewPadding - 1; +// Padding on the right and left of the entry field. +static const int kEntryPadding = 3; -static const int kEVBubbleBackgroundImages[] = { - IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_L, - IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_C, - IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_R, -}; - -static const int kSelectedKeywordBackgroundImages[] = { - IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_L, - IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_C, - IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_R, -}; +// Padding between the entry and the leading/trailing views. +static const int kInnerPadding = 3; static const SkBitmap* kBackground = NULL; static const SkBitmap* kPopupBackground = NULL; +// The delay the mouse has to be hovering over the lock/warning icon before the +// info bubble is shown. +static const int kInfoBubbleHoverDelayMs = 500; + // The tab key image. static const SkBitmap* kTabButtonBitmap = NULL; @@ -140,23 +132,21 @@ LocationBarView::LocationBarView(Profile* profile, CommandUpdater* command_updater, ToolbarModel* model, Delegate* delegate, - bool popup_window_mode) + bool popup_window_mode, + const BubblePositioner* bubble_positioner) : profile_(profile), command_updater_(command_updater), model_(model), delegate_(delegate), disposition_(CURRENT_TAB), - ALLOW_THIS_IN_INITIALIZER_LIST(location_icon_view_(this)), - ALLOW_THIS_IN_INITIALIZER_LIST(ev_bubble_view_( - kEVBubbleBackgroundImages, IDR_OMNIBOX_HTTPS_VALID, - GetColor(ToolbarModel::EV_SECURE, SECURITY_TEXT), this)), location_entry_view_(NULL), - selected_keyword_view_(kSelectedKeywordBackgroundImages, - IDR_OMNIBOX_SEARCH, SK_ColorBLACK, profile), + selected_keyword_view_(profile), keyword_hint_view_(profile), - star_view_(command_updater), + type_to_search_view_(l10n_util::GetString(IDS_OMNIBOX_EMPTY_TEXT)), + security_image_view_(this, profile, model, bubble_positioner), popup_window_mode_(popup_window_mode), - ALLOW_THIS_IN_INITIALIZER_LIST(first_run_bubble_(this)) { + first_run_bubble_(this), + bubble_positioner_(bubble_positioner) { DCHECK(profile_); SetID(VIEW_ID_LOCATION_BAR); SetFocusable(true); @@ -180,45 +170,52 @@ void LocationBarView::Init() { font_ = font_.DeriveFont(3); } - AddChildView(&location_icon_view_); - location_icon_view_.SetVisible(true); - location_icon_view_.SetDragController(this); - location_icon_view_.set_parent_owned(false); - - AddChildView(&ev_bubble_view_); - ev_bubble_view_.SetVisible(false); - ev_bubble_view_.SetDragController(this); - ev_bubble_view_.set_parent_owned(false); - // URL edit field. // View container for URL edit field. #if defined(OS_WIN) + views::Widget* widget = GetWidget(); location_entry_.reset(new AutocompleteEditViewWin(font_, this, model_, this, - GetWidget()->GetNativeView(), profile_, command_updater_, - popup_window_mode_, this)); + widget->GetNativeView(), + profile_, command_updater_, + popup_window_mode_, + bubble_positioner_)); #else location_entry_.reset(new AutocompleteEditViewGtk(this, model_, profile_, - command_updater_, popup_window_mode_, this)); + command_updater_, + popup_window_mode_, + bubble_positioner_)); location_entry_->Init(); // Make all the children of the widget visible. NOTE: this won't display // anything, it just toggles the visible flag. - gtk_widget_show_all(location_entry_->GetNativeView()); + gtk_widget_show_all(location_entry_->widget()); // Hide the widget. NativeViewHostGtk will make it visible again as // necessary. - gtk_widget_hide(location_entry_->GetNativeView()); + gtk_widget_hide(location_entry_->widget()); #endif location_entry_view_ = new views::NativeViewHost; location_entry_view_->SetID(VIEW_ID_AUTOCOMPLETE); AddChildView(location_entry_view_); location_entry_view_->set_focus_view(this); - location_entry_view_->Attach(location_entry_->GetNativeView()); + location_entry_view_->Attach( +#if defined(OS_WIN) + location_entry_->m_hWnd +#else + location_entry_->widget() +#endif + ); // NOLINT AddChildView(&selected_keyword_view_); selected_keyword_view_.SetFont(font_); selected_keyword_view_.SetVisible(false); selected_keyword_view_.set_parent_owned(false); - SkColor dimmed_text = GetColor(ToolbarModel::NONE, DEEMPHASIZED_TEXT); + SkColor dimmed_text = GetColor(false, DEEMPHASIZED_TEXT); + + AddChildView(&type_to_search_view_); + type_to_search_view_.SetVisible(false); + type_to_search_view_.SetFont(font_); + type_to_search_view_.SetColor(dimmed_text); + type_to_search_view_.set_parent_owned(false); AddChildView(&keyword_hint_view_); keyword_hint_view_.SetVisible(false); @@ -226,19 +223,22 @@ void LocationBarView::Init() { keyword_hint_view_.SetColor(dimmed_text); keyword_hint_view_.set_parent_owned(false); + AddChildView(&security_image_view_); + security_image_view_.SetVisible(false); + security_image_view_.set_parent_owned(false); + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { - ContentSettingImageView* content_blocked_view = new ContentSettingImageView( - static_cast<ContentSettingsType>(i), this, profile_); + ContentSettingImageView* content_blocked_view = + new ContentSettingImageView(static_cast<ContentSettingsType>(i), this, + profile_, bubble_positioner_); content_setting_views_.push_back(content_blocked_view); AddChildView(content_blocked_view); content_blocked_view->SetVisible(false); } - if (!popup_window_mode_) { - AddChildView(&star_view_); - star_view_.SetVisible(true); - star_view_.set_parent_owned(false); - } + AddChildView(&info_label_); + info_label_.SetVisible(false); + info_label_.set_parent_owned(false); // Notify us when any ancestor is resized. In this case we want to tell the // AutocompleteEditView to close its popup. @@ -256,59 +256,63 @@ bool LocationBarView::IsInitialized() const { } // static -SkColor LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level, - ColorKind kind) { - switch (kind) { +SkColor LocationBarView::GetColor(bool is_secure, ColorKind kind) { + enum SecurityState { + NOT_SECURE = 0, + SECURE, + NUM_STATES + }; + + static bool initialized = false; + static SkColor colors[NUM_STATES][NUM_KINDS]; + if (!initialized) { #if defined(OS_WIN) - case BACKGROUND: return color_utils::GetSysSkColor(COLOR_WINDOW); - case TEXT: return color_utils::GetSysSkColor(COLOR_WINDOWTEXT); - case SELECTED_TEXT: return color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT); + colors[NOT_SECURE][BACKGROUND] = color_utils::GetSysSkColor(COLOR_WINDOW); + colors[NOT_SECURE][TEXT] = color_utils::GetSysSkColor(COLOR_WINDOWTEXT); + colors[NOT_SECURE][SELECTED_TEXT] = + color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT); #else // TODO(beng): source from theme provider. - case BACKGROUND: return SK_ColorWHITE; - case TEXT: return SK_ColorBLACK; - case SELECTED_TEXT: return SK_ColorWHITE; + colors[NOT_SECURE][BACKGROUND] = SK_ColorWHITE; + colors[NOT_SECURE][TEXT] = SK_ColorBLACK; + colors[NOT_SECURE][SELECTED_TEXT] = SK_ColorWHITE; #endif - - case DEEMPHASIZED_TEXT: - return color_utils::AlphaBlend(GetColor(security_level, TEXT), - GetColor(security_level, BACKGROUND), 128); - - case SECURITY_TEXT: { - SkColor color; - switch (security_level) { - case ToolbarModel::EV_SECURE: - case ToolbarModel::SECURE: - color = SkColorSetRGB(7, 149, 0); - break; - - case ToolbarModel::SECURITY_WARNING: - return GetColor(security_level, DEEMPHASIZED_TEXT); - break; - - case ToolbarModel::SECURITY_ERROR: - color = SkColorSetRGB(162, 0, 0); - break; - - default: - NOTREACHED(); - return GetColor(security_level, TEXT); - } - return color_utils::GetReadableColor(color, GetColor(security_level, - BACKGROUND)); - } - - default: - NOTREACHED(); - return GetColor(security_level, TEXT); + colors[SECURE][BACKGROUND] = SkColorSetRGB(255, 245, 195); + colors[SECURE][TEXT] = SK_ColorBLACK; + colors[SECURE][SELECTED_TEXT] = 0; // Unused + colors[NOT_SECURE][DEEMPHASIZED_TEXT] = + color_utils::AlphaBlend(colors[NOT_SECURE][TEXT], + colors[NOT_SECURE][BACKGROUND], 128); + colors[SECURE][DEEMPHASIZED_TEXT] = + color_utils::AlphaBlend(colors[SECURE][TEXT], + colors[SECURE][BACKGROUND], 128); + colors[NOT_SECURE][SECURITY_TEXT] = color_utils::GetReadableColor( + SkColorSetRGB(200, 0, 0), colors[NOT_SECURE][BACKGROUND]); + colors[SECURE][SECURITY_TEXT] = SkColorSetRGB(0, 150, 20); + colors[NOT_SECURE][SECURITY_INFO_BUBBLE_TEXT] = + colors[NOT_SECURE][SECURITY_TEXT]; + colors[SECURE][SECURITY_INFO_BUBBLE_TEXT] = color_utils::GetReadableColor( + SkColorSetRGB(0, 153, 51), colors[NOT_SECURE][BACKGROUND]); + colors[NOT_SECURE][SCHEME_STRIKEOUT] = color_utils::GetReadableColor( + SkColorSetRGB(210, 0, 0), colors[NOT_SECURE][BACKGROUND]); + colors[SECURE][SCHEME_STRIKEOUT] = 0; // Unused + initialized = true; } + + return colors[is_secure ? SECURE : NOT_SECURE][kind]; } void LocationBarView::Update(const TabContents* tab_for_state_restoring) { + SetSecurityIcon(model_->GetIcon()); RefreshContentSettingViews(); RefreshPageActionViews(); + std::wstring info_text, info_tooltip; + ToolbarModel::InfoTextType info_text_type = + model_->GetInfoText(&info_text, &info_tooltip); + SetInfoText(info_text, info_text_type, info_tooltip); location_entry_->Update(tab_for_state_restoring); - OnChanged(); + Layout(); + SchedulePaint(); } void LocationBarView::UpdateContentSettingsIcons() { @@ -358,6 +362,7 @@ void LocationBarView::SetProfile(Profile* profile) { for (ContentSettingViews::const_iterator i(content_setting_views_.begin()); i != content_setting_views_.end(); ++i) (*i)->set_profile(profile); + security_image_view_.set_profile(profile); } } @@ -365,11 +370,8 @@ TabContents* LocationBarView::GetTabContents() const { return delegate_->GetTabContents(); } -void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction* page_action, +void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction *page_action, bool preview_enabled) { - if (popup_window_mode_) - return; - DCHECK(page_action); TabContents* contents = delegate_->GetTabContents(); @@ -398,156 +400,13 @@ views::View* LocationBarView::GetPageActionView( return NULL; } -void LocationBarView::SetStarToggled(bool on) { - star_view_.SetToggled(on); -} - -void LocationBarView::ShowStarBubble(const GURL& url, bool newly_bookmarked) { - gfx::Rect screen_bounds(star_view_.GetImageBounds()); - // Compensate for some built-in padding in the Star image. - screen_bounds.Inset(1, 1, 1, 2); - gfx::Point origin(screen_bounds.origin()); - views::View::ConvertPointToScreen(&star_view_, &origin); - screen_bounds.set_origin(origin); - browser::ShowBookmarkBubbleView(GetWindow(), screen_bounds, &star_view_, - profile_, url, newly_bookmarked); -} - gfx::Size LocationBarView::GetPreferredSize() { return gfx::Size(0, (popup_window_mode_ ? kPopupBackground : kBackground)->height()); } void LocationBarView::Layout() { - if (!location_entry_.get()) - return; - - int entry_width = width() - kViewPadding; - - // |location_icon_view_| is visible except when |ev_bubble_view_| or - // |selected_keyword_view_| are visible. - int location_icon_width = 0; - int ev_bubble_width = 0; - location_icon_view_.SetVisible(false); - ev_bubble_view_.SetVisible(false); - const std::wstring keyword(location_entry_->model()->keyword()); - const bool is_keyword_hint(location_entry_->model()->is_keyword_hint()); - const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint; - if (show_selected_keyword) { - entry_width -= kViewPadding; // Assume the keyword might be hidden. - } else if (model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) { - ev_bubble_view_.SetVisible(true); - ev_bubble_view_.SetLabel(model_->GetEVCertName()); - ev_bubble_width = ev_bubble_view_.GetPreferredSize().width(); - entry_width -= kBubblePadding + ev_bubble_width + kViewPadding; - } else { - location_icon_view_.SetVisible(true); - location_icon_width = location_icon_view_.GetPreferredSize().width(); - entry_width -= - kViewPadding + location_icon_width + kLocationIconEditPadding; - } - - entry_width -= star_view_.GetPreferredSize().width() + kViewPadding; - for (PageActionViews::const_iterator i(page_action_views_.begin()); - i != page_action_views_.end(); ++i) { - if ((*i)->IsVisible()) - entry_width -= (*i)->GetPreferredSize().width() + kViewPadding; - } - for (ContentSettingViews::const_iterator i(content_setting_views_.begin()); - i != content_setting_views_.end(); ++i) { - if ((*i)->IsVisible()) - entry_width -= (*i)->GetPreferredSize().width() + kViewPadding; - } - -#if defined(OS_WIN) - RECT formatting_rect; - location_entry_->GetRect(&formatting_rect); - RECT edit_bounds; - location_entry_->GetClientRect(&edit_bounds); - int max_edit_width = entry_width - formatting_rect.left - - (edit_bounds.right - formatting_rect.right); -#else - int max_edit_width = entry_width; -#endif - - if (max_edit_width < 0) - return; - const int available_width = AvailableWidth(max_edit_width); - - const bool show_keyword_hint = !keyword.empty() && is_keyword_hint; - selected_keyword_view_.SetVisible(show_selected_keyword); - keyword_hint_view_.SetVisible(show_keyword_hint); - if (show_selected_keyword) { - if (selected_keyword_view_.keyword() != keyword) - selected_keyword_view_.SetKeyword(keyword); - } else if (show_keyword_hint) { - if (keyword_hint_view_.keyword() != keyword) - keyword_hint_view_.SetKeyword(keyword); - } - - // TODO(sky): baseline layout. - int location_y = TopMargin(); - int location_height = std::max(height() - location_y - kVertMargin, 0); - - // Lay out items to the right of the edit field. - int offset = width() - kViewPadding; - int star_width = star_view_.GetPreferredSize().width(); - offset -= star_width; - star_view_.SetBounds(offset, location_y, star_width, location_height); - offset -= kViewPadding; - - for (PageActionViews::const_iterator i(page_action_views_.begin()); - i != page_action_views_.end(); ++i) { - if ((*i)->IsVisible()) { - int page_action_width = (*i)->GetPreferredSize().width(); - offset -= page_action_width; - (*i)->SetBounds(offset, location_y, page_action_width, location_height); - offset -= kViewPadding; - } - } - // We use a reverse_iterator here because we're laying out the views from - // right to left but in the vector they're ordered left to right. - for (ContentSettingViews::const_reverse_iterator - i(content_setting_views_.rbegin()); i != content_setting_views_.rend(); - ++i) { - if ((*i)->IsVisible()) { - int content_blocked_width = (*i)->GetPreferredSize().width(); - offset -= content_blocked_width; - (*i)->SetBounds(offset, location_y, content_blocked_width, - location_height); - offset -= kViewPadding; - } - } - - // Now lay out items to the left of the edit field. - if (location_icon_view_.IsVisible()) { - location_icon_view_.SetBounds(kViewPadding, location_y, location_icon_width, - location_height); - offset = location_icon_view_.bounds().right() + kLocationIconEditPadding; - } else if (ev_bubble_view_.IsVisible()) { - ev_bubble_view_.SetBounds(kBubblePadding, location_y, ev_bubble_width, - location_height); - offset = ev_bubble_view_.bounds().right() + kViewPadding; - } else { - offset = show_selected_keyword ? kBubblePadding : kViewPadding; - } - - // Now lay out the edit field and views that autocollapse to give it more - // room. - gfx::Rect location_bounds(offset, location_y, entry_width, location_height); - if (show_selected_keyword) { - LayoutView(true, &selected_keyword_view_, available_width, - &location_bounds); - if (!selected_keyword_view_.IsVisible()) { - location_bounds.set_x( - location_bounds.x() + kViewPadding - kBubblePadding); - } - } else if (show_keyword_hint) { - LayoutView(false, &keyword_hint_view_, available_width, - &location_bounds); - } - - location_entry_view_->SetBounds(location_bounds); + DoLayout(true); } void LocationBarView::Paint(gfx::Canvas* canvas) { @@ -560,9 +419,10 @@ void LocationBarView::Paint(gfx::Canvas* canvas) { canvas->TileImageInt(*background, 0, 0, 0, 0, width(), height()); int top_margin = TopMargin(); - canvas->FillRectInt(GetColor(ToolbarModel::NONE, BACKGROUND), 0, - top_margin, width(), - std::max(height() - top_margin - kVertMargin, 0)); + canvas->FillRectInt( + GetColor(model_->GetSchemeSecurityLevel() == ToolbarModel::SECURE, + BACKGROUND), + 0, top_margin, width(), std::max(height() - top_margin - kVertMargin, 0)); } void LocationBarView::VisibleBoundsInRootChanged() { @@ -649,11 +509,7 @@ void LocationBarView::OnAutocompleteAccept( } void LocationBarView::OnChanged() { - location_icon_view_.SetImage( - ResourceBundle::GetSharedInstance().GetBitmapNamed( - location_entry_->GetIcon())); - Layout(); - SchedulePaint(); + DoLayout(false); } void LocationBarView::OnInputInProgress(bool in_progress) { @@ -684,6 +540,117 @@ std::wstring LocationBarView::GetTitle() const { return UTF16ToWideHack(delegate_->GetTabContents()->GetTitle()); } +void LocationBarView::DoLayout(const bool force_layout) { + if (!location_entry_.get()) + return; + + int entry_width = width() - (kEntryPadding * 2); + + for (PageActionViews::const_iterator i(page_action_views_.begin()); + i != page_action_views_.end(); ++i) { + if ((*i)->IsVisible()) + entry_width -= (*i)->GetPreferredSize().width() + kInnerPadding; + } + for (ContentSettingViews::const_iterator i(content_setting_views_.begin()); + i != content_setting_views_.end(); ++i) { + if ((*i)->IsVisible()) + entry_width -= (*i)->GetPreferredSize().width() + kInnerPadding; + } + gfx::Size security_image_size; + if (security_image_view_.IsVisible()) { + security_image_size = security_image_view_.GetPreferredSize(); + entry_width -= security_image_size.width() + kInnerPadding; + } + gfx::Size info_label_size; + if (info_label_.IsVisible()) { + info_label_size = info_label_.GetPreferredSize(); + entry_width -= (info_label_size.width() + kInnerPadding); + } + +#if defined(OS_WIN) + RECT formatting_rect; + location_entry_->GetRect(&formatting_rect); + RECT edit_bounds; + location_entry_->GetClientRect(&edit_bounds); + int max_edit_width = entry_width - formatting_rect.left - + (edit_bounds.right - formatting_rect.right); +#else + int max_edit_width = entry_width; +#endif + + if (max_edit_width < 0) + return; + const int available_width = AvailableWidth(max_edit_width); + bool needs_layout = force_layout; + needs_layout |= AdjustHints(available_width); + + if (!needs_layout) + return; + + // TODO(sky): baseline layout. + int location_y = TopMargin(); + int location_height = std::max(height() - location_y - kVertMargin, 0); + + // First set the bounds for the label that appears to the right of the + // security icon. + int offset = width() - kEntryPadding; + if (info_label_.IsVisible()) { + offset -= info_label_size.width(); + info_label_.SetBounds(offset, location_y, + info_label_size.width(), location_height); + offset -= kInnerPadding; + } + if (security_image_view_.IsVisible()) { + offset -= security_image_size.width(); + security_image_view_.SetBounds(offset, location_y, + security_image_size.width(), + location_height); + offset -= kInnerPadding; + } + + for (PageActionViews::const_iterator i(page_action_views_.begin()); + i != page_action_views_.end(); ++i) { + if ((*i)->IsVisible()) { + int page_action_width = (*i)->GetPreferredSize().width(); + offset -= page_action_width; + (*i)->SetBounds(offset, location_y, page_action_width, location_height); + offset -= kInnerPadding; + } + } + // We use a reverse_iterator here because we're laying out the views from + // right to left but in the vector they're ordered left to right. + for (ContentSettingViews::const_reverse_iterator + i(content_setting_views_.rbegin()); i != content_setting_views_.rend(); + ++i) { + if ((*i)->IsVisible()) { + int content_blocked_width = (*i)->GetPreferredSize().width(); + offset -= content_blocked_width; + (*i)->SetBounds(offset, location_y, content_blocked_width, + location_height); + offset -= kInnerPadding; + } + } + gfx::Rect location_bounds(kEntryPadding, location_y, entry_width, + location_height); + if (selected_keyword_view_.IsVisible()) { + LayoutView(true, &selected_keyword_view_, available_width, + &location_bounds); + } else if (keyword_hint_view_.IsVisible()) { + LayoutView(false, &keyword_hint_view_, available_width, + &location_bounds); + } else if (type_to_search_view_.IsVisible()) { + LayoutView(false, &type_to_search_view_, available_width, + &location_bounds); + } + + location_entry_view_->SetBounds(location_bounds); + if (!force_layout) { + // If force_layout is false and we got this far it means one of the views + // was added/removed or changed in size. We need to paint ourselves. + SchedulePaint(); + } +} + int LocationBarView::TopMargin() const { return std::min(kVertMargin, height()); } @@ -702,7 +669,52 @@ int LocationBarView::AvailableWidth(int location_bar_width) { } bool LocationBarView::UsePref(int pref_width, int available_width) { - return (pref_width + kViewPadding <= available_width); + return (pref_width + kInnerPadding <= available_width); +} + +bool LocationBarView::NeedsResize(View* view, int available_width) { + gfx::Size size = view->GetPreferredSize(); + if (!UsePref(size.width(), available_width)) + size = view->GetMinimumSize(); + return (view->width() != size.width()); +} + +bool LocationBarView::AdjustHints(int available_width) { + const std::wstring keyword(location_entry_->model()->keyword()); + const bool is_keyword_hint(location_entry_->model()->is_keyword_hint()); + const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint; + const bool show_keyword_hint = !keyword.empty() && is_keyword_hint; + bool show_search_hint(location_entry_->model()->show_search_hint()); + DCHECK(keyword.empty() || !show_search_hint); + + if (show_search_hint) { + // Only show type to search if all the text fits. + gfx::Size view_pref = type_to_search_view_.GetPreferredSize(); + show_search_hint = UsePref(view_pref.width(), available_width); + } + + // NOTE: This isn't just one big || statement as ToggleVisibility MUST be + // invoked for each view. + bool needs_layout = false; + needs_layout |= ToggleVisibility(show_selected_keyword, + &selected_keyword_view_); + needs_layout |= ToggleVisibility(show_keyword_hint, &keyword_hint_view_); + needs_layout |= ToggleVisibility(show_search_hint, &type_to_search_view_); + if (show_selected_keyword) { + if (selected_keyword_view_.keyword() != keyword) { + needs_layout = true; + selected_keyword_view_.SetKeyword(keyword); + } + needs_layout |= NeedsResize(&selected_keyword_view_, available_width); + } else if (show_keyword_hint) { + if (keyword_hint_view_.keyword() != keyword) { + needs_layout = true; + keyword_hint_view_.SetKeyword(keyword); + } + needs_layout |= NeedsResize(&keyword_hint_view_, available_width); + } + + return needs_layout; } void LocationBarView::LayoutView(bool leading, @@ -713,20 +725,40 @@ void LocationBarView::LayoutView(bool leading, gfx::Size view_size = view->GetPreferredSize(); if (!UsePref(view_size.width(), available_width)) view_size = view->GetMinimumSize(); - if (view_size.width() + kViewPadding >= bounds->width()) { + if (view_size.width() + kInnerPadding < bounds->width()) { + view->SetVisible(true); + if (leading) { + view->SetBounds(bounds->x(), bounds->y(), view_size.width(), + bounds->height()); + bounds->Offset(view_size.width() + kInnerPadding, 0); + } else { + view->SetBounds(bounds->right() - view_size.width(), bounds->y(), + view_size.width(), bounds->height()); + } + bounds->set_width(bounds->width() - view_size.width() - kInnerPadding); + } else { view->SetVisible(false); - return; } - if (leading) { - view->SetBounds(bounds->x(), bounds->y(), view_size.width(), - bounds->height()); - bounds->Offset(view_size.width() + kViewPadding, 0); - } else { - view->SetBounds(bounds->right() - view_size.width(), bounds->y(), - view_size.width(), bounds->height()); +} + +void LocationBarView::SetSecurityIcon(ToolbarModel::Icon icon) { + switch (icon) { + case ToolbarModel::LOCK_ICON: + security_image_view_.SetImageShown(SecurityImageView::LOCK); + security_image_view_.SetVisible(true); + break; + case ToolbarModel::WARNING_ICON: + security_image_view_.SetImageShown(SecurityImageView::WARNING); + security_image_view_.SetVisible(true); + break; + case ToolbarModel::NO_ICON: + security_image_view_.SetVisible(false); + break; + default: + NOTREACHED(); + security_image_view_.SetVisible(false); + break; } - bounds->set_width(bounds->width() - view_size.width() - kViewPadding); - view->SetVisible(true); } void LocationBarView::RefreshContentSettingViews() { @@ -746,9 +778,7 @@ void LocationBarView::DeletePageActionViews() { } void LocationBarView::RefreshPageActionViews() { - if (popup_window_mode_) - return; - + std::vector<ExtensionAction*> page_actions; ExtensionsService* service = profile_->GetExtensionsService(); if (!service) return; @@ -760,7 +790,6 @@ void LocationBarView::RefreshPageActionViews() { // Remember the previous visibility of the page actions so that we can // notify when this changes. - std::vector<ExtensionAction*> page_actions; for (size_t i = 0; i < service->extensions()->size(); ++i) { if (service->extensions()->at(i)->page_action()) page_actions.push_back(service->extensions()->at(i)->page_action()); @@ -775,7 +804,8 @@ void LocationBarView::RefreshPageActionViews() { for (size_t i = 0; i < page_actions.size(); ++i) { page_action_views_[i] = new PageActionWithBadgeView( - new PageActionImageView(this, profile_, page_actions[i])); + new PageActionImageView(this, profile_, + page_actions[i], bubble_positioner_)); page_action_views_[i]->SetVisible(false); AddChildView(page_action_views_[i]); } @@ -802,6 +832,25 @@ void LocationBarView::RefreshPageActionViews() { } } +void LocationBarView::SetInfoText(const std::wstring& text, + ToolbarModel::InfoTextType text_type, + const std::wstring& tooltip_text) { + info_label_.SetVisible(!text.empty()); + info_label_.SetText(text); + if (text_type == ToolbarModel::INFO_EV_TEXT) + info_label_.SetColor(GetColor(true, SECURITY_TEXT)); + info_label_.SetTooltipText(tooltip_text); +} + +bool LocationBarView::ToggleVisibility(bool new_vis, View* view) { + DCHECK(view); + if (view->IsVisible() != new_vis) { + view->SetVisible(new_vis); + return true; + } + return false; +} + #if defined(OS_WIN) void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) { UINT flags = 0; @@ -818,54 +867,10 @@ void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) { gfx::Point screen_point(event.location()); ConvertPointToScreen(this, &screen_point); - location_entry_->HandleExternalMsg(msg, flags, screen_point.ToPOINT()); -} -#endif - -void LocationBarView::ShowFirstRunBubbleInternal( - FirstRun::BubbleType bubble_type) { -#if defined(OS_WIN) // First run bubble doesn't make sense for Chrome OS. - // If the browser is no longer active, let's not show the info bubble, as this - // would make the browser the active window again. - if (!location_entry_view_ || !location_entry_view_->GetWidget()->IsActive()) - return; - // Point at the start of the edit control; adjust to look as good as possible. - const int kXOffset = 1; // Text looks like it actually starts 1 px in. - const int kYOffset = -4; // Point into the omnibox, not just at its edge. - gfx::Point origin(location_entry_view_->bounds().x() + kXOffset, - y() + height() + kYOffset); - // If the UI layout is RTL, the coordinate system is not transformed and - // therefore we need to adjust the X coordinate so that bubble appears on the - // right hand side of the location bar. - if (UILayoutIsRightToLeft()) - origin.set_x(width() - origin.x()); - views::View::ConvertPointToScreen(this, &origin); - FirstRunBubble::Show(profile_, GetWindow(), gfx::Rect(origin, gfx::Size()), - bubble_type); -#endif + location_entry_->HandleExternalMsg(msg, flags, screen_point.ToPOINT()); } - -bool LocationBarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) { - if (keyword_hint_view_.IsVisible() && - views::FocusManager::IsTabTraversalKeyEvent(e)) { - // We want to receive tab key events when the hint is showing. - return true; - } - -#if defined(OS_WIN) - return location_entry_->SkipDefaultKeyEventProcessing(e); -#else - // TODO(jcampan): We need to refactor the code of - // AutocompleteEditViewWin::SkipDefaultKeyEventProcessing into this class so - // it can be shared between Windows and Linux. - // For now, we just override back-space as it is the accelerator for back - // navigation. - if (e.GetKeyCode() == base::VKEY_BACK) - return true; - return false; #endif -} bool LocationBarView::GetAccessibleRole(AccessibilityTypes::Role* role) { DCHECK(role); @@ -874,213 +879,76 @@ bool LocationBarView::GetAccessibleRole(AccessibilityTypes::Role* role) { return true; } +// SelectedKeywordView ------------------------------------------------------- -void LocationBarView::WriteDragData(views::View* sender, - const gfx::Point& press_pt, - OSExchangeData* data) { - DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE); - - TabContents* tab_contents = delegate_->GetTabContents(); - DCHECK(tab_contents); - drag_utils::SetURLAndDragImage(tab_contents->GetURL(), - UTF16ToWideHack(tab_contents->GetTitle()), - tab_contents->GetFavIcon(), data); -} - -int LocationBarView::GetDragOperations(views::View* sender, - const gfx::Point& p) { - DCHECK((sender == &location_icon_view_) || (sender == &ev_bubble_view_)); - TabContents* tab_contents = delegate_->GetTabContents(); - return (tab_contents && tab_contents->GetURL().is_valid() && - !location_entry()->IsEditingOrEmpty()) ? - (DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK) : - DragDropTypes::DRAG_NONE; -} - -bool LocationBarView::CanStartDrag(View* sender, - const gfx::Point& press_pt, - const gfx::Point& p) { - return true; -} - -// ClickHandler ---------------------------------------------------------------- - -LocationBarView::ClickHandler::ClickHandler(const views::View* owner, - const LocationBarView* location_bar) - : owner_(owner), - location_bar_(location_bar) { -} - -void LocationBarView::ClickHandler::OnMouseReleased( - const views::MouseEvent& event, - bool canceled) { - if (canceled || !owner_->HitTest(event.location())) - return; - - // Do not show page info if the user has been editing the location - // bar, or the location bar is at the NTP. - if (location_bar_->location_entry()->IsEditingOrEmpty()) - return; - - TabContents* tab = location_bar_->GetTabContents(); - NavigationEntry* nav_entry = tab->controller().GetActiveEntry(); - if (!nav_entry) { - NOTREACHED(); - return; - } - tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true); -} - -// LocationIconView ------------------------------------------------------------ - -LocationBarView::LocationIconView::LocationIconView( - const LocationBarView* location_bar) - : ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) { -} - -LocationBarView::LocationIconView::~LocationIconView() { -} - -bool LocationBarView::LocationIconView::OnMousePressed( - const views::MouseEvent& event) { - // We want to show the dialog on mouse release; that is the standard behavior - // for buttons. - return true; -} - -void LocationBarView::LocationIconView::OnMouseReleased( - const views::MouseEvent& event, - bool canceled) { - click_handler_.OnMouseReleased(event, canceled); -} - -// IconLabelBubbleView --------------------------------------------------------- - -// Amount to offset the image. -static const int kImageOffset = 1; - -// Amount to offset the label from the image. -static const int kLabelOffset = 3; - -// Amount of padding after the label. -static const int kLabelPadding = 4; - -LocationBarView::IconLabelBubbleView::IconLabelBubbleView( - const int background_images[], - int contained_image, - const SkColor& color) - : background_painter_(background_images) { - AddChildView(&image_); - image_.set_parent_owned(false); - image_.SetImage( - ResourceBundle::GetSharedInstance().GetBitmapNamed(contained_image)); - AddChildView(&label_); - label_.set_parent_owned(false); - label_.SetColor(color); -} - -LocationBarView::IconLabelBubbleView::~IconLabelBubbleView() { -} - -void LocationBarView::IconLabelBubbleView::SetFont(const gfx::Font& font) { - label_.SetFont(font); -} - -void LocationBarView::IconLabelBubbleView::SetLabel(const std::wstring& label) { - label_.SetText(label); -} - -void LocationBarView::IconLabelBubbleView::Paint(gfx::Canvas* canvas) { - int y_offset = (GetParent()->height() - height()) / 2; - canvas->TranslateInt(0, y_offset); - background_painter_.Paint(width(), height(), canvas); - canvas->TranslateInt(0, -y_offset); -} - -gfx::Size LocationBarView::IconLabelBubbleView::GetPreferredSize() { - gfx::Size size(GetNonLabelSize()); - size.Enlarge(label_.GetPreferredSize().width(), 0); - return size; -} - -void LocationBarView::IconLabelBubbleView::Layout() { - image_.SetBounds(kImageOffset, 0, image_.GetPreferredSize().width(), - height()); - gfx::Size label_size(label_.GetPreferredSize()); - label_.SetBounds(image_.x() + image_.width() + kLabelOffset, - (height() - label_size.height()) / 2, label_size.width(), - label_size.height()); -} - -gfx::Size LocationBarView::IconLabelBubbleView::GetNonLabelSize() { - return gfx::Size(kImageOffset + image_.GetPreferredSize().width() + - kLabelOffset + kLabelPadding, background_painter_.height()); -} - -// EVBubbleView ---------------------------------------------------------------- - -LocationBarView::EVBubbleView::EVBubbleView(const int background_images[], - int contained_image, - const SkColor& color, - const LocationBarView* location_bar) - : IconLabelBubbleView(background_images, contained_image, color), - ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) { -} - -LocationBarView::EVBubbleView::~EVBubbleView() { -} - -bool LocationBarView::EVBubbleView::OnMousePressed( - const views::MouseEvent& event) { - // We want to show the dialog on mouse release; that is the standard behavior - // for buttons. - return true; -} +// The background is drawn using HorizontalPainter. This is the +// left/center/right image names. +static const int kBorderImages[] = { + IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_L, + IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_C, + IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_R }; -void LocationBarView::EVBubbleView::OnMouseReleased( - const views::MouseEvent& event, - bool canceled) { - click_handler_.OnMouseReleased(event, canceled); -} +// Insets around the label. +static const int kTopInset = 0; +static const int kBottomInset = 0; +static const int kLeftInset = 4; +static const int kRightInset = 4; -// SelectedKeywordView --------------------------------------------------------- +// Offset from the top the background is drawn at. +static const int kBackgroundYOffset = 2; -LocationBarView::SelectedKeywordView::SelectedKeywordView( - const int background_images[], - int contained_image, - const SkColor& color, - Profile* profile) - : IconLabelBubbleView(background_images, contained_image, color), +LocationBarView::SelectedKeywordView::SelectedKeywordView(Profile* profile) + : background_painter_(kBorderImages), profile_(profile) { + AddChildView(&full_label_); + AddChildView(&partial_label_); + // Full_label and partial_label are deleted by us, make sure View doesn't + // delete them too. + full_label_.set_parent_owned(false); + partial_label_.set_parent_owned(false); full_label_.SetVisible(false); partial_label_.SetVisible(false); + full_label_.set_border( + views::Border::CreateEmptyBorder(kTopInset, kLeftInset, kBottomInset, + kRightInset)); + partial_label_.set_border( + views::Border::CreateEmptyBorder(kTopInset, kLeftInset, kBottomInset, + kRightInset)); + full_label_.SetColor(SK_ColorBLACK); + partial_label_.SetColor(SK_ColorBLACK); } LocationBarView::SelectedKeywordView::~SelectedKeywordView() { } void LocationBarView::SelectedKeywordView::SetFont(const gfx::Font& font) { - IconLabelBubbleView::SetFont(font); full_label_.SetFont(font); partial_label_.SetFont(font); } +void LocationBarView::SelectedKeywordView::Paint(gfx::Canvas* canvas) { + canvas->TranslateInt(0, kBackgroundYOffset); + background_painter_.Paint(width(), height() - kTopInset, canvas); + canvas->TranslateInt(0, -kBackgroundYOffset); +} + gfx::Size LocationBarView::SelectedKeywordView::GetPreferredSize() { - gfx::Size size(GetNonLabelSize()); - size.Enlarge(full_label_.GetPreferredSize().width(), 0); - return size; + return full_label_.GetPreferredSize(); } gfx::Size LocationBarView::SelectedKeywordView::GetMinimumSize() { - gfx::Size size(GetNonLabelSize()); - size.Enlarge(partial_label_.GetMinimumSize().width(), 0); - return size; + return partial_label_.GetMinimumSize(); } void LocationBarView::SelectedKeywordView::Layout() { - SetLabel((width() == GetPreferredSize().width()) ? - full_label_.GetText() : partial_label_.GetText()); - IconLabelBubbleView::Layout(); + gfx::Size pref = GetPreferredSize(); + bool at_pref = (width() == pref.width()); + if (at_pref) + full_label_.SetBounds(0, 0, width(), height()); + else + partial_label_.SetBounds(0, 0, width(), height()); + full_label_.SetVisible(at_pref); + partial_label_.SetVisible(!at_pref); } void LocationBarView::SelectedKeywordView::SetKeyword( @@ -1096,9 +964,12 @@ void LocationBarView::SelectedKeywordView::SetKeyword( full_label_.SetText(l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT, short_name)); const std::wstring min_string = CalculateMinString(short_name); - partial_label_.SetText(min_string.empty() ? - full_label_.GetText() : - l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT, min_string)); + if (!min_string.empty()) { + partial_label_.SetText( + l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT, min_string)); + } else { + partial_label_.SetText(full_label_.GetText()); + } } std::wstring LocationBarView::SelectedKeywordView::CalculateMinString( @@ -1225,18 +1096,250 @@ void LocationBarView::KeywordHintView::Layout() { } } +bool LocationBarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) { + if (keyword_hint_view_.IsVisible() && + views::FocusManager::IsTabTraversalKeyEvent(e)) { + // We want to receive tab key events when the hint is showing. + return true; + } + +#if defined(OS_WIN) + return location_entry_->SkipDefaultKeyEventProcessing(e); +#else + // TODO(jcampan): We need to refactor the code of + // AutocompleteEditViewWin::SkipDefaultKeyEventProcessing into this class so + // it can be shared between Windows and Linux. + // For now, we just override back-space as it is the accelerator for back + // navigation. + if (e.GetKeyCode() == base::VKEY_BACK) + return true; + return false; +#endif +} + +// ShowInfoBubbleTask----------------------------------------------------------- + +class LocationBarView::ShowInfoBubbleTask : public Task { + public: + explicit ShowInfoBubbleTask( + LocationBarView::LocationBarImageView* image_view); + virtual void Run(); + void Cancel(); + + private: + LocationBarView::LocationBarImageView* image_view_; + bool cancelled_; + + DISALLOW_COPY_AND_ASSIGN(ShowInfoBubbleTask); +}; + +LocationBarView::ShowInfoBubbleTask::ShowInfoBubbleTask( + LocationBarView::LocationBarImageView* image_view) + : image_view_(image_view), + cancelled_(false) { +} + +void LocationBarView::ShowInfoBubbleTask::Run() { + if (cancelled_) + return; + + if (!image_view_->GetWidget()->IsActive()) { + // The browser is no longer active. Let's not show the info bubble, this + // would make the browser the active window again. Also makes sure we NULL + // show_info_bubble_task_ to prevent the SecurityImageView from keeping a + // dangling pointer. + image_view_->show_info_bubble_task_ = NULL; + return; + } + + image_view_->ShowInfoBubble(); +} + +void LocationBarView::ShowInfoBubbleTask::Cancel() { + cancelled_ = true; +} + +// ----------------------------------------------------------------------------- + +void LocationBarView::ShowFirstRunBubbleInternal( + FirstRun::BubbleType bubble_type) { + if (!location_entry_view_) + return; + if (!location_entry_view_->GetWidget()->IsActive()) { + // The browser is no longer active. Let's not show the info bubble, this + // would make the browser the active window again. + return; + } + + gfx::Point location; + + // If the UI layout is RTL, the coordinate system is not transformed and + // therefore we need to adjust the X coordinate so that bubble appears on the + // right hand side of the location bar. + if (UILayoutIsRightToLeft()) + location.Offset(width(), 0); + views::View::ConvertPointToScreen(this, &location); + + // We try to guess that 20 pixels offset is a good place for the first + // letter in the OmniBox. + gfx::Rect bounds(location.x(), location.y(), 20, height()); + + // Moving the bounds "backwards" so that it appears within the location bar + // if the UI layout is RTL. + if (UILayoutIsRightToLeft()) + bounds.set_x(location.x() - 20); + +#if defined(OS_WIN) + FirstRunBubble::Show(profile_, GetWindow(), bounds, bubble_type); +#else + // First run bubble doesn't make sense for Chrome OS. +#endif +} + +// LocationBarImageView--------------------------------------------------------- + +LocationBarView::LocationBarImageView::LocationBarImageView( + const BubblePositioner* bubble_positioner) + : info_bubble_(NULL), + show_info_bubble_task_(NULL), + bubble_positioner_(bubble_positioner) { +} + +LocationBarView::LocationBarImageView::~LocationBarImageView() { + if (show_info_bubble_task_) + show_info_bubble_task_->Cancel(); + + if (info_bubble_) + info_bubble_->Close(); +} + +void LocationBarView::LocationBarImageView::OnMouseMoved( + const views::MouseEvent& event) { + if (show_info_bubble_task_) { + show_info_bubble_task_->Cancel(); + show_info_bubble_task_ = NULL; + } + + if (info_bubble_) { + // If an info bubble is currently showing, nothing to do. + return; + } + + show_info_bubble_task_ = new ShowInfoBubbleTask(this); + MessageLoop::current()->PostDelayedTask(FROM_HERE, show_info_bubble_task_, + kInfoBubbleHoverDelayMs); +} + +void LocationBarView::LocationBarImageView::OnMouseExited( + const views::MouseEvent& event) { + if (show_info_bubble_task_) { + show_info_bubble_task_->Cancel(); + show_info_bubble_task_ = NULL; + } + + if (info_bubble_) + info_bubble_->Close(); +} + +void LocationBarView::LocationBarImageView::InfoBubbleClosing( + InfoBubble* info_bubble, bool closed_by_escape) { + info_bubble_ = NULL; +} + +void LocationBarView::LocationBarImageView::ShowInfoBubbleImpl( + const std::wstring& text, SkColor text_color) { + gfx::Rect bounds(bubble_positioner_->GetLocationStackBounds()); + gfx::Point location; + views::View::ConvertPointToScreen(this, &location); + bounds.set_x(location.x()); + bounds.set_width(width()); + + views::Label* label = new views::Label(text); + label->SetMultiLine(true); + label->SetColor(text_color); + label->SetFont(ResourceBundle::GetSharedInstance().GetFont( + ResourceBundle::BaseFont).DeriveFont(2)); + label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + label->SizeToFit(0); + DCHECK(info_bubble_ == NULL); + info_bubble_ = InfoBubble::Show(GetWindow(), bounds, label, this); + show_info_bubble_task_ = NULL; +} + +// SecurityImageView------------------------------------------------------------ + +// static +SkBitmap* LocationBarView::SecurityImageView::lock_icon_ = NULL; +SkBitmap* LocationBarView::SecurityImageView::warning_icon_ = NULL; + +LocationBarView::SecurityImageView::SecurityImageView( + const LocationBarView* parent, + Profile* profile, + ToolbarModel* model, + const BubblePositioner* bubble_positioner) + : LocationBarImageView(bubble_positioner), + parent_(parent), + profile_(profile), + model_(model) { + if (!lock_icon_) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + lock_icon_ = rb.GetBitmapNamed(IDR_LOCK); + warning_icon_ = rb.GetBitmapNamed(IDR_WARNING); + } + SetImageShown(LOCK); +} + +LocationBarView::SecurityImageView::~SecurityImageView() { +} + +void LocationBarView::SecurityImageView::SetImageShown(Image image) { + switch (image) { + case LOCK: + SetImage(lock_icon_); + break; + case WARNING: + SetImage(warning_icon_); + break; + default: + NOTREACHED(); + break; + } +} + +bool LocationBarView::SecurityImageView::OnMousePressed( + const views::MouseEvent& event) { + TabContents* tab = parent_->GetTabContents(); + NavigationEntry* nav_entry = tab->controller().GetActiveEntry(); + if (!nav_entry) { + NOTREACHED(); + return true; + } + tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true); + return true; +} + +void LocationBarView::SecurityImageView::ShowInfoBubble() { + std::wstring text; + model_->GetIconHoverText(&text); + ShowInfoBubbleImpl(text, GetColor( + model_->GetSecurityLevel() == ToolbarModel::SECURE, + SECURITY_INFO_BUBBLE_TEXT)); +} + // ContentSettingImageView------------------------------------------------------ LocationBarView::ContentSettingImageView::ContentSettingImageView( ContentSettingsType content_type, const LocationBarView* parent, - Profile* profile) + Profile* profile, + const BubblePositioner* bubble_positioner) : content_setting_image_model_( ContentSettingImageModel::CreateContentSettingImageModel( content_type)), parent_(parent), profile_(profile), - info_bubble_(NULL) { + info_bubble_(NULL), + bubble_positioner_(bubble_positioner) { } LocationBarView::ContentSettingImageView::~ContentSettingImageView() { @@ -1248,39 +1351,29 @@ void LocationBarView::ContentSettingImageView::UpdateFromTabContents( const TabContents* tab_contents) { int old_icon = content_setting_image_model_->get_icon(); content_setting_image_model_->UpdateFromTabContents(tab_contents); - if (!content_setting_image_model_->is_visible()) { + if (content_setting_image_model_->is_visible()) { + if (old_icon != content_setting_image_model_->get_icon()) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + SetImage(rb.GetBitmapNamed(content_setting_image_model_->get_icon())); + } + SetTooltipText(UTF8ToWide(content_setting_image_model_->get_tooltip())); + SetVisible(true); + } else { SetVisible(false); - return; - } - if (old_icon != content_setting_image_model_->get_icon()) { - SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed( - content_setting_image_model_->get_icon())); } - SetTooltipText(UTF8ToWide(content_setting_image_model_->get_tooltip())); - SetVisible(true); } bool LocationBarView::ContentSettingImageView::OnMousePressed( const views::MouseEvent& event) { - // We want to show the bubble on mouse release; that is the standard behavior - // for buttons. - return true; -} - -void LocationBarView::ContentSettingImageView::OnMouseReleased( - const views::MouseEvent& event, - bool canceled) { - if (canceled || !HitTest(event.location())) - return; + gfx::Rect bounds(bubble_positioner_->GetLocationStackBounds()); + gfx::Point location; + views::View::ConvertPointToScreen(this, &location); + bounds.set_x(location.x()); + bounds.set_width(width()); TabContents* tab_contents = parent_->GetTabContents(); if (!tab_contents) - return; - - gfx::Rect screen_bounds(GetImageBounds()); - gfx::Point origin(screen_bounds.origin()); - views::View::ConvertPointToScreen(this, &origin); - screen_bounds.set_origin(origin); + return true; ContentSettingBubbleContents* bubble_contents = new ContentSettingBubbleContents( ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -1288,9 +1381,9 @@ void LocationBarView::ContentSettingImageView::OnMouseReleased( content_setting_image_model_->get_content_settings_type()), profile_, tab_contents); DCHECK(!info_bubble_); - info_bubble_ = - InfoBubble::Show(GetWindow(), screen_bounds, bubble_contents, this); + info_bubble_ = InfoBubble::Show(GetWindow(), bounds, bubble_contents, this); bubble_contents->set_info_bubble(info_bubble_); + return true; } void LocationBarView::ContentSettingImageView::VisibilityChanged( @@ -1315,8 +1408,10 @@ bool LocationBarView::ContentSettingImageView::CloseOnEscape() { LocationBarView::PageActionImageView::PageActionImageView( LocationBarView* owner, Profile* profile, - ExtensionAction* page_action) - : owner_(owner), + ExtensionAction* page_action, + const BubblePositioner* bubble_positioner) + : LocationBarImageView(bubble_positioner), + owner_(owner), profile_(profile), page_action_(page_action), ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)), @@ -1373,17 +1468,19 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button, if (popup_showing) return; - gfx::Rect screen_bounds(GetImageBounds()); - gfx::Point origin(screen_bounds.origin()); - View::ConvertPointToScreen(this, &origin); - screen_bounds.set_origin(origin); + View* parent = GetParent(); + gfx::Point origin; + View::ConvertPointToScreen(parent, &origin); + gfx::Rect rect = parent->bounds(); + rect.set_x(origin.x()); + rect.set_y(origin.y()); popup_ = ExtensionPopup::Show( page_action_->GetPopupUrl(current_tab_id_), browser, browser->profile(), browser->window()->GetNativeHandle(), - screen_bounds, + rect, BubbleBorder::TOP_RIGHT, true, // Activate the popup window. inspect_with_devtools, @@ -1396,17 +1493,24 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button, } } +void LocationBarView::PageActionImageView::OnMouseMoved( + const views::MouseEvent& event) { + // PageActionImageView uses normal tooltips rather than the info bubble, + // so just do nothing here rather than letting LocationBarImageView start + // its hover timer. +} + bool LocationBarView::PageActionImageView::OnMousePressed( const views::MouseEvent& event) { - // We want to show the bubble on mouse release; that is the standard behavior - // for buttons. (Also, triggering on mouse press causes bugs like - // http://crbug.com/33155.) + // We are interested in capturing mouse messages, but we want want to wait + // until mouse-up because we might show a context menu. Doing so on mouse-down + // causes weird bugs like http://crbug.com/33155. return true; } void LocationBarView::PageActionImageView::OnMouseReleased( const views::MouseEvent& event, bool canceled) { - if (canceled || !HitTest(event.location())) + if (canceled) return; int button = -1; @@ -1416,26 +1520,30 @@ void LocationBarView::PageActionImageView::OnMouseReleased( button = 2; } else if (event.IsRightMouseButton()) { // Get the top left point of this button in screen coordinates. - gfx::Point menu_origin; - ConvertPointToScreen(this, &menu_origin); + gfx::Point point = gfx::Point(0, 0); + ConvertPointToScreen(this, &point); // Make the menu appear below the button. - menu_origin.Offset(0, height()); + point.Offset(0, height()); Extension* extension = profile_->GetExtensionsService()->GetExtensionById( page_action()->extension_id(), false); Browser* browser = BrowserView::GetBrowserViewForNativeWindow( platform_util::GetTopLevel(GetWidget()->GetNativeView()))->browser(); - context_menu_contents_ = - new ExtensionContextMenuModel(extension, browser, this); + context_menu_contents_ = new ExtensionContextMenuModel( + extension, browser, this); context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get())); - context_menu_menu_->RunContextMenuAt(menu_origin); + context_menu_menu_->RunContextMenuAt(point); return; } ExecuteAction(button, false); // inspect_with_devtools } +void LocationBarView::PageActionImageView::ShowInfoBubble() { + ShowInfoBubbleImpl(ASCIIToWide(tooltip_), GetColor(false, TEXT)); +} + void LocationBarView::PageActionImageView::OnImageLoaded( SkBitmap* image, ExtensionResource resource, int index) { // We loaded icons()->size() icons, plus one extra if the page action had @@ -1464,8 +1572,8 @@ void LocationBarView::PageActionImageView::UpdateVisibility( current_tab_id_ = ExtensionTabUtil::GetTabId(contents); current_url_ = url; - bool visible = - preview_enabled_ || page_action_->GetIsVisible(current_tab_id_); + bool visible = preview_enabled_ || + page_action_->GetIsVisible(current_tab_id_); if (visible) { // Set the tooltip. tooltip_ = page_action_->GetTitle(current_tab_id_); @@ -1521,54 +1629,6 @@ void LocationBarView::PageActionImageView::HidePopup() { popup_->Close(); } -// StarView--------------------------------------------------------------------- - -LocationBarView::StarView::StarView(CommandUpdater* command_updater) - : command_updater_(command_updater) { - SetID(VIEW_ID_STAR_BUTTON); - SetToggled(false); -} - -LocationBarView::StarView::~StarView() { -} - -void LocationBarView::StarView::SetToggled(bool on) { - SetTooltipText(l10n_util::GetString( - on ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR)); - // Since StarView is an ImageView, the SetTooltipText changes the accessible - // name. To keep the accessible name unchanged, we need to set the accessible - // name right after we modify the tooltip text for this view. - SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_STAR)); - SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed( - on ? IDR_OMNIBOX_STAR_LIT : IDR_OMNIBOX_STAR)); -} - -bool LocationBarView::StarView::GetAccessibleRole( - AccessibilityTypes::Role* role) { - *role = AccessibilityTypes::ROLE_PUSHBUTTON; - return true; -} - -bool LocationBarView::StarView::OnMousePressed(const views::MouseEvent& event) { - // We want to show the bubble on mouse release; that is the standard behavior - // for buttons. - return true; -} - -void LocationBarView::StarView::OnMouseReleased(const views::MouseEvent& event, - bool canceled) { - if (!canceled && HitTest(event.location())) - command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE); -} - -void LocationBarView::StarView::InfoBubbleClosing(InfoBubble* info_bubble, - bool closed_by_escape) { -} - -bool LocationBarView::StarView::CloseOnEscape() { - return true; -} - //////////////////////////////////////////////////////////////////////////////// // LocationBarView, LocationBar implementation: diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h index 956523b..faf2bfc 100644 --- a/chrome/browser/views/location_bar_view.h +++ b/chrome/browser/views/location_bar_view.h @@ -38,6 +38,7 @@ #endif class Browser; +class BubblePositioner; class CommandUpdater; class ContentSettingImageModel; class ExtensionAction; @@ -56,7 +57,6 @@ class Profile; class LocationBarView : public LocationBar, public LocationBarTesting, public views::View, - public views::DragController, public AutocompleteEditController { public: class Delegate { @@ -76,13 +76,17 @@ class LocationBarView : public LocationBar, SELECTED_TEXT, DEEMPHASIZED_TEXT, SECURITY_TEXT, + SECURITY_INFO_BUBBLE_TEXT, + SCHEME_STRIKEOUT, + NUM_KINDS }; LocationBarView(Profile* profile, CommandUpdater* command_updater, ToolbarModel* model, Delegate* delegate, - bool popup_window_mode); + bool popup_window_mode, + const BubblePositioner* bubble_positioner); virtual ~LocationBarView(); void Init(); @@ -93,8 +97,7 @@ class LocationBarView : public LocationBar, // Returns the appropriate color for the desired kind, based on the user's // system theme. - static SkColor GetColor(ToolbarModel::SecurityLevel security_level, - ColorKind kind); + static SkColor GetColor(bool is_secure, ColorKind kind); // Updates the location bar. We also reset the bar's permanent text and // security style, and, if |tab_for_state_restoring| is non-NULL, also restore @@ -118,12 +121,6 @@ class LocationBarView : public LocationBar, // Retrieves the PageAction View which is associated with |page_action|. views::View* GetPageActionView(ExtensionAction* page_action); - // Toggles the star on or off. - void SetStarToggled(bool on); - - // Shows the bookmark bubble. - void ShowStarBubble(const GURL& url, bool newly_bookmarked); - // Sizing functions virtual gfx::Size GetPreferredSize(); @@ -161,15 +158,6 @@ class LocationBarView : public LocationBar, virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e); virtual bool GetAccessibleRole(AccessibilityTypes::Role* role); - // Overridden from views::DragController: - virtual void WriteDragData(View* sender, - const gfx::Point& press_pt, - OSExchangeData* data); - virtual int GetDragOperations(View* sender, const gfx::Point& p); - virtual bool CanStartDrag(View* sender, - const gfx::Point& press_pt, - const gfx::Point& p); - // Overridden from LocationBar: virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type); virtual std::wstring GetInputString() const; @@ -184,9 +172,6 @@ class LocationBarView : public LocationBar, virtual void InvalidatePageActions(); virtual void SaveStateToContents(TabContents* contents); virtual void Revert(); - virtual const AutocompleteEditView* location_entry() const { - return location_entry_.get(); - } virtual AutocompleteEditView* location_entry() { return location_entry_.get(); } @@ -205,100 +190,20 @@ class LocationBarView : public LocationBar, void Focus(); private: - // This helper class is kept as a member by classes that need to show the Page - // Info dialog on click, to encapsulate that logic in one place. - class ClickHandler { - public: - explicit ClickHandler(const views::View* owner, - const LocationBarView* location_bar); - - void OnMouseReleased(const views::MouseEvent& event, bool canceled); - - private: - const views::View* owner_; - const LocationBarView* location_bar_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ClickHandler); - }; - - // LocationIconView is used to display an icon to the left of the edit field. - // This shows the user's current action while editing, the page security - // status on https pages, or a globe for other URLs. - class LocationIconView : public views::ImageView { - public: - explicit LocationIconView(const LocationBarView* location_bar); - virtual ~LocationIconView(); - - // Overridden from view. - virtual bool OnMousePressed(const views::MouseEvent& event); - virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); - - private: - ClickHandler click_handler_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(LocationIconView); - }; - - // View used to draw a bubble to the left of the address, containing an icon - // and a label. We use this as a base for the classes that handle the EV - // bubble and tab-to-search UI. - class IconLabelBubbleView : public views::View { + // View used when the user has selected a keyword. + // + // SelectedKeywordView maintains two labels. One label contains the + // complete description of the keyword, the second contains a truncated + // version of the description. The second is used if there is not enough room + // to display the complete description. + class SelectedKeywordView : public views::View { public: - IconLabelBubbleView(const int background_images[], - int contained_image, - const SkColor& color); - virtual ~IconLabelBubbleView(); + explicit SelectedKeywordView(Profile* profile); + virtual ~SelectedKeywordView(); void SetFont(const gfx::Font& font); - void SetLabel(const std::wstring& label); virtual void Paint(gfx::Canvas* canvas); - virtual gfx::Size GetPreferredSize(); - virtual void Layout(); - - protected: - gfx::Size GetNonLabelSize(); - - private: - // For painting the background. - views::HorizontalPainter background_painter_; - - // The contents of the bubble. - views::ImageView image_; - views::Label label_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(IconLabelBubbleView); - }; - - // EVBubbleView displays the EV Bubble. - class EVBubbleView : public IconLabelBubbleView { - public: - EVBubbleView(const int background_images[], - int contained_image, - const SkColor& color, - const LocationBarView* location_bar); - virtual ~EVBubbleView(); - - // Overridden from view. - virtual bool OnMousePressed(const views::MouseEvent& event); - virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); - - private: - ClickHandler click_handler_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(EVBubbleView); - }; - - // SelectedKeywordView displays the tab-to-search UI. - class SelectedKeywordView : public IconLabelBubbleView { - public: - SelectedKeywordView(const int background_images[], - int contained_image, - const SkColor& color, - Profile* profile); - virtual ~SelectedKeywordView(); - - void SetFont(const gfx::Font& font); virtual gfx::Size GetPreferredSize(); virtual gfx::Size GetMinimumSize(); @@ -319,16 +224,18 @@ class LocationBarView : public LocationBar, // deleted out from under us. std::wstring keyword_; - // These labels are never visible. They are used to size the view. One - // label contains the complete description of the keyword, the second - // contains a truncated version of the description, for if there is not - // enough room to display the complete description. + // For painting the background. + views::HorizontalPainter background_painter_; + + // Label containing the complete description. views::Label full_label_; + + // Label containing the partial description. views::Label partial_label_; Profile* profile_; - DISALLOW_IMPLICIT_CONSTRUCTORS(SelectedKeywordView); + DISALLOW_COPY_AND_ASSIGN(SelectedKeywordView); }; // KeywordHintView is used to display a hint to the user when the selected @@ -368,7 +275,96 @@ class LocationBarView : public LocationBar, Profile* profile_; - DISALLOW_IMPLICIT_CONSTRUCTORS(KeywordHintView); + DISALLOW_COPY_AND_ASSIGN(KeywordHintView); + }; + + class ShowInfoBubbleTask; + class ShowFirstRunBubbleTask; + + class LocationBarImageView : public views::ImageView, + public InfoBubbleDelegate { + public: + explicit LocationBarImageView(const BubblePositioner* bubble_positioner); + virtual ~LocationBarImageView(); + + // Overridden from view for the mouse hovering. + virtual void OnMouseMoved(const views::MouseEvent& event); + virtual void OnMouseExited(const views::MouseEvent& event); + virtual bool OnMousePressed(const views::MouseEvent& event) = 0; + + // InfoBubbleDelegate + void InfoBubbleClosing(InfoBubble* info_bubble, bool closed_by_escape); + bool CloseOnEscape() { return true; } + + virtual void ShowInfoBubble() = 0; + + protected: + void ShowInfoBubbleImpl(const std::wstring& text, SkColor text_color); + + private: + friend class ShowInfoBubbleTask; + + // The currently shown info bubble if any. + InfoBubble* info_bubble_; + + // A task used to display the info bubble when the mouse hovers on the + // image. + ShowInfoBubbleTask* show_info_bubble_task_; + + // A positioner used to give the info bubble the correct target bounds. The + // caller maintains ownership of this and must ensure it's kept alive. + const BubblePositioner* bubble_positioner_; + + DISALLOW_COPY_AND_ASSIGN(LocationBarImageView); + }; + + // SecurityImageView is used to display the lock or warning icon when the + // current URL's scheme is https. + // + // If a message has been set with SetInfoBubbleText, it displays an info + // bubble when the mouse hovers on the image. + class SecurityImageView : public LocationBarImageView { + public: + enum Image { + LOCK = 0, + WARNING + }; + + SecurityImageView(const LocationBarView* parent, + Profile* profile, + ToolbarModel* model_, + const BubblePositioner* bubble_positioner); + virtual ~SecurityImageView(); + + // Sets the image that should be displayed. + void SetImageShown(Image image); + + // Overridden from view for the mouse hovering. + virtual bool OnMousePressed(const views::MouseEvent& event); + + void set_profile(Profile* profile) { profile_ = profile; } + + virtual void ShowInfoBubble(); + + private: + // The lock icon shown when using HTTPS. + static SkBitmap* lock_icon_; + + // The warning icon shown when HTTPS is broken. + static SkBitmap* warning_icon_; + + // A task used to display the info bubble when the mouse hovers on the + // image. + ShowInfoBubbleTask* show_info_bubble_task_; + + // The owning LocationBarView. + const LocationBarView* parent_; + + Profile* profile_; + + ToolbarModel* model_; + + DISALLOW_COPY_AND_ASSIGN(SecurityImageView); }; class ContentSettingImageView : public views::ImageView, @@ -376,7 +372,8 @@ class LocationBarView : public LocationBar, public: ContentSettingImageView(ContentSettingsType content_type, const LocationBarView* parent, - Profile* profile); + Profile* profile, + const BubblePositioner* bubble_positioner); virtual ~ContentSettingImageView(); void set_profile(Profile* profile) { profile_ = profile; } @@ -385,7 +382,6 @@ class LocationBarView : public LocationBar, private: // views::ImageView overrides: virtual bool OnMousePressed(const views::MouseEvent& event); - virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); virtual void VisibilityChanged(View* starting_from, bool is_visible); // InfoBubbleDelegate overrides: @@ -404,20 +400,25 @@ class LocationBarView : public LocationBar, // The currently shown info bubble if any. InfoBubble* info_bubble_; + // A positioner used to give the info bubble the correct target bounds. The + // caller maintains ownership of this and must ensure it's kept alive. + const BubblePositioner* bubble_positioner_; + DISALLOW_IMPLICIT_CONSTRUCTORS(ContentSettingImageView); }; typedef std::vector<ContentSettingImageView*> ContentSettingViews; // PageActionImageView is used to display the icon for a given PageAction // and notify the extension when the icon is clicked. - class PageActionImageView : public views::ImageView, + class PageActionImageView : public LocationBarImageView, public ImageLoadingTracker::Observer, public ExtensionContextMenuModel::PopupDelegate, public ExtensionPopup::Observer { public: PageActionImageView(LocationBarView* owner, Profile* profile, - ExtensionAction* page_action); + ExtensionAction* page_action, + const BubblePositioner* bubble_positioner); virtual ~PageActionImageView(); ExtensionAction* page_action() { return page_action_; } @@ -429,9 +430,13 @@ class LocationBarView : public LocationBar, } // Overridden from view. + virtual void OnMouseMoved(const views::MouseEvent& event); virtual bool OnMousePressed(const views::MouseEvent& event); virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); + // Overridden from LocationBarImageView. + virtual void ShowInfoBubble(); + // Overridden from ImageLoadingTracker. virtual void OnImageLoaded( SkBitmap* image, ExtensionResource resource, int index); @@ -492,7 +497,7 @@ class LocationBarView : public LocationBar, // The current popup and the button it came from. NULL if no popup. ExtensionPopup* popup_; - DISALLOW_IMPLICIT_CONSTRUCTORS(PageActionImageView); + DISALLOW_COPY_AND_ASSIGN(PageActionImageView); }; friend class PageActionImageView; @@ -500,30 +505,11 @@ class LocationBarView : public LocationBar, friend class PageActionWithBadgeView; typedef std::vector<PageActionWithBadgeView*> PageActionViews; - class StarView : public views::ImageView, public InfoBubbleDelegate { - public: - explicit StarView(CommandUpdater* command_updater); - virtual ~StarView(); - - // Toggles the star on or off. - void SetToggled(bool on); - - private: - // views::ImageView overrides: - virtual bool GetAccessibleRole(AccessibilityTypes::Role* role); - virtual bool OnMousePressed(const views::MouseEvent& event); - virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); - - // InfoBubbleDelegate overrides: - virtual void InfoBubbleClosing(InfoBubble* info_bubble, - bool closed_by_escape); - virtual bool CloseOnEscape(); - - // The CommandUpdater for the Browser object that owns the location bar. - CommandUpdater* command_updater_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(StarView); - }; + // Both Layout and OnChanged call into this. This updates the contents + // of the 3 views: selected_keyword, keyword_hint and type_search_view. If + // force_layout is true, or one of these views has changed in such a way as + // to necessitate a layout, layout occurs as well. + void DoLayout(bool force_layout); // Returns the height in pixels of the margin at the top of the bar. int TopMargin() const; @@ -539,12 +525,25 @@ class LocationBarView : public LocationBar, // minimum size of the view should be used. bool UsePref(int pref_width, int available_width); + // Returns true if the view needs to be resized. This determines whether the + // min or pref should be used, and returns true if the view is not at that + // size. + bool NeedsResize(View* view, int available_width); + + // Adjusts the keyword hint, selected keyword and type to search views + // based on the contents of the edit. Returns true if something changed that + // necessitates a layout. + bool AdjustHints(int available_width); + // If View fits in the specified region, it is made visible and the // bounds are adjusted appropriately. If the View does not fit, it is // made invisible. void LayoutView(bool leading, views::View* view, int available_width, gfx::Rect* bounds); + // Sets the security icon to display. Note that no repaint is done. + void SetSecurityIcon(ToolbarModel::Icon icon); + // Update the visibility state of the Content Blocked icons to reflect what is // actually blocked on the current page. void RefreshContentSettingViews(); @@ -556,8 +555,16 @@ class LocationBarView : public LocationBar, // PageActions. void RefreshPageActionViews(); - // Sets the visibility of view to new_vis. - void ToggleVisibility(bool new_vis, views::View* view); + // Sets the text that should be displayed in the info label and its associated + // tooltip text. Call with an empty string if the info label should be + // hidden. + void SetInfoText(const std::wstring& text, + ToolbarModel::InfoTextType text_type, + const std::wstring& tooltip_text); + + // Sets the visibility of view to new_vis. Returns whether the visibility + // changed. + bool ToggleVisibility(bool new_vis, views::View* view); #if defined(OS_WIN) // Helper for the Mouse event handlers that does all the real work. @@ -602,20 +609,13 @@ class LocationBarView : public LocationBar, // Font used by edit and some of the hints. gfx::Font font_; - // An icon to the left of the edit field. - LocationIconView location_icon_view_; - - // A bubble displayed for EV HTTPS sites. - EVBubbleView ev_bubble_view_; - // Location_entry view wrapper views::NativeViewHost* location_entry_view_; // The following views are used to provide hints and remind the user as to // what is going in the edit. They are all added a children of the // LocationBarView. At most one is visible at a time. Preference is - // given to the keyword_view_, then hint_view_. - // These autocollapse when the edit needs the room. + // given to the keyword_view_, then hint_view_, then type_to_search_view_. // Shown if the user has selected a keyword. SelectedKeywordView selected_keyword_view_; @@ -623,14 +623,20 @@ class LocationBarView : public LocationBar, // Shown if the selected url has a corresponding keyword. KeywordHintView keyword_hint_view_; + // Shown if the text is not a keyword or url. + views::Label type_to_search_view_; + + // The view that shows the lock/warning when in HTTPS mode. + SecurityImageView security_image_view_; + // The content setting views. ContentSettingViews content_setting_views_; // The page action icon views. PageActionViews page_action_views_; - // The star. - StarView star_view_; + // A label displayed after the lock icon to show some extra information. + views::Label info_label_; // When true, the location bar view is read only and also is has a slightly // different presentation (font size / color). This is used for popups. @@ -639,10 +645,13 @@ class LocationBarView : public LocationBar, // Used schedule a task for the first run info bubble. ScopedRunnableMethodFactory<LocationBarView> first_run_bubble_; + // The positioner that places the omnibox and info bubbles. + const BubblePositioner* bubble_positioner_; + // Storage of string needed for accessibility. std::wstring accessible_name_; - DISALLOW_IMPLICIT_CONSTRUCTORS(LocationBarView); + DISALLOW_COPY_AND_ASSIGN(LocationBarView); }; #endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H_ diff --git a/chrome/browser/views/pinned_contents_info_bubble.cc b/chrome/browser/views/pinned_contents_info_bubble.cc deleted file mode 100644 index 8331db1..0000000 --- a/chrome/browser/views/pinned_contents_info_bubble.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/pinned_contents_info_bubble.h" - -#include "chrome/browser/views/bubble_border.h" - -#if defined(OS_WIN) -// BorderWidget --------------------------------------------------------------- - -void PinnedContentsBorderContents::InitAndGetBounds( - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size, - bool prefer_arrow_on_right, - gfx::Rect* contents_bounds, - gfx::Rect* window_bounds) { - bubble_border_ = new BubbleBorder; - - // Arrow offset is calculated from the middle of the |position_relative_to|. - int offset = position_relative_to.x() + (position_relative_to.width() / 2); - offset -= bubble_anchor_.x(); - - gfx::Insets insets; - bubble_border_->GetInsets(&insets); - offset += kLeftMargin + insets.left() + 1; - bubble_border_->set_arrow_offset(offset); - - BorderContents::InitAndGetBounds( - position_relative_to, contents_size, prefer_arrow_on_right, - contents_bounds, window_bounds); - - // Now move the y position to make sure the bubble contents overlap the view. - window_bounds->Offset(0, -(kTopMargin + 1)); -} - -gfx::Rect PinnedContentsBorderWidget::InitAndGetBounds( - HWND owner, - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size, - bool prefer_arrow_on_right) { - border_contents_ = new PinnedContentsBorderContents(bubble_anchor_); - return BorderWidget::InitAndGetBounds( - owner, position_relative_to, contents_size, - prefer_arrow_on_right); -} -#endif - -// InfoBubble ----------------------------------------------------------------- - -// static -PinnedContentsInfoBubble* PinnedContentsInfoBubble::Show( - views::Window* parent, - const gfx::Rect& position_relative_to, - const gfx::Point& bubble_anchor, - views::View* contents, - InfoBubbleDelegate* delegate) { - PinnedContentsInfoBubble* window = - new PinnedContentsInfoBubble(bubble_anchor); - window->Init(parent, position_relative_to, contents, delegate); - return window; -} - -void PinnedContentsInfoBubble::Init(views::Window* parent, - const gfx::Rect& position_relative_to, - views::View* contents, - InfoBubbleDelegate* delegate) { -// TODO(finnur): This needs to be implemented for other platforms once we -// decide this is the way to go. -#if defined(OS_WIN) - border_.reset(new PinnedContentsBorderWidget(bubble_anchor_)); -#endif - InfoBubble::Init(parent, position_relative_to, contents, delegate); -} diff --git a/chrome/browser/views/pinned_contents_info_bubble.h b/chrome/browser/views/pinned_contents_info_bubble.h deleted file mode 100644 index 92477c0..0000000 --- a/chrome/browser/views/pinned_contents_info_bubble.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_ -#define CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_ - -#include "chrome/browser/views/info_bubble.h" - -// This is a specialization of BorderContents, used to draw a border around -// an InfoBubble that has its contents pinned to a specific location. See -// base class for details. -class PinnedContentsBorderContents : public BorderContents { - public: - explicit PinnedContentsBorderContents(const gfx::Point& bubble_anchor) - : bubble_anchor_(bubble_anchor) {} - - // BorderContents overrides: - virtual void InitAndGetBounds( - const gfx::Rect& position_relative_to, // In screen coordinates - const gfx::Size& contents_size, - bool prefer_arrow_on_right, - gfx::Rect* contents_bounds, // Returned in window coordinates - gfx::Rect* window_bounds); // Returned in screen coordinates - - private: - // The location of the pinned contents (in screen coordinates). - const gfx::Point bubble_anchor_; - - DISALLOW_COPY_AND_ASSIGN(PinnedContentsBorderContents); -}; - -#if defined(OS_WIN) -// The window that surrounds the info bubble. See base class for details. -class PinnedContentsBorderWidget : public BorderWidget { - public: - explicit PinnedContentsBorderWidget(const gfx::Point& bubble_anchor) - : bubble_anchor_(bubble_anchor) {} - virtual ~PinnedContentsBorderWidget() {} - - // BorderWidget overrides: - virtual gfx::Rect InitAndGetBounds(HWND owner, - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size, - bool is_rtl); - - private: - // The location of the pinned contents (in screen coordinates). - const gfx::Point bubble_anchor_; - - DISALLOW_COPY_AND_ASSIGN(PinnedContentsBorderWidget); -}; -#endif - -// A specialization of the InfoBubble. Used to draw an InfoBubble which, in -// addition to having an arrow pointing to where the user clicked, also shifts -// the bubble horizontally to fix it to a specific location. See base class -// for details. -class PinnedContentsInfoBubble : public InfoBubble { - public: - // Shows the InfoBubble (see base class function for details). - // |bubble_anchor| specifies how far horizontally to shift the bubble in - // order to anchor its contents. Once the InfoBubble has been anchored its - // arrow may be pointing to a slightly different |y| location than specified - // in |position_relative_to|. - static PinnedContentsInfoBubble* Show(views::Window* parent, - const gfx::Rect& position_relative_to, - const gfx::Point& bubble_anchor_, - views::View* contents, - InfoBubbleDelegate* delegate); - - private: - explicit PinnedContentsInfoBubble(const gfx::Point& bubble_anchor) - : bubble_anchor_(bubble_anchor) {} - virtual ~PinnedContentsInfoBubble() {} - - // InfoBubble overrides: - virtual void Init(views::Window* parent, - const gfx::Rect& position_relative_to, - views::View* contents, - InfoBubbleDelegate* delegate); - - // The location of the pinned contents (in screen coordinates). - const gfx::Point bubble_anchor_; - - DISALLOW_COPY_AND_ASSIGN(PinnedContentsInfoBubble); -}; - -#endif // CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_ diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index 3521a88..ce26ac7 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -316,7 +316,7 @@ DraggedTabController::DraggedTabController(Tab* source_tab, original_delegate_(NULL), source_tab_(source_tab), source_tabstrip_(source_tabstrip), - source_model_index_(source_tabstrip->GetModelIndexOfTab(source_tab)), + source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)), attached_tabstrip_(source_tabstrip), old_focused_view_(NULL), in_destructor_(false), @@ -508,7 +508,7 @@ void DraggedTabController::InitWindowCreatePoint() { // first_tab based on source_tabstrip_, not attached_tabstrip_. Otherwise, // the window_create_point_ is not in the correct coordinate system. Please // refer to http://crbug.com/6223 comment #15 for detailed information. - Tab* first_tab = source_tabstrip_->GetTabAtTabDataIndex(0); + Tab* first_tab = source_tabstrip_->GetTabAt(0); views::View::ConvertPointToWidget(first_tab, &first_source_tab_point_); UpdateWindowCreatePoint(); } @@ -963,9 +963,8 @@ gfx::Point DraggedTabController::GetDraggedViewPoint( Tab* DraggedTabController::GetTabMatchingDraggedContents( TabStrip* tabstrip) const { - int model_index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_); - return model_index == TabStripModel::kNoTab ? - NULL : tabstrip->GetTabAtModelIndex(model_index); + int index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_); + return index == TabStripModel::kNoTab ? NULL : tabstrip->GetTabAt(index); } bool DraggedTabController::EndDragImpl(EndDragType type) { diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc index f089393..b363cb5 100644 --- a/chrome/browser/views/tabs/tab_renderer.cc +++ b/chrome/browser/views/tabs/tab_renderer.cc @@ -6,7 +6,6 @@ #include <limits> -#include "app/animation_container.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "app/slide_animation.h" @@ -82,15 +81,9 @@ static int loading_animation_frame_count = 0; static int waiting_animation_frame_count = 0; static int waiting_to_loading_frame_count_ratio = 0; -// Used when |render_as_new_tab| is true. -static SkBitmap* new_tab_mask = NULL; -static SkBitmap* new_tab_shadow = NULL; - TabRenderer::TabImage TabRenderer::tab_alpha = {0}; TabRenderer::TabImage TabRenderer::tab_active = {0}; -TabRenderer::TabImage TabRenderer::tab_active_nano = {0}; TabRenderer::TabImage TabRenderer::tab_inactive = {0}; -TabRenderer::TabImage TabRenderer::tab_alpha_nano = {0}; // Max opacity for the mini-tab title change animation. const double kMiniTitleChangeThrobOpacity = 0.75; @@ -212,7 +205,7 @@ class TabCloseButton : public views::ImageButton { } private: - DISALLOW_COPY_AND_ASSIGN(TabCloseButton); + DISALLOW_EVIL_CONSTRUCTORS(TabCloseButton); }; } // namespace @@ -253,7 +246,7 @@ class TabRenderer::FavIconCrashAnimation : public Animation, private: TabRenderer* target_; - DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation); + DISALLOW_EVIL_CONSTRUCTORS(FavIconCrashAnimation); }; //////////////////////////////////////////////////////////////////////////////// @@ -289,10 +282,6 @@ TabRenderer::~TabRenderer() { delete crash_animation_; } -void TabRenderer::SizeToNewTabButtonImages() { - SetBounds(x(), y(), new_tab_shadow->width(), new_tab_shadow->height()); -} - void TabRenderer::ViewHierarchyChanged(bool is_add, View* parent, View* child) { if (parent->GetThemeProvider()) SetThemeProvider(parent->GetThemeProvider()); @@ -418,11 +407,6 @@ void TabRenderer::StopMiniTabTitleAnimation() { mini_title_animation_->Stop(); } -void TabRenderer::SetAnimationContainer(AnimationContainer* container) { - container_ = container; - pulse_animation_->SetContainer(container); -} - void TabRenderer::PaintIcon(gfx::Canvas* canvas) { if (animation_state_ != ANIMATION_NONE) { PaintLoadingAnimation(canvas); @@ -518,15 +502,6 @@ void TabRenderer::OnMouseExited(const views::MouseEvent& e) { // TabRenderer, views::View overrides: void TabRenderer::Paint(gfx::Canvas* canvas) { - if (data_.render_as_new_tab) { - if (UILayoutIsRightToLeft()) { - canvas->TranslateInt(width(), 0); - canvas->ScaleInt(-1, 1); - } - PaintAsNewTab(canvas); - return; - } - // Don't paint if we're narrower than we can render correctly. (This should // only happen during animations). if (width() < GetMinimumUnselectedSize().width() && !mini()) @@ -740,47 +715,45 @@ void TabRenderer::PaintInactiveTabBackground(gfx::Canvas* canvas) { int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? 0 : background_offset_.y(); - if (!data_.app) { - // Draw left edge. Don't draw over the toolbar, as we're not the foreground - // tab. - SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap( - *tab_bg, offset, bg_offset_y, tab_active.l_width, height()); - SkBitmap theme_l = - SkBitmapOperations::CreateMaskedBitmap(tab_l, *tab_alpha.image_l); - canvas->DrawBitmapInt(theme_l, - 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, - 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, - false); - - // Draw right edge. Again, don't draw over the toolbar. - SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg, - offset + width() - tab_active.r_width, bg_offset_y, - tab_active.r_width, height()); - SkBitmap theme_r = - SkBitmapOperations::CreateMaskedBitmap(tab_r, *tab_alpha.image_r); - canvas->DrawBitmapInt(theme_r, - 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap, - width() - theme_r.width(), 0, theme_r.width(), - theme_r.height() - kToolbarOverlap, false); - - // Draw center. Instead of masking out the top portion we simply skip over - // it by incrementing by kDropShadowHeight, since it's a simple rectangle. - // And again, don't draw over the toolbar. - canvas->TileImageInt(*tab_bg, - offset + tab_active.l_width, bg_offset_y + kDropShadowHeight, - tab_active.l_width, kDropShadowHeight, - width() - tab_active.l_width - tab_active.r_width, - height() - kDropShadowHeight - kToolbarOverlap); - - // Now draw the highlights/shadows around the tab edge. - canvas->DrawBitmapInt(*tab_inactive.image_l, 0, 0); - canvas->TileImageInt(*tab_inactive.image_c, - tab_inactive.l_width, 0, - width() - tab_inactive.l_width - tab_inactive.r_width, - height()); - canvas->DrawBitmapInt(*tab_inactive.image_r, - width() - tab_inactive.r_width, 0); - } + // Draw left edge. Don't draw over the toolbar, as we're not the foreground + // tab. + SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap( + *tab_bg, offset, bg_offset_y, tab_active.l_width, height()); + SkBitmap theme_l = + SkBitmapOperations::CreateMaskedBitmap(tab_l, *tab_alpha.image_l); + canvas->DrawBitmapInt(theme_l, + 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, + 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, + false); + + // Draw right edge. Again, don't draw over the toolbar. + SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg, + offset + width() - tab_active.r_width, bg_offset_y, + tab_active.r_width, height()); + SkBitmap theme_r = + SkBitmapOperations::CreateMaskedBitmap(tab_r, *tab_alpha.image_r); + canvas->DrawBitmapInt(theme_r, + 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap, + width() - theme_r.width(), 0, theme_r.width(), + theme_r.height() - kToolbarOverlap, false); + + // Draw center. Instead of masking out the top portion we simply skip over it + // by incrementing by kDropShadowHeight, since it's a simple rectangle. And + // again, don't draw over the toolbar. + canvas->TileImageInt(*tab_bg, + offset + tab_active.l_width, bg_offset_y + kDropShadowHeight, + tab_active.l_width, kDropShadowHeight, + width() - tab_active.l_width - tab_active.r_width, + height() - kDropShadowHeight - kToolbarOverlap); + + // Now draw the highlights/shadows around the tab edge. + canvas->DrawBitmapInt(*tab_inactive.image_l, 0, 0); + canvas->TileImageInt(*tab_inactive.image_c, + tab_inactive.l_width, 0, + width() - tab_inactive.l_width - tab_inactive.r_width, + height()); + canvas->DrawBitmapInt(*tab_inactive.image_r, + width() - tab_inactive.r_width, 0); } void TabRenderer::PaintActiveTabBackground(gfx::Canvas* canvas) { @@ -792,39 +765,33 @@ void TabRenderer::PaintActiveTabBackground(gfx::Canvas* canvas) { SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR); - // App tabs are drawn slightly differently (as nano tabs). - TabImage* tab_image = data_.app ? &tab_active_nano : &tab_active; - TabImage* alpha = data_.app ? &tab_alpha_nano : &tab_alpha; - // Draw left edge. SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap( - *tab_bg, offset, 0, tab_image->l_width, height()); + *tab_bg, offset, 0, tab_active.l_width, height()); SkBitmap theme_l = - SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l); + SkBitmapOperations::CreateMaskedBitmap(tab_l, *tab_alpha.image_l); canvas->DrawBitmapInt(theme_l, 0, 0); // Draw right edge. SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg, - offset + width() - tab_image->r_width, 0, tab_image->r_width, height()); + offset + width() - tab_active.r_width, 0, tab_active.r_width, height()); SkBitmap theme_r = - SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r); - canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, 0); + SkBitmapOperations::CreateMaskedBitmap(tab_r, *tab_alpha.image_r); + canvas->DrawBitmapInt(theme_r, width() - tab_active.r_width, 0); // Draw center. Instead of masking out the top portion we simply skip over it // by incrementing by kDropShadowHeight, since it's a simple rectangle. canvas->TileImageInt(*tab_bg, - offset + tab_image->l_width, - kDropShadowHeight + tab_image->y_offset, - tab_image->l_width, - kDropShadowHeight + tab_image->y_offset, - width() - tab_image->l_width - tab_image->r_width, - height() - kDropShadowHeight - tab_image->y_offset); + offset + tab_active.l_width, kDropShadowHeight, + tab_active.l_width, kDropShadowHeight, + width() - tab_active.l_width - tab_active.r_width, + height() - kDropShadowHeight); // Now draw the highlights/shadows around the tab edge. - canvas->DrawBitmapInt(*tab_image->image_l, 0, 0); - canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, - width() - tab_image->l_width - tab_image->r_width, height()); - canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width, 0); + canvas->DrawBitmapInt(*tab_active.image_l, 0, 0); + canvas->TileImageInt(*tab_active.image_c, tab_active.l_width, 0, + width() - tab_active.l_width - tab_active.r_width, height()); + canvas->DrawBitmapInt(*tab_active.image_r, width() - tab_active.r_width, 0); } void TabRenderer::PaintLoadingAnimation(gfx::Canvas* canvas) { @@ -852,47 +819,6 @@ void TabRenderer::PaintLoadingAnimation(gfx::Canvas* canvas) { false); } -void TabRenderer::PaintAsNewTab(gfx::Canvas* canvas) { - bool is_otr = data_.off_the_record; - - // The tab image needs to be lined up with the background image - // so that it feels partially transparent. These offsets represent the tab - // position within the frame background image. - int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) + - background_offset_.x(); - - int tab_id; - if (GetWidget() && - GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) { - tab_id = IDR_THEME_TAB_BACKGROUND_V; - } else { - tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : - IDR_THEME_TAB_BACKGROUND; - } - - SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id); - - // If the theme is providing a custom background image, then its top edge - // should be at the top of the tab. Otherwise, we assume that the background - // image is a composited foreground + frame image. - int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? - 0 : background_offset_.y(); - - SkBitmap image = SkBitmapOperations::CreateTiledBitmap( - *tab_bg, offset, bg_offset_y, new_tab_mask->width(), - new_tab_mask->height()); - image = SkBitmapOperations::CreateMaskedBitmap(image, *new_tab_mask); - canvas->DrawBitmapInt(image, - 0, 0, image.width(), image.height(), - 0, 0, image.width(), image.height(), - false); - - canvas->DrawBitmapInt(*new_tab_shadow, - 0, 0, new_tab_shadow->width(), new_tab_shadow->height(), - 0, 0, new_tab_shadow->width(), new_tab_shadow->height(), - false); -} - int TabRenderer::IconCapacity() const { if (height() < GetMinimumUnselectedSize().height()) return 0; @@ -918,9 +844,6 @@ bool TabRenderer::ShouldShowCloseBox() const { } double TabRenderer::GetThrobValue() { - if (data_.alpha != 1) - return data_.alpha; - if (pulse_animation_->IsAnimating()) return pulse_animation_->GetCurrentValue() * kHoverOpacity; @@ -969,38 +892,21 @@ void TabRenderer::LoadTabImages() { tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT); tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT); - tab_alpha_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_LEFT); - tab_alpha_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_RIGHT); - tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT); tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER); tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT); tab_active.l_width = tab_active.image_l->width(); tab_active.r_width = tab_active.image_r->width(); - // This is high much taller *visually* the regular tab is compared to the - // nano tabs. The images are the same height, this is really just the - // difference in whitespace above the tab image. - const int kMiniTabDiffHeight = 14; - - tab_active_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_LEFT); - tab_active_nano.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_CENTER); - tab_active_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_RIGHT); - tab_active_nano.l_width = tab_active_nano.image_l->width(); - tab_active_nano.r_width = tab_active_nano.image_r->width(); - tab_active_nano.y_offset = kMiniTabDiffHeight; - tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); + tab_inactive.l_width = tab_inactive.image_l->width(); tab_inactive.r_width = tab_inactive.image_r->width(); loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER); waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING); - - new_tab_mask = rb.GetBitmapNamed(IDR_TAB_ALPHA_NEW_TAB); - new_tab_shadow = rb.GetBitmapNamed(IDR_TAB_NEW_TAB_SHADOW); } void TabRenderer::SetBlocked(bool blocked) { diff --git a/chrome/browser/views/tabs/tab_renderer.h b/chrome/browser/views/tabs/tab_renderer.h index fc01a7a..2e309c6 100644 --- a/chrome/browser/views/tabs/tab_renderer.h +++ b/chrome/browser/views/tabs/tab_renderer.h @@ -1,19 +1,17 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2008 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_VIEWS_TABS_TAB_RENDERER_H_ -#define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_ +#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H__ +#define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H__ #include "app/animation.h" -#include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/string16.h" #include "gfx/point.h" #include "views/controls/button/image_button.h" #include "views/view.h" -class AnimationContainer; class SlideAnimation; class TabContents; class ThrobAnimation; @@ -39,11 +37,6 @@ class TabRenderer : public views::View, TabRenderer(); virtual ~TabRenderer(); - // Sizes the renderer to the size of the new tab images. This is used - // during the new tab animation. See TabStrip's description of AnimationType - // for details. - void SizeToNewTabButtonImages(); - // Overridden from views: void ViewHierarchyChanged(bool is_add, View* parent, View* child); ThemeProvider* GetThemeProvider(); @@ -62,26 +55,10 @@ class TabRenderer : public views::View, void set_mini(bool mini) { data_.mini = mini; } bool mini() const { return data_.mini; } - // Sets the mini-state of the tab. - void set_app(bool app) { data_.app = app; } - bool app() const { return data_.app; } - // Sets the phantom state of the tab. void set_phantom(bool phantom) { data_.phantom = phantom; } bool phantom() const { return data_.phantom; } - // Used during new tab animation to force the tab to render a new tab like - // animation. - void set_render_as_new_tab(bool value) { data_.render_as_new_tab = value; } - - // Sets the alpha value to render the tab at. This is used during the new - // tab animation. - void set_alpha(double value) { data_.alpha = value; } - - // Forces the tab to render unselected even though it is selected. - void set_render_unselected(bool value) { data_.render_unselected = value; } - bool render_unselected() const { return data_.render_unselected; } - // Are we in the process of animating a mini tab state change on this tab? void set_animating_mini_change(bool value); @@ -116,9 +93,6 @@ class TabRenderer : public views::View, theme_provider_ = provider; } - // Sets the container all animations run from. - void SetAnimationContainer(AnimationContainer* container); - // Paints the icon. Most of the time you'll want to invoke Paint directly, but // in certain situations this invoked outside of Paint. void PaintIcon(gfx::Canvas* canvas); @@ -184,7 +158,6 @@ class TabRenderer : public views::View, void PaintInactiveTabBackground(gfx::Canvas* canvas); void PaintActiveTabBackground(gfx::Canvas* canvas); void PaintLoadingAnimation(gfx::Canvas* canvas); - void PaintAsNewTab(gfx::Canvas* canvas); // Returns the number of favicon-size elements that can fit in the tab's // current size. @@ -238,11 +211,7 @@ class TabRenderer : public views::View, mini(false), blocked(false), animating_mini_change(false), - phantom(false), - app(false), - render_as_new_tab(false), - render_unselected(false), - alpha(1) { + phantom(false) { } SkBitmap favicon; @@ -255,10 +224,6 @@ class TabRenderer : public views::View, bool blocked; bool animating_mini_change; bool phantom; - bool app; - bool render_as_new_tab; - bool render_unselected; - double alpha; }; TabData data_; @@ -268,13 +233,10 @@ class TabRenderer : public views::View, SkBitmap* image_r; int l_width; int r_width; - int y_offset; }; static TabImage tab_active; - static TabImage tab_active_nano; static TabImage tab_inactive; static TabImage tab_alpha; - static TabImage tab_alpha_nano; // Whether we're showing the icon. It is cached so that we can detect when it // changes and layout appropriately. @@ -298,12 +260,10 @@ class TabRenderer : public views::View, ThemeProvider* theme_provider_; - scoped_refptr<AnimationContainer> container_; - static void InitClass(); static bool initialized_; - DISALLOW_COPY_AND_ASSIGN(TabRenderer); + DISALLOW_EVIL_CONSTRUCTORS(TabRenderer); }; -#endif // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_ +#endif // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H__ diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index a28ff52b..1a9edb3 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -4,14 +4,12 @@ #include "chrome/browser/views/tabs/tab_strip.h" -#include "app/animation_container.h" #include "app/drag_drop_types.h" #include "app/l10n_util.h" #include "app/os_exchange_data.h" #include "app/resource_bundle.h" #include "app/slide_animation.h" #include "base/command_line.h" -#include "base/compiler_specific.h" #include "base/stl_util-inl.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_theme_provider.h" @@ -27,7 +25,6 @@ #include "chrome/browser/views/tabs/tab.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" -#include "chrome/common/url_constants.h" #include "gfx/canvas.h" #include "gfx/path.h" #include "gfx/size.h" @@ -57,21 +54,10 @@ using views::DropTargetEvent; -// Duration of the first step in a new tab animation. -static const int kNewTabDurationMs = 50; - -// Duration of the last step in the new tab animation. -static const int kNewTab3DurationMs = 100; - -// Amount in pixels newly inserted tabs go past target bounds before animating -// to final position. This is used for ANIMATION_NEW_TAB_2. -static const int kNewTabOvershoot = 9; - -// Amount in pixels the newly inserted tab is clipped against the previous -// tab while animating. This is used to make sure the user doesn't see the -// newly inserted tab behind other tabs and so that its shadow isn't visible -// until the user can actually see the tab. -static const int kNetTabSelectedOffset = -13; +static const int kDefaultAnimationDurationMs = 200; +static const int kResizeLayoutAnimationDurationMs = 200; +static const int kReorderAnimationDurationMs = 200; +static const int kMiniTabAnimationDurationMs = 200; static const int kNewTabButtonHOffset = -5; static const int kNewTabButtonVOffset = 5; @@ -95,27 +81,6 @@ static inline int Round(double x) { return static_cast<int>(floor(x + 0.5)); } -namespace { - -// Animation delegate used during new tab animation step 2 to vary the alpha of -// the tab. -class NewTabAlphaDelegate - : public views::BoundsAnimator::OwnedAnimationDelegate { - public: - explicit NewTabAlphaDelegate(Tab* tab) : tab_(tab) { - } - - virtual void AnimationProgressed(const Animation* animation) { - if (tab_->render_unselected()) - tab_->set_alpha(animation->GetCurrentValue()); - } - - private: - Tab* tab_; - - DISALLOW_COPY_AND_ASSIGN(NewTabAlphaDelegate); -}; - /////////////////////////////////////////////////////////////////////////////// // NewTabButton // @@ -159,44 +124,292 @@ class NewTabButton : public views::ImageButton { DISALLOW_COPY_AND_ASSIGN(NewTabButton); }; -} // namespace - -// AnimationDelegate used when removing a tab. Does the necessary cleanup when -// done. -class TabStrip::RemoveTabDelegate - : public views::BoundsAnimator::OwnedAnimationDelegate { +/////////////////////////////////////////////////////////////////////////////// +// +// TabAnimation +// +// A base class for all TabStrip animations. +// +class TabStrip::TabAnimation : public AnimationDelegate { public: - RemoveTabDelegate(TabStrip* tab_strip, Tab* tab) - : tabstrip_(tab_strip), - tab_(tab) { + friend class TabStrip; + + // Possible types of animation. + enum Type { + INSERT, + REMOVE, + MOVE, + RESIZE, + MINI, + MINI_MOVE + }; + + TabAnimation(TabStrip* tabstrip, Type type) + : tabstrip_(tabstrip), + animation_(this), + start_selected_width_(0), + start_unselected_width_(0), + end_selected_width_(0), + end_unselected_width_(0), + layout_on_completion_(false), + type_(type) { + } + virtual ~TabAnimation() {} + + Type type() const { return type_; } + + void Start() { + animation_.SetSlideDuration(GetDuration()); + animation_.SetTweenType(SlideAnimation::EASE_OUT); + if (!animation_.IsShowing()) { + animation_.Reset(); + animation_.Show(); + } + } + + void Stop() { + animation_.Stop(); + } + + void set_layout_on_completion(bool layout_on_completion) { + layout_on_completion_ = layout_on_completion; + } + + // Retrieves the width for the Tab at the specified index if an animation is + // active. + static double GetCurrentTabWidth(TabStrip* tabstrip, + TabStrip::TabAnimation* animation, + int index) { + Tab* tab = tabstrip->GetTabAt(index); + double tab_width; + if (tab->mini()) { + tab_width = Tab::GetMiniWidth(); + } else { + double unselected, selected; + tabstrip->GetCurrentTabWidths(&unselected, &selected); + tab_width = tab->IsSelected() ? selected : unselected; + } + if (animation) { + double specified_tab_width = animation->GetWidthForTab(index); + if (specified_tab_width != -1) + tab_width = specified_tab_width; + } + return tab_width; + } + + // Overridden from AnimationDelegate: + virtual void AnimationProgressed(const Animation* animation) { + tabstrip_->AnimationLayout(end_unselected_width_); } virtual void AnimationEnded(const Animation* animation) { - CompleteRemove(); + tabstrip_->FinishAnimation(this, layout_on_completion_); + // This object is destroyed now, so we can't do anything else after this. } virtual void AnimationCanceled(const Animation* animation) { - // We can be canceled for two interesting reasons: - // . The tab we reference was dragged back into the tab strip. In this case - // we don't want to remove the tab (closing is false). - // . The drag was completed before the animation completed - // (DestroyDraggedSourceTab). In this case we need to remove the tab - // (closing is true). - if (tab_->closing()) - CompleteRemove(); + AnimationEnded(animation); + } + + // Returns the gap before the tab at the specified index. Subclass if during + // an animation you need to insert a gap before a tab. + virtual double GetGapWidth(int index) { + return 0; + } + + protected: + // Returns the duration of the animation. + virtual int GetDuration() const { + return kDefaultAnimationDurationMs; + } + + // Subclasses override to return the width of the Tab at the specified index + // at the current animation frame. -1 indicates the default width should be + // used for the Tab. + virtual double GetWidthForTab(int index) const { + return -1; // Use default. + } + + // Figure out the desired start and end widths for the specified pre- and + // post- animation tab counts. + void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count, + int start_mini_count, + int end_mini_count) { + tabstrip_->GetDesiredTabWidths(start_tab_count, start_mini_count, + &start_unselected_width_, + &start_selected_width_); + double standard_tab_width = + static_cast<double>(TabRenderer::GetStandardSize().width()); + if (start_tab_count < end_tab_count && + start_unselected_width_ < standard_tab_width) { + double minimum_tab_width = + static_cast<double>(TabRenderer::GetMinimumUnselectedSize().width()); + start_unselected_width_ -= minimum_tab_width / start_tab_count; + } + tabstrip_->GenerateIdealBounds(); + tabstrip_->GetDesiredTabWidths(end_tab_count, end_mini_count, + &end_unselected_width_, + &end_selected_width_); } + TabStrip* tabstrip_; + SlideAnimation animation_; + + double start_selected_width_; + double start_unselected_width_; + double end_selected_width_; + double end_unselected_width_; + private: - void CompleteRemove() { - if (!tab_->closing()) { - // The tab was added back yet we weren't canceled. This shouldn't happen. - NOTREACHED(); - return; + // True if a complete re-layout is required upon completion of the animation. + // Subclasses set this if they don't perform a complete layout + // themselves and canceling the animation may leave the strip in an + // inconsistent state. + bool layout_on_completion_; + + const Type type_; + + DISALLOW_COPY_AND_ASSIGN(TabAnimation); +}; + +/////////////////////////////////////////////////////////////////////////////// + +// Handles insertion of a Tab at |index|. +class TabStrip::InsertTabAnimation : public TabStrip::TabAnimation { + public: + explicit InsertTabAnimation(TabStrip* tabstrip, int index) + : TabAnimation(tabstrip, INSERT), + index_(index) { + int tab_count = tabstrip->GetTabCount(); + int end_mini_count = tabstrip->GetMiniTabCount(); + int start_mini_count = end_mini_count; + if (index < end_mini_count) + start_mini_count--; + GenerateStartAndEndWidths(tab_count - 1, tab_count, start_mini_count, + end_mini_count); + } + virtual ~InsertTabAnimation() {} + + protected: + // Overridden from TabStrip::TabAnimation: + virtual double GetWidthForTab(int index) const { + if (index == index_) { + bool is_selected = tabstrip_->model()->selected_index() == index; + double start_width, target_width; + if (index < tabstrip_->GetMiniTabCount()) { + start_width = Tab::GetMinimumSelectedSize().width(); + target_width = Tab::GetMiniWidth(); + } else { + target_width = + is_selected ? end_unselected_width_ : end_selected_width_; + start_width = + is_selected ? Tab::GetMinimumSelectedSize().width() : + Tab::GetMinimumUnselectedSize().width(); + } + double delta = target_width - start_width; + if (delta > 0) + return start_width + (delta * animation_.GetCurrentValue()); + return start_width; + } + + if (tabstrip_->GetTabAt(index)->mini()) + return Tab::GetMiniWidth(); + + if (tabstrip_->GetTabAt(index)->IsSelected()) { + double delta = end_selected_width_ - start_selected_width_; + return start_selected_width_ + (delta * animation_.GetCurrentValue()); + } + + double delta = end_unselected_width_ - start_unselected_width_; + return start_unselected_width_ + (delta * animation_.GetCurrentValue()); + } + + private: + int index_; + + DISALLOW_COPY_AND_ASSIGN(InsertTabAnimation); +}; + +/////////////////////////////////////////////////////////////////////////////// + +// Handles removal of a Tab from |index| +class TabStrip::RemoveTabAnimation : public TabStrip::TabAnimation { + public: + RemoveTabAnimation(TabStrip* tabstrip, int index, TabContents* contents) + : TabAnimation(tabstrip, REMOVE), + index_(index) { + int tab_count = tabstrip->GetTabCount(); + int start_mini_count = tabstrip->GetMiniTabCount(); + int end_mini_count = start_mini_count; + if (index < start_mini_count) + end_mini_count--; + GenerateStartAndEndWidths(tab_count, tab_count - 1, start_mini_count, + end_mini_count); + // If the last non-mini-tab is being removed we force a layout on + // completion. This is necessary as the value returned by GetTabHOffset + // changes once the tab is actually removed (which happens at the end of + // the animation), and unless we layout GetTabHOffset won't be called after + // the removal. + // We do the same when the last mini-tab is being removed for the same + // reason. + set_layout_on_completion(start_mini_count > 0 && + (end_mini_count == 0 || + (start_mini_count == end_mini_count && + tab_count == start_mini_count + 1))); + } + + // Returns the index of the tab being removed. + int index() const { return index_; } + + virtual ~RemoveTabAnimation() { + } + + protected: + // Overridden from TabStrip::TabAnimation: + virtual double GetWidthForTab(int index) const { + Tab* tab = tabstrip_->GetTabAt(index); + if (index == index_) { + // The tab(s) being removed are gradually shrunken depending on the state + // of the animation. + // Removed animated Tabs are never selected. + if (tab->mini()) { + return animation_.CurrentValueBetween(Tab::GetMiniWidth(), + -kTabHOffset); + } + + double start_width = start_unselected_width_; + // Make sure target_width is at least abs(kTabHOffset), otherwise if + // less than kTabHOffset during layout tabs get negatively offset. + double target_width = + std::max(abs(kTabHOffset), + Tab::GetMinimumUnselectedSize().width() + kTabHOffset); + return animation_.CurrentValueBetween(start_width, target_width); + } + + if (tab->mini()) + return Tab::GetMiniWidth(); + + if (tabstrip_->available_width_for_tabs_ != -1 && + index_ != tabstrip_->GetTabCount() - 1) { + return TabStrip::TabAnimation::GetWidthForTab(index); + } + // All other tabs are sized according to the start/end widths specified at + // the start of the animation. + if (tab->IsSelected()) { + double delta = end_selected_width_ - start_selected_width_; + return start_selected_width_ + (delta * animation_.GetCurrentValue()); } - tabstrip_->RemoveTab(tab_); + double delta = end_unselected_width_ - start_unselected_width_; + return start_unselected_width_ + (delta * animation_.GetCurrentValue()); + } + + virtual void AnimationEnded(const Animation* animation) { + tabstrip_->RemoveTabAt(index_); HighlightCloseButton(); + TabStrip::TabAnimation::AnimationEnded(animation); } + private: // When the animation completes, we send the Container a message to simulate // a mouse moved event at the current mouse position. This tickles the Tab // the mouse is currently over to show the "hot" state of the close button. @@ -226,10 +439,293 @@ class TabStrip::RemoveTabDelegate #endif } - TabStrip* tabstrip_; + int index_; + + DISALLOW_COPY_AND_ASSIGN(RemoveTabAnimation); +}; + +/////////////////////////////////////////////////////////////////////////////// + +// Handles the movement of a Tab from one position to another. +class TabStrip::MoveTabAnimation : public TabStrip::TabAnimation { + public: + MoveTabAnimation(TabStrip* tabstrip, int tab_a_index, int tab_b_index) + : TabAnimation(tabstrip, MOVE), + start_tab_a_bounds_(tabstrip_->GetIdealBounds(tab_b_index)), + start_tab_b_bounds_(tabstrip_->GetIdealBounds(tab_a_index)) { + tab_a_ = tabstrip_->GetTabAt(tab_a_index); + tab_b_ = tabstrip_->GetTabAt(tab_b_index); + + // Since we don't do a full TabStrip re-layout, we need to force a full + // layout upon completion since we're not guaranteed to be in a good state + // if for example the animation is canceled. + set_layout_on_completion(true); + } + virtual ~MoveTabAnimation() {} + + // Overridden from AnimationDelegate: + virtual void AnimationProgressed(const Animation* animation) { + // Position Tab A + double distance = start_tab_b_bounds_.x() - start_tab_a_bounds_.x(); + double delta = distance * animation_.GetCurrentValue(); + double new_x = start_tab_a_bounds_.x() + delta; + tab_a_->SetBounds(Round(new_x), tab_a_->y(), tab_a_->width(), + tab_a_->height()); + + // Position Tab B + distance = start_tab_a_bounds_.x() - start_tab_b_bounds_.x(); + delta = distance * animation_.GetCurrentValue(); + new_x = start_tab_b_bounds_.x() + delta; + tab_b_->SetBounds(Round(new_x), tab_b_->y(), tab_b_->width(), + tab_b_->height()); + + tabstrip_->SchedulePaint(); + } + + protected: + // Overridden from TabStrip::TabAnimation: + virtual int GetDuration() const { return kReorderAnimationDurationMs; } + + private: + // The two tabs being exchanged. + Tab* tab_a_; + Tab* tab_b_; + + // ...and their bounds. + gfx::Rect start_tab_a_bounds_; + gfx::Rect start_tab_b_bounds_; + + DISALLOW_COPY_AND_ASSIGN(MoveTabAnimation); +}; + +/////////////////////////////////////////////////////////////////////////////// + +// Handles the animated resize layout of the entire TabStrip from one width +// to another. +class TabStrip::ResizeLayoutAnimation : public TabStrip::TabAnimation { + public: + explicit ResizeLayoutAnimation(TabStrip* tabstrip) + : TabAnimation(tabstrip, RESIZE) { + int tab_count = tabstrip->GetTabCount(); + int mini_tab_count = tabstrip->GetMiniTabCount(); + GenerateStartAndEndWidths(tab_count, tab_count, mini_tab_count, + mini_tab_count); + InitStartState(); + } + virtual ~ResizeLayoutAnimation() { + } + + // Overridden from AnimationDelegate: + virtual void AnimationEnded(const Animation* animation) { + tabstrip_->needs_resize_layout_ = false; + TabStrip::TabAnimation::AnimationEnded(animation); + } + + protected: + // Overridden from TabStrip::TabAnimation: + virtual int GetDuration() const { + return kResizeLayoutAnimationDurationMs; + } + + virtual double GetWidthForTab(int index) const { + Tab* tab = tabstrip_->GetTabAt(index); + if (tab->mini()) + return Tab::GetMiniWidth(); + + if (tab->IsSelected()) { + return animation_.CurrentValueBetween(start_selected_width_, + end_selected_width_); + } + + return animation_.CurrentValueBetween(start_unselected_width_, + end_unselected_width_); + } + + private: + // We need to start from the current widths of the Tabs as they were last + // laid out, _not_ the last known good state, which is what'll be done if we + // don't measure the Tab sizes here and just go with the default TabAnimation + // behavior... + void InitStartState() { + for (int i = 0; i < tabstrip_->GetTabCount(); ++i) { + Tab* current_tab = tabstrip_->GetTabAt(i); + if (!current_tab->mini()) { + if (current_tab->IsSelected()) { + start_selected_width_ = current_tab->width(); + } else { + start_unselected_width_ = current_tab->width(); + } + } + } + } + + DISALLOW_COPY_AND_ASSIGN(ResizeLayoutAnimation); +}; + +// Handles a tabs mini-state changing while the tab does not change position +// in the model. +class TabStrip::MiniTabAnimation : public TabStrip::TabAnimation { + public: + explicit MiniTabAnimation(TabStrip* tabstrip, int index) + : TabAnimation(tabstrip, MINI), + index_(index) { + int tab_count = tabstrip->GetTabCount(); + int start_mini_count = tabstrip->GetMiniTabCount(); + int end_mini_count = start_mini_count; + if (tabstrip->GetTabAt(index)->mini()) + start_mini_count--; + else + start_mini_count++; + tabstrip_->GetTabAt(index)->set_animating_mini_change(true); + GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count, + end_mini_count); + } + + protected: + // Overridden from TabStrip::TabAnimation: + virtual int GetDuration() const { + return kMiniTabAnimationDurationMs; + } + + virtual double GetWidthForTab(int index) const { + Tab* tab = tabstrip_->GetTabAt(index); + + if (index == index_) { + if (tab->mini()) { + return animation_.CurrentValueBetween( + start_selected_width_, + static_cast<double>(Tab::GetMiniWidth())); + } else { + return animation_.CurrentValueBetween( + static_cast<double>(Tab::GetMiniWidth()), + end_selected_width_); + } + } else if (tab->mini()) { + return Tab::GetMiniWidth(); + } + + if (tab->IsSelected()) { + return animation_.CurrentValueBetween(start_selected_width_, + end_selected_width_); + } + + return animation_.CurrentValueBetween(start_unselected_width_, + end_unselected_width_); + } + + private: + // Index of the tab whose mini state changed. + int index_; + + DISALLOW_COPY_AND_ASSIGN(MiniTabAnimation); +}; + +//////////////////////////////////////////////////////////////////////////////// + +// Handles the animation when a tabs mini state changes and the tab moves as a +// result. +class TabStrip::MiniMoveAnimation : public TabStrip::TabAnimation { + public: + explicit MiniMoveAnimation(TabStrip* tabstrip, + int from_index, + int to_index, + const gfx::Rect& start_bounds) + : TabAnimation(tabstrip, MINI_MOVE), + tab_(tabstrip->GetTabAt(to_index)), + start_bounds_(start_bounds), + from_index_(from_index), + to_index_(to_index) { + int tab_count = tabstrip->GetTabCount(); + int start_mini_count = tabstrip->GetMiniTabCount(); + int end_mini_count = start_mini_count; + if (tabstrip->GetTabAt(to_index)->mini()) + start_mini_count--; + else + start_mini_count++; + GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count, + end_mini_count); + target_bounds_ = tabstrip->GetIdealBounds(to_index); + tab_->set_animating_mini_change(true); + } + + // Overridden from AnimationDelegate: + virtual void AnimationProgressed(const Animation* animation) { + // Do the normal layout. + TabAnimation::AnimationProgressed(animation); + + // Then special case the position of the tab being moved. + int x = animation_.CurrentValueBetween(start_bounds_.x(), + target_bounds_.x()); + int width = animation_.CurrentValueBetween(start_bounds_.width(), + target_bounds_.width()); + gfx::Rect tab_bounds(x, start_bounds_.y(), width, + start_bounds_.height()); + tab_->SetBounds(tab_bounds); + } + + virtual void AnimationEnded(const Animation* animation) { + tabstrip_->needs_resize_layout_ = false; + TabStrip::TabAnimation::AnimationEnded(animation); + } + + virtual double GetGapWidth(int index) { + if (to_index_ < from_index_) { + // The tab was mini. + if (index == to_index_) { + double current_size = + animation_.CurrentValueBetween(0, target_bounds_.width()); + if (current_size < -kTabHOffset) + return -(current_size + kTabHOffset); + } else if (index == from_index_ + 1) { + return animation_.CurrentValueBetween(start_bounds_.width(), 0); + } + } else { + // The tab was made a normal tab. + if (index == from_index_) { + return animation_.CurrentValueBetween(Tab::GetMiniWidth() + + kTabHOffset, 0); + } + } + return 0; + } + + protected: + // Overridden from TabStrip::TabAnimation: + virtual int GetDuration() const { return kReorderAnimationDurationMs; } + + virtual double GetWidthForTab(int index) const { + Tab* tab = tabstrip_->GetTabAt(index); + + if (index == to_index_) + return animation_.CurrentValueBetween(0, target_bounds_.width()); + + if (tab->mini()) + return Tab::GetMiniWidth(); + + if (tab->IsSelected()) { + return animation_.CurrentValueBetween(start_selected_width_, + end_selected_width_); + } + + return animation_.CurrentValueBetween(start_unselected_width_, + end_unselected_width_); + } + + private: + // The tab being moved. Tab* tab_; - DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate); + // Initial bounds of tab_. + gfx::Rect start_bounds_; + + // Target bounds. + gfx::Rect target_bounds_; + + // Start and end indices of the tab. + int from_index_; + int to_index_; + + DISALLOW_COPY_AND_ASSIGN(MiniMoveAnimation); }; /////////////////////////////////////////////////////////////////////////////// @@ -245,14 +741,13 @@ TabStrip::TabStrip(TabStripModel* model) needs_resize_layout_(false), current_unselected_width_(Tab::GetStandardSize().width()), current_selected_width_(Tab::GetStandardSize().width()), - available_width_for_tabs_(-1), - animation_container_(new AnimationContainer()), - ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)), - animation_type_(ANIMATION_DEFAULT) { + available_width_for_tabs_(-1) { Init(); } TabStrip::~TabStrip() { + active_animation_.reset(NULL); + // TODO(beng): (1031854) Restore this line once XPFrame/VistaFrame are dead. // model_->RemoveObserver(this); @@ -280,34 +775,36 @@ void TabStrip::DestroyDragController() { void TabStrip::DestroyDraggedSourceTab(Tab* tab) { // We could be running an animation that references this Tab. - StopAnimating(true); - + if (active_animation_.get()) + active_animation_->Stop(); // Make sure we leave the tab_data_ vector in a consistent state, otherwise // we'll be pointing to tabs that have been deleted and removed from the // child view list. - int tab_data_index = TabDataIndexOfTab(tab); - if (tab_data_index != -1) { - if (!model_->closing_all()) - NOTREACHED() << "Leaving in an inconsistent state!"; - tab_data_.erase(tab_data_.begin() + tab_data_index); + std::vector<TabData>::iterator it = tab_data_.begin(); + for (; it != tab_data_.end(); ++it) { + if (it->tab == tab) { + if (!model_->closing_all()) + NOTREACHED() << "Leaving in an inconsistent state!"; + tab_data_.erase(it); + break; + } } - + tab->GetParent()->RemoveChildView(tab); delete tab; - // Force a layout here, because if we've just quickly drag detached a Tab, // the stopping of the active animation above may have left the TabStrip in a // bad (visual) state. Layout(); } -gfx::Rect TabStrip::GetIdealBounds(int tab_data_index) { - DCHECK_GE(tab_data_index, 0); - DCHECK_LT(tab_data_index, GetTabCount()); - return tab_data_[tab_data_index].ideal_bounds; +gfx::Rect TabStrip::GetIdealBounds(int index) { + DCHECK_GE(index, 0); + DCHECK_LT(index, GetTabCount()); + return tab_data_.at(index).ideal_bounds; } Tab* TabStrip::GetSelectedTab() const { - return GetTabAtModelIndex(model()->selected_index()); + return GetTabAtAdjustForAnimation(model()->selected_index()); } void TabStrip::InitTabStripButtons() { @@ -339,7 +836,7 @@ int TabStrip::GetPreferredHeight() { void TabStrip::SetBackgroundOffset(const gfx::Point& offset) { int tab_count = GetTabCount(); for (int i = 0; i < tab_count; ++i) - GetTabAtTabDataIndex(i)->SetBackgroundOffset(offset); + GetTabAt(i)->SetBackgroundOffset(offset); } bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) { @@ -374,10 +871,12 @@ bool TabStrip::IsDragSessionActive() const { } void TabStrip::UpdateLoadingAnimations() { - for (int i = 0, model_index = 0; i < GetTabCount(); ++i) { - Tab* current_tab = GetTabAtTabDataIndex(i); - if (!current_tab->closing()) { - TabContents* contents = model_->GetTabContentsAt(model_index); + for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { + Tab* current_tab = GetTabAt(i); + if (current_tab->closing()) { + --index; + } else { + TabContents* contents = model_->GetTabContentsAt(index); if (!contents || !contents->is_loading()) { current_tab->ValidateLoadingAnimation(Tab::ANIMATION_NONE); } else if (contents->waiting_for_response()) { @@ -385,13 +884,12 @@ void TabStrip::UpdateLoadingAnimations() { } else { current_tab->ValidateLoadingAnimation(Tab::ANIMATION_LOADING); } - model_index++; } } } bool TabStrip::IsAnimating() const { - return bounds_animator_.IsAnimating() || new_tab_timer_.IsRunning(); + return active_animation_.get() != NULL; } TabStrip* TabStrip::AsTabStrip() { @@ -403,7 +901,6 @@ TabStrip* TabStrip::AsTabStrip() { void TabStrip::PaintChildren(gfx::Canvas* canvas) { // Tabs are painted in reverse order, so they stack to the left. - int tab_count = GetTabCount(); // Phantom tabs appear behind all other tabs and are rendered first. To make // them slightly transparent we render them to a different layer. @@ -413,8 +910,8 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) { canvas->saveLayerAlpha(&bounds, kPhantomTabAlpha, SkCanvas::kARGB_ClipLayer_SaveFlag); canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); - for (int i = tab_count - 1; i >= 0; --i) { - Tab* tab = GetTabAtTabDataIndex(i); + for (int i = GetTabCount() - 1; i >= 0; --i) { + Tab* tab = GetTabAt(i); if (tab->phantom()) tab->ProcessPaint(canvas); } @@ -423,8 +920,8 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) { canvas->saveLayerAlpha(&bounds, kPhantomTabIconAlpha, SkCanvas::kARGB_ClipLayer_SaveFlag); canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); - for (int i = tab_count - 1; i >= 0; --i) { - Tab* tab = GetTabAtTabDataIndex(i); + for (int i = GetTabCount() - 1; i >= 0; --i) { + Tab* tab = GetTabAt(i); if (tab->phantom()) { canvas->save(); canvas->ClipRectInt(tab->MirroredX(), tab->y(), tab->width(), @@ -439,27 +936,14 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) { Tab* selected_tab = NULL; - for (int i = tab_count - 1; i >= 0; --i) { - Tab* tab = GetTabAtTabDataIndex(i); + for (int i = GetTabCount() - 1; i >= 0; --i) { + Tab* tab = GetTabAt(i); // We must ask the _Tab's_ model, not ourselves, because in some situations // the model will be different to this object, e.g. when a Tab is being // removed after its TabContents has been destroyed. if (!tab->phantom()) { if (!tab->IsSelected()) { - if (tab->render_unselected() && model_->count() > 1) { - // See comment above kNetTabAnimationSelectedOffset as to why we do - // this. - Tab* last_tab = GetTabAtModelIndex(model_->count() - 2); - canvas->save(); - int clip_x = last_tab->bounds().right() + kNetTabSelectedOffset; - int clip_width = width() - clip_x; - clip_x = MirroredXWithWidthInsideView(clip_x, clip_width); - canvas->ClipRectInt(clip_x, 0, clip_width, height()); - tab->ProcessPaint(canvas); - canvas->restore(); - } else { - tab->ProcessPaint(canvas); - } + tab->ProcessPaint(canvas); } else { selected_tab = tab; } @@ -478,30 +962,23 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) { paint); } - if (animation_type_ == ANIMATION_NEW_TAB_3) - newtab_button_->ProcessPaint(canvas); - // Paint the selected tab last, so it overlaps all the others. if (selected_tab) selected_tab->ProcessPaint(canvas); // Paint the New Tab button. - if (animation_type_ != ANIMATION_NEW_TAB_1 && - animation_type_ != ANIMATION_NEW_TAB_2 && - animation_type_ != ANIMATION_NEW_TAB_3) { - newtab_button_->ProcessPaint(canvas); - } + newtab_button_->ProcessPaint(canvas); } // Overridden to support automation. See automation_proxy_uitest.cc. views::View* TabStrip::GetViewByID(int view_id) const { if (GetTabCount() > 0) { if (view_id == VIEW_ID_TAB_LAST) { - return GetTabAtTabDataIndex(GetTabCount() - 1); + return GetTabAt(GetTabCount() - 1); } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) { int index = view_id - VIEW_ID_TAB_0; if (index >= 0 && index < GetTabCount()) { - return GetTabAtTabDataIndex(index); + return GetTabAt(index); } else { return NULL; } @@ -514,15 +991,22 @@ views::View* TabStrip::GetViewByID(int view_id) const { void TabStrip::Layout() { // Called from: // - window resize - StopAnimating(false); - + // - animation completion + if (active_animation_.get()) + active_animation_->Stop(); GenerateIdealBounds(); + int tab_count = GetTabCount(); + int tab_right = 0; - for (int i = 0, tab_count = GetTabCount(); i < tab_count; ++i) - tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds); - - newtab_button_->SetBounds(newtab_button_bounds_); - + for (int i = 0; i < tab_count; ++i) { + const gfx::Rect& bounds = tab_data_.at(i).ideal_bounds; + Tab* tab = GetTabAt(i); + tab->set_animating_mini_change(false); + tab->SetBounds(bounds.x(), bounds.y(), bounds.width(), bounds.height()); + tab_right = bounds.right(); + tab_right += GetTabHOffset(i + 1); + } + LayoutNewTabButton(static_cast<double>(tab_right), current_unselected_width_); SchedulePaint(); } @@ -531,9 +1015,6 @@ gfx::Size TabStrip::GetPreferredSize() { } void TabStrip::OnDragEntered(const DropTargetEvent& event) { - // Force animations to stop, otherwise it makes the index calculation tricky. - StopAnimating(true); - UpdateDropIndex(event); } @@ -604,10 +1085,10 @@ views::View* TabStrip::GetViewForPoint(const gfx::Point& point) { // left-adjacent Tab, so we look ahead for it as we walk. int tab_count = GetTabCount(); for (int i = 0; i < tab_count; ++i) { - Tab* next_tab = i < (tab_count - 1) ? GetTabAtTabDataIndex(i + 1) : NULL; + Tab* next_tab = i < (tab_count - 1) ? GetTabAt(i + 1) : NULL; if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point)) return next_tab; - Tab* tab = GetTabAtTabDataIndex(i); + Tab* tab = GetTabAt(i); if (IsPointInTab(tab, point)) return tab; } @@ -636,15 +1117,16 @@ void TabStrip::ViewHierarchyChanged(bool is_add, // TabStrip, TabStripModelObserver implementation: void TabStrip::TabInsertedAt(TabContents* contents, - int model_index, + int index, bool foreground) { DCHECK(contents); - DCHECK(model_index == TabStripModel::kNoTab || - model_->ContainsIndex(model_index)); + DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); // This tab may be attached to another browser window, we should notify // renderer. contents->render_view_host()->UpdateBrowserWindowId( contents->controller().window_id().id()); + if (active_animation_.get()) + active_animation_->Stop(); bool contains_tab = false; Tab* tab = NULL; @@ -663,23 +1145,10 @@ void TabStrip::TabInsertedAt(TabContents* contents, } // See if we're already in the list. We don't want to add ourselves twice. - int tab_data_index = TabDataIndexOfTab(tab); - - if (tab_data_index != -1) { - contains_tab = true; - - // Make sure we stop animating the view. This is necessary otherwise when - // the animation is done it'll try to remove the tab. - bounds_animator_.StopAnimatingView(tab); - - // We have the tab, but it might not be at the right index. Reset the data - // to ensure it's at the right index. - TabData tab_data = tab_data_[tab_data_index]; - DCHECK(tab_data.tab == tab); - tab_data_.erase(tab_data_.begin() + tab_data_index); - tab_data_.insert( - tab_data_.begin() + ModelIndexToTabDataIndex(model_index), - tab_data); + std::vector<TabData>::const_iterator iter = tab_data_.begin(); + for (; iter != tab_data_.end() && !contains_tab; ++iter) { + if (iter->tab == tab) + contains_tab = true; } } @@ -690,43 +1159,40 @@ void TabStrip::TabInsertedAt(TabContents* contents, // Only insert if we're not already in the list. if (!contains_tab) { TabData d = { tab, gfx::Rect() }; - tab_data_.insert(tab_data_.begin() + - ModelIndexToTabDataIndex(model_index), d); - tab->UpdateData(contents, model_->IsPhantomTab(model_index), false); + tab_data_.insert(tab_data_.begin() + index, d); + tab->UpdateData(contents, model_->IsPhantomTab(index), false); } - tab->set_mini(model_->IsMiniTab(model_index)); - tab->set_app(model_->IsAppTab(model_index)); - tab->SetBlocked(model_->IsTabBlocked(model_index)); + tab->set_mini(model_->IsMiniTab(index)); + tab->SetBlocked(model_->IsTabBlocked(index)); // We only add the tab to the child list if it's not already - an invisible // tab maintained by the DraggedTabController will already be parented. - if (!tab->GetParent()) { + if (!tab->GetParent()) AddChildView(tab); - tab->SetAnimationContainer(animation_container_.get()); - } // Don't animate the first tab, it looks weird, and don't animate anything // if the containing window isn't visible yet. if (GetTabCount() > 1 && GetWindow() && GetWindow()->IsVisible()) { - if (!IsDragSessionActive() && - ShouldStartIntertTabAnimationAtEnd(model_index, foreground)) { - StartInsertTabAnimationAtEnd(); - } else { - StartInsertTabAnimation(model_index); - } + StartInsertTabAnimation(index); } else { Layout(); } } -void TabStrip::TabDetachedAt(TabContents* contents, int model_index) { - StartRemoveTabAnimation(model_index); +void TabStrip::TabDetachedAt(TabContents* contents, int index) { + GenerateIdealBounds(); + StartRemoveTabAnimation(index, contents); + // Have to do this _after_ calling StartRemoveTabAnimation, so that any + // previous remove is completed fully and index is valid in sync with the + // model index. + GetTabAt(index)->set_closing(true); } void TabStrip::TabSelectedAt(TabContents* old_contents, TabContents* new_contents, - int model_index, + int index, bool user_gesture) { + DCHECK(index >= 0 && index < GetTabCount()); // We have "tiny tabs" if the tabs are so tiny that the unselected ones are // a different size to the selected ones. bool tiny_tabs = current_unselected_width_ != current_selected_width_; @@ -736,133 +1202,117 @@ void TabStrip::TabSelectedAt(TabContents* old_contents, SchedulePaint(); } - int old_model_index = model_->GetIndexOfTabContents(old_contents); - if (old_model_index >= 0) { - GetTabAtTabDataIndex(ModelIndexToTabDataIndex(old_model_index))-> - StopMiniTabTitleAnimation(); - } + int old_index = model_->GetIndexOfTabContents(old_contents); + if (old_index >= 0) + GetTabAt(old_index)->StopMiniTabTitleAnimation(); } -void TabStrip::TabMoved(TabContents* contents, - int from_model_index, - int to_model_index) { - StartMoveTabAnimation(from_model_index, to_model_index); +void TabStrip::TabMoved(TabContents* contents, int from_index, int to_index) { + gfx::Rect start_bounds = GetIdealBounds(from_index); + Tab* tab = GetTabAt(from_index); + tab_data_.erase(tab_data_.begin() + from_index); + TabData data = {tab, gfx::Rect()}; + tab->set_mini(model_->IsMiniTab(to_index)); + tab->SetBlocked(model_->IsTabBlocked(to_index)); + tab_data_.insert(tab_data_.begin() + to_index, data); + if (tab->phantom() != model_->IsPhantomTab(to_index)) + tab->set_phantom(!tab->phantom()); + GenerateIdealBounds(); + StartMoveTabAnimation(from_index, to_index); } -void TabStrip::TabChangedAt(TabContents* contents, - int model_index, +void TabStrip::TabChangedAt(TabContents* contents, int index, TabChangeType change_type) { // Index is in terms of the model. Need to make sure we adjust that index in // case we have an animation going. - Tab* tab = GetTabAtModelIndex(model_index); + Tab* tab = GetTabAtAdjustForAnimation(index); if (change_type == TITLE_NOT_LOADING) { if (tab->mini() && !tab->IsSelected()) tab->StartMiniTabTitleAnimation(); // We'll receive another notification of the change asynchronously. return; } - tab->UpdateData(contents, model_->IsPhantomTab(model_index), + tab->UpdateData(contents, model_->IsPhantomTab(index), change_type == LOADING_ONLY); tab->UpdateFromModel(); } void TabStrip::TabReplacedAt(TabContents* old_contents, TabContents* new_contents, - int model_index) { - TabChangedAt(new_contents, model_index, ALL); + int index) { + TabChangedAt(new_contents, index, ALL); } -void TabStrip::TabMiniStateChanged(TabContents* contents, int model_index) { - GetTabAtModelIndex(model_index)->set_mini( - model_->IsMiniTab(model_index)); +void TabStrip::TabMiniStateChanged(TabContents* contents, int index) { + GetTabAt(index)->set_mini(model_->IsMiniTab(index)); // Don't animate if the window isn't visible yet. The window won't be visible // when dragging a mini-tab to a new window. if (GetWindow() && GetWindow()->IsVisible()) - StartMiniTabAnimation(); + StartMiniTabAnimation(index); else Layout(); } -void TabStrip::TabBlockedStateChanged(TabContents* contents, int model_index) { - GetTabAtModelIndex(model_index)->SetBlocked( - model_->IsTabBlocked(model_index)); +void TabStrip::TabBlockedStateChanged(TabContents* contents, int index) { + GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index)); } /////////////////////////////////////////////////////////////////////////////// // TabStrip, Tab::Delegate implementation: bool TabStrip::IsTabSelected(const Tab* tab) const { - if (tab->closing() || tab->render_unselected()) + if (tab->closing()) return false; - return GetModelIndexOfTab(tab) == model_->selected_index(); + return GetIndexOfTab(tab) == model_->selected_index(); } bool TabStrip::IsTabPinned(const Tab* tab) const { if (tab->closing()) return false; - return model_->IsTabPinned(GetModelIndexOfTab(tab)); + return model_->IsTabPinned(GetIndexOfTab(tab)); } void TabStrip::SelectTab(Tab* tab) { - int model_index = GetModelIndexOfTab(tab); - if (model_->ContainsIndex(model_index)) - model_->SelectTabContentsAt(model_index, true); + int index = GetIndexOfTab(tab); + if (model_->ContainsIndex(index)) + model_->SelectTabContentsAt(index, true); } void TabStrip::CloseTab(Tab* tab) { - int model_index = GetModelIndexOfTab(tab); - if (model_->ContainsIndex(model_index)) { - TabContents* contents = model_->GetTabContentsAt(model_index); + int tab_index = GetIndexOfTab(tab); + if (model_->ContainsIndex(tab_index)) { + TabContents* contents = model_->GetTabContentsAt(tab_index); if (contents) UserMetrics::RecordAction(UserMetricsAction("CloseTab_Mouse"), contents->profile()); - if (model_index + 1 != model_->count() && model_->count() > 1) { - Tab* last_tab = GetTabAtModelIndex(model_->count() - 2); - // Limit the width available to the TabStrip for laying out Tabs, so that - // Tabs are not resized until a later time (when the mouse pointer leaves - // the TabStrip). - available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab); - needs_resize_layout_ = true; - AddMessageLoopObserver(); - } else if (model_->count() > 1) { - Tab* last_tab = GetTabAtModelIndex(model_->count() - 1); - // Limit the width available to the TabStrip for laying out Tabs, so that - // Tabs are not resized until a later time (when the mouse pointer leaves - // the TabStrip). - available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab); - needs_resize_layout_ = true; - AddMessageLoopObserver(); - } + Tab* last_tab = GetTabAt(GetTabCount() - 1); + // Limit the width available to the TabStrip for laying out Tabs, so that + // Tabs are not resized until a later time (when the mouse pointer leaves + // the TabStrip). + available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab); + needs_resize_layout_ = true; + AddMessageLoopObserver(); // Note that the next call might not close the tab (because of unload // hanlders or if the delegate veto the close). - model_->CloseTabContentsAt(model_index); + model_->CloseTabContentsAt(tab_index); } } bool TabStrip::IsCommandEnabledForTab( TabStripModel::ContextMenuCommand command_id, const Tab* tab) const { - int model_index = GetModelIndexOfTab(tab); - if (model_->ContainsIndex(model_index)) - return model_->IsContextMenuCommandEnabled(model_index, command_id); + int index = GetIndexOfTab(tab); + if (model_->ContainsIndex(index)) + return model_->IsContextMenuCommandEnabled(index, command_id); return false; } void TabStrip::ExecuteCommandForTab( TabStripModel::ContextMenuCommand command_id, Tab* tab) { - int model_index = GetModelIndexOfTab(tab); - if (model_->ContainsIndex(model_index)) - model_->ExecuteContextMenuCommand(model_index, command_id); -} - -void TabStrip::OnBoundsAnimatorDone(views::BoundsAnimator* animator) { - AnimationType last_type = animation_type_; - - ResetAnimationState(false); - - if (last_type == ANIMATION_NEW_TAB_2) - NewTabAnimation2Done(); + int index = GetIndexOfTab(tab); + if (model_->ContainsIndex(index)) + model_->ExecuteContextMenuCommand(index, command_id); } void TabStrip::StartHighlightTabsForCommand( @@ -870,13 +1320,13 @@ void TabStrip::StartHighlightTabsForCommand( if (command_id == TabStripModel::CommandCloseTabsOpenedBy || command_id == TabStripModel::CommandCloseOtherTabs || command_id == TabStripModel::CommandCloseTabsToRight) { - int model_index = GetModelIndexOfTab(tab); - if (model_->ContainsIndex(model_index)) { + int index = GetIndexOfTab(tab); + if (model_->ContainsIndex(index)) { std::vector<int> indices = - model_->GetIndicesClosedByCommand(model_index, command_id); + model_->GetIndicesClosedByCommand(index, command_id); for (std::vector<int>::const_iterator i = indices.begin(); i != indices.end(); ++i) { - GetTabAtModelIndex(*i)->StartPulse(); + GetTabAtAdjustForAnimation(*i)->StartPulse(); } } } @@ -894,7 +1344,7 @@ void TabStrip::StopHighlightTabsForCommand( void TabStrip::StopAllHighlighting() { for (int i = 0; i < GetTabCount(); ++i) - GetTabAtTabDataIndex(i)->StopPulse(); + GetTabAt(i)->StopPulse(); } void TabStrip::MaybeStartDrag(Tab* tab, const views::MouseEvent& event) { @@ -904,8 +1354,8 @@ void TabStrip::MaybeStartDrag(Tab* tab, const views::MouseEvent& event) { // the user is dragging. if (IsAnimating() || tab->closing() || !HasAvailableDragActions()) return; - int model_index = GetModelIndexOfTab(tab); - if (!model_->ContainsIndex(model_index)) { + int index = GetIndexOfTab(tab); + if (!model_->ContainsIndex(index)) { CHECK(false); return; } @@ -1013,18 +1463,15 @@ void TabStrip::DidProcessEvent(GdkEvent* event) { void TabStrip::Init() { SetID(VIEW_ID_TAB_STRIP); model_->AddObserver(this); - newtab_button_bounds_.SetRect(0, 0, kNewTabButtonWidth, kNewTabButtonHeight); - if (browser_defaults::kSizeTabButtonToTopOfTabStrip) { - newtab_button_bounds_.set_height( - kNewTabButtonHeight + kNewTabButtonVOffset); - } + newtab_button_size_.SetSize(kNewTabButtonWidth, kNewTabButtonHeight); + if (browser_defaults::kSizeTabButtonToTopOfTabStrip) + newtab_button_size_.set_height(kNewTabButtonHeight + kNewTabButtonVOffset); if (drop_indicator_width == 0) { // Direction doesn't matter, both images are the same size. SkBitmap* drop_image = GetDropArrowImage(true); drop_indicator_width = drop_image->width(); drop_indicator_height = drop_image->height(); } - bounds_animator_.set_observer(this); } void TabStrip::LoadNewTabButtonImage() { @@ -1054,14 +1501,20 @@ void TabStrip::LoadNewTabButtonImage() { delete tp; } -Tab* TabStrip::GetTabAtTabDataIndex(int tab_data_index) const { - DCHECK_GE(tab_data_index, 0); - DCHECK_LT(tab_data_index, GetTabCount()); - return tab_data_[tab_data_index].tab; +Tab* TabStrip::GetTabAt(int index) const { + DCHECK_GE(index, 0); + DCHECK_LT(index, GetTabCount()); + return tab_data_.at(index).tab; } -Tab* TabStrip::GetTabAtModelIndex(int model_index) const { - return GetTabAtTabDataIndex(ModelIndexToTabDataIndex(model_index)); +Tab* TabStrip::GetTabAtAdjustForAnimation(int index) const { + if (active_animation_.get() && + active_animation_->type() == TabAnimation::REMOVE && + index >= + static_cast<RemoveTabAnimation*>(active_animation_.get())->index()) { + index++; + } + return GetTabAt(index); } int TabStrip::GetTabCount() const { @@ -1094,7 +1547,7 @@ void TabStrip::GetDesiredTabWidths(int tab_count, int available_width; if (available_width_for_tabs_ < 0) { available_width = width(); - available_width -= (kNewTabButtonHOffset + newtab_button_bounds_.width()); + available_width -= (kNewTabButtonHOffset + newtab_button_size_.width()); } else { // Interesting corner case: if |available_width_for_tabs_| > the result // of the calculation in the conditional arm above, the strip is in @@ -1154,6 +1607,14 @@ void TabStrip::GetDesiredTabWidths(int tab_count, } } +int TabStrip::GetTabHOffset(int tab_index) { + if (tab_index < GetTabCount() && GetTabAt(tab_index - 1)->mini() && + !GetTabAt(tab_index)->mini()) { + return mini_to_non_mini_gap_ + kTabHOffset; + } + return kTabHOffset; +} + void TabStrip::ResizeLayoutTabs() { // We've been called back after the TabStrip has been emptied out (probably // just prior to the window being destroyed). We need to do nothing here or @@ -1174,7 +1635,7 @@ void TabStrip::ResizeLayoutTabs() { // mini-tabs have the same width), so there is nothing to do. return; } - Tab* first_tab = GetTabAtTabDataIndex(mini_tab_count); + Tab* first_tab = GetTabAt(mini_tab_count); double unselected, selected; GetDesiredTabWidths(GetTabCount(), mini_tab_count, &unselected, &selected); int w = Round(first_tab->IsSelected() ? selected : selected); @@ -1196,7 +1657,7 @@ bool TabStrip::IsCursorInTabStripZone() const { DWORD pos = GetMessagePos(); gfx::Point cursor_point(pos); #elif defined(OS_LINUX) - // TODO(sky): make sure this is right with multiple monitors. + // TODO: make sure this is right with multiple monitors. GdkScreen* screen = gdk_screen_get_default(); GdkDisplay* display = gdk_screen_get_display(screen); gint x, y; @@ -1227,13 +1688,14 @@ gfx::Rect TabStrip::GetDropBounds(int drop_index, DCHECK(drop_index != -1); int center_x; if (drop_index < GetTabCount()) { - Tab* tab = GetTabAtTabDataIndex(drop_index); + Tab* tab = GetTabAt(drop_index); + // TODO(sky): update these for mini-tabs. if (drop_before) center_x = tab->x() - (kTabHOffset / 2); else center_x = tab->x() + (tab->width() / 2); } else { - Tab* last_tab = GetTabAtTabDataIndex(drop_index - 1); + Tab* last_tab = GetTabAt(drop_index - 1); center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2); } @@ -1269,7 +1731,7 @@ void TabStrip::UpdateDropIndex(const DropTargetEvent& event) { const int x = MirroredXCoordinateInsideView(event.x()); // We don't allow replacing the urls of mini-tabs. for (int i = GetMiniTabCount(); i < GetTabCount(); ++i) { - Tab* tab = GetTabAtTabDataIndex(i); + Tab* tab = GetTabAt(i); const int tab_max_x = tab->x() + tab->width(); const int hot_width = tab->width() / 3; if (x < tab_max_x) { @@ -1287,26 +1749,25 @@ void TabStrip::UpdateDropIndex(const DropTargetEvent& event) { SetDropIndex(GetTabCount(), true); } -void TabStrip::SetDropIndex(int tab_data_index, bool drop_before) { - if (tab_data_index == -1) { +void TabStrip::SetDropIndex(int index, bool drop_before) { + if (index == -1) { if (drop_info_.get()) drop_info_.reset(NULL); return; } - if (drop_info_.get() && drop_info_->drop_index == tab_data_index && + if (drop_info_.get() && drop_info_->drop_index == index && drop_info_->drop_before == drop_before) { return; } bool is_beneath; - gfx::Rect drop_bounds = GetDropBounds(tab_data_index, drop_before, - &is_beneath); + gfx::Rect drop_bounds = GetDropBounds(index, drop_before, &is_beneath); if (!drop_info_.get()) { - drop_info_.reset(new DropInfo(tab_data_index, drop_before, !is_beneath)); + drop_info_.reset(new DropInfo(index, drop_before, !is_beneath)); } else { - drop_info_->drop_index = tab_data_index; + drop_info_->drop_index = index; drop_info_->drop_before = drop_before; if (is_beneath == drop_info_->point_down) { drop_info_->point_down = !is_beneath; @@ -1383,19 +1844,8 @@ TabStrip::DropInfo::~DropInfo() { // - Tab reorder void TabStrip::GenerateIdealBounds() { int tab_count = GetTabCount(); - int non_closing_tab_count = 0; - int mini_tab_count = 0; - for (int i = 0; i < tab_count; ++i) { - if (!tab_data_[i].tab->closing()) { - ++non_closing_tab_count; - if (tab_data_[i].tab->mini()) - mini_tab_count++; - } - } - double unselected, selected; - GetDesiredTabWidths(non_closing_tab_count, mini_tab_count, &unselected, - &selected); + GetDesiredTabWidths(tab_count, GetMiniTabCount(), &unselected, &selected); current_unselected_width_ = unselected; current_selected_width_ = selected; @@ -1404,259 +1854,139 @@ void TabStrip::GenerateIdealBounds() { // selected state or the number of tabs in the strip! int tab_height = Tab::GetStandardSize().height(); double tab_x = 0; - bool last_was_mini = false; for (int i = 0; i < tab_count; ++i) { - if (!tab_data_[i].tab->closing()) { - Tab* tab = GetTabAtTabDataIndex(i); - double tab_width = unselected; - if (tab->mini()) { - tab_width = Tab::GetMiniWidth(); - } else { - if (last_was_mini) { - // Give a bigger gap between mini and non-mini tabs. - tab_x += mini_to_non_mini_gap_; - } - if (tab->IsSelected()) - tab_width = selected; - } - double end_of_tab = tab_x + tab_width; - int rounded_tab_x = Round(tab_x); - tab_data_[i].ideal_bounds = - gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, + Tab* tab = GetTabAt(i); + double tab_width = unselected; + if (tab->mini()) + tab_width = Tab::GetMiniWidth(); + else if (tab->IsSelected()) + tab_width = selected; + double end_of_tab = tab_x + tab_width; + int rounded_tab_x = Round(tab_x); + gfx::Rect state(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, tab_height); - tab_x = end_of_tab + kTabHOffset; - last_was_mini = tab->mini(); - } + tab_data_.at(i).ideal_bounds = state; + tab_x = end_of_tab + GetTabHOffset(i + 1); } +} - // Update bounds of new tab button. - int new_tab_x; - int new_tab_y = browser_defaults::kSizeTabButtonToTopOfTabStrip ? +void TabStrip::LayoutNewTabButton(double last_tab_right, + double unselected_width) { + int delta = abs(Round(unselected_width) - Tab::GetStandardSize().width()); + int v_offset = browser_defaults::kSizeTabButtonToTopOfTabStrip ? 0 : kNewTabButtonVOffset; - if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && - available_width_for_tabs_ == -1) { + if (delta > 1 && !needs_resize_layout_) { // We're shrinking tabs, so we need to anchor the New Tab button to the // right edge of the TabStrip's bounds, rather than the right edge of the // right-most Tab, otherwise it'll bounce when animating. - new_tab_x = width() - newtab_button_bounds_.width(); + newtab_button_->SetBounds(width() - newtab_button_size_.width(), + v_offset, + newtab_button_size_.width(), + newtab_button_size_.height()); } else { - new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; - } - newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); -} - -void TabStrip::NewTabAnimation1Done() { - int tab_data_index = static_cast<int>(tab_data_.size() - 1); - Tab* tab = GetTabAtTabDataIndex(tab_data_index); - - gfx::Rect old_tab_bounds = tab->bounds(); - - GenerateIdealBounds(); - - gfx::Rect& end_bounds = tab_data_[tab_data_index].ideal_bounds; - end_bounds.Offset(kNewTabOvershoot, 0); - - int x = old_tab_bounds.right() - end_bounds.width(); - int w = end_bounds.width(); - if (x < 0) { - w += x; - x = 0; - } - tab->SetBounds(x, old_tab_bounds.y(), w, end_bounds.height()); - - AnimateToIdealBounds(); - - animation_type_ = ANIMATION_NEW_TAB_2; - tab->set_render_as_new_tab(false); - tab->set_render_unselected(true); - tab->set_alpha(0); - - // BoundsAnimator takes ownership of NewTabAlphaDelegate. - bounds_animator_.SetAnimationDelegate(tab, new NewTabAlphaDelegate(tab), - true); -} - -void TabStrip::NewTabAnimation2Done() { - animation_type_ = ANIMATION_NEW_TAB_3; - - GenerateIdealBounds(); - - AnimateToIdealBounds(); - - SlideAnimation* animation = new SlideAnimation(NULL); - animation->SetSlideDuration(kNewTab3DurationMs); - animation->SetTweenType(SlideAnimation::EASE_IN_OUT); - - // BoundsAnimator takes ownership of animation. - bounds_animator_.SetAnimationForView(tab_data_.back().tab, animation); -} - -void TabStrip::AnimateToIdealBounds() { - for (size_t i = 0; i < tab_data_.size(); ++i) { - if (!tab_data_[i].tab->closing()) { - bounds_animator_.AnimateViewTo(tab_data_[i].tab, - tab_data_[i].ideal_bounds, - false); - } - } - - if (animation_type_ != ANIMATION_NEW_TAB_3) { - bounds_animator_.AnimateViewTo(newtab_button_, - newtab_button_bounds_, - false); + newtab_button_->SetBounds( + Round(last_tab_right - kTabHOffset) + kNewTabButtonHOffset, + v_offset, newtab_button_size_.width(), newtab_button_size_.height()); } } -bool TabStrip::ShouldStartIntertTabAnimationAtEnd(int model_index, - bool foreground) { - return foreground && (model_index + 1 == model_->count()) && - (model_->GetTabContentsAt(model_index)->GetURL() == - GURL(chrome::kChromeUINewTabURL)); +// Called from: +// - animation tick +void TabStrip::AnimationLayout(double unselected_width) { + int tab_height = Tab::GetStandardSize().height(); + double tab_x = 0; + for (int i = 0; i < GetTabCount(); ++i) { + TabAnimation* animation = active_animation_.get(); + if (animation) + tab_x += animation->GetGapWidth(i); + double tab_width = TabAnimation::GetCurrentTabWidth(this, animation, i); + double end_of_tab = tab_x + tab_width; + int rounded_tab_x = Round(tab_x); + Tab* tab = GetTabAt(i); + tab->SetBounds(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, + tab_height); + tab_x = end_of_tab + GetTabHOffset(i + 1); + } + LayoutNewTabButton(tab_x, unselected_width); + SchedulePaint(); } void TabStrip::StartResizeLayoutAnimation() { - ResetAnimationState(true); - GenerateIdealBounds(); - AnimateToIdealBounds(); + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset(new ResizeLayoutAnimation(this)); + active_animation_->Start(); } -void TabStrip::StartInsertTabAnimationAtEnd() { - ResetAnimationState(true); - +void TabStrip::StartInsertTabAnimation(int index) { // The TabStrip can now use its entire width to lay out Tabs. available_width_for_tabs_ = -1; - - animation_type_ = ANIMATION_NEW_TAB_1; - - GenerateIdealBounds(); - - int tab_data_index = ModelIndexToTabDataIndex(model_->count() - 1); - Tab* tab = tab_data_[tab_data_index].tab; - tab->SizeToNewTabButtonImages(); - tab->SetBounds(newtab_button_->x() + - (newtab_button_->width() - tab->width()) / 2, - tab_data_[tab_data_index].ideal_bounds.y(), - tab->width(), tab->height()); - tab->set_render_as_new_tab(true); - - new_tab_timer_.Start(base::TimeDelta::FromMilliseconds(kNewTabDurationMs), - this, &TabStrip::NewTabAnimation1Done); + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset(new InsertTabAnimation(this, index)); + active_animation_->Start(); } -void TabStrip::StartInsertTabAnimation(int model_index) { - ResetAnimationState(true); - - // The TabStrip can now use its entire width to lay out Tabs. - available_width_for_tabs_ = -1; - - GenerateIdealBounds(); - - int tab_data_index = ModelIndexToTabDataIndex(model_index); - Tab* tab = tab_data_[tab_data_index].tab; - if (model_index == 0) { - tab->SetBounds(0, tab_data_[tab_data_index].ideal_bounds.y(), 0, - tab_data_[tab_data_index].ideal_bounds.height()); - } else { - Tab* last_tab = tab_data_[tab_data_index - 1].tab; - tab->SetBounds(last_tab->bounds().right() + kTabHOffset, - tab_data_[tab_data_index].ideal_bounds.y(), 0, - tab_data_[tab_data_index].ideal_bounds.height()); +void TabStrip::StartRemoveTabAnimation(int index, TabContents* contents) { + if (active_animation_.get()) { + // Some animations (e.g. MoveTabAnimation) cause there to be a Layout when + // they're completed (which includes canceled). Since |tab_data_| is now + // inconsistent with TabStripModel, doing this Layout will crash now, so + // we ask the MoveTabAnimation to skip its Layout (the state will be + // corrected by the RemoveTabAnimation we're about to initiate). + active_animation_->set_layout_on_completion(false); + active_animation_->Stop(); } - - AnimateToIdealBounds(); + active_animation_.reset(new RemoveTabAnimation(this, index, contents)); + active_animation_->Start(); } -void TabStrip::StartRemoveTabAnimation(int model_index) { - ResetAnimationState(true); - - // Mark the tab as closing. - int tab_data_index = ModelIndexToTabDataIndex(model_index); - Tab* tab = tab_data_[tab_data_index].tab; - tab->set_closing(true); - - // Start an animation for the tabs. - GenerateIdealBounds(); - AnimateToIdealBounds(); - - // Animate the tab being closed to 0x0. - gfx::Rect tab_bounds = tab->bounds(); - tab_bounds.set_width(0); - bounds_animator_.AnimateViewTo(tab, tab_bounds, false); - - // Register delegate to do cleanup when done, BoundsAnimator takes - // ownership of RemoveTabDelegate. - bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), - true); +void TabStrip::StartMoveTabAnimation(int from_index, int to_index) { + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset(new MoveTabAnimation(this, from_index, to_index)); + active_animation_->Start(); } -void TabStrip::StartMoveTabAnimation(int from_model_index, - int to_model_index) { - ResetAnimationState(true); - - int from_tab_data_index = ModelIndexToTabDataIndex(from_model_index); - - Tab* tab = tab_data_[from_tab_data_index].tab; - tab_data_.erase(tab_data_.begin() + from_tab_data_index); - - TabData data = {tab, gfx::Rect()}; - tab->set_mini(model_->IsMiniTab(to_model_index)); - //tab->set_app(model_->IsAppTab(to_model_index)); - tab->SetBlocked(model_->IsTabBlocked(to_model_index)); - - int to_tab_data_index = ModelIndexToTabDataIndex(to_model_index); - - tab_data_.insert(tab_data_.begin() + to_tab_data_index, data); - if (tab->phantom() != model_->IsPhantomTab(to_model_index)) - tab->set_phantom(!tab->phantom()); - - GenerateIdealBounds(); - AnimateToIdealBounds(); +void TabStrip::StartMiniTabAnimation(int index) { + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset(new MiniTabAnimation(this, index)); + active_animation_->Start(); } -void TabStrip::StartMiniTabAnimation() { - ResetAnimationState(true); - - GenerateIdealBounds(); - AnimateToIdealBounds(); +void TabStrip::StartMiniMoveTabAnimation(int from_index, + int to_index, + const gfx::Rect& start_bounds) { + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset( + new MiniMoveAnimation(this, from_index, to_index, start_bounds)); + active_animation_->Start(); } -void TabStrip::StopAnimating(bool layout) { - if (!IsAnimating()) - return; - - new_tab_timer_.Stop(); +void TabStrip::FinishAnimation(TabStrip::TabAnimation* animation, + bool layout) { + active_animation_.reset(NULL); - if (bounds_animator_.IsAnimating()) { - // Cancelling the animation triggers OnBoundsAnimatorDone, which invokes - // ResetAnimationState. - bounds_animator_.Cancel(); - } else { - ResetAnimationState(false); - } - - DCHECK(!IsAnimating()); + // Reset the animation state of each tab. + for (int i = 0, count = GetTabCount(); i < count; ++i) + GetTabAt(i)->set_animating_mini_change(false); if (layout) Layout(); } -void TabStrip::ResetAnimationState(bool stop_new_tab_timer) { - if (animation_type_ == ANIMATION_NEW_TAB_2) - newtab_button_->SchedulePaint(); - - if (stop_new_tab_timer) - new_tab_timer_.Stop(); - - animation_type_ = ANIMATION_DEFAULT; - - // Reset the animation state of each tab. - for (int i = 0, count = GetTabCount(); i < count; ++i) { - Tab* tab = GetTabAtTabDataIndex(i); - tab->set_animating_mini_change(false); - tab->set_render_as_new_tab(false); - tab->set_render_unselected(false); - tab->set_alpha(1); +int TabStrip::GetIndexOfTab(const Tab* tab) const { + for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { + Tab* current_tab = GetTabAt(i); + if (current_tab->closing()) { + --index; + } else if (current_tab == tab) { + return index; + } } + return -1; } int TabStrip::GetMiniTabCount() const { @@ -1681,21 +2011,22 @@ bool TabStrip::IsPointInTab(Tab* tab, return tab->HitTest(point_in_tab_coords); } -void TabStrip::RemoveTab(Tab* tab) { - int tab_data_index = TabDataIndexOfTab(tab); - - DCHECK(tab_data_index != -1); +void TabStrip::RemoveTabAt(int index) { + Tab* removed = tab_data_.at(index).tab; // Remove the Tab from the TabStrip's list... - tab_data_.erase(tab_data_.begin() + tab_data_index); + tab_data_.erase(tab_data_.begin() + index); // If the TabContents being detached was removed as a result of a drag // gesture from its corresponding Tab, we don't want to remove the Tab from // the child list, because if we do so it'll stop receiving events and the // drag will stall. So we only remove if a drag isn't active, or the Tab // was for some other TabContents. - if (!IsDragSessionActive() || !drag_controller_->IsDragSourceTab(tab)) - delete tab; + if (!IsDragSessionActive() || !drag_controller_->IsDragSourceTab(removed)) { + removed->GetParent()->RemoveChildView(removed); + delete removed; + } + GenerateIdealBounds(); } void TabStrip::HandleGlobalMouseMoveEvent() { @@ -1718,40 +2049,8 @@ void TabStrip::HandleGlobalMouseMoveEvent() { bool TabStrip::HasPhantomTabs() const { for (int i = 0; i < GetTabCount(); ++i) { - if (GetTabAtTabDataIndex(i)->phantom()) + if (GetTabAt(i)->phantom()) return true; } return false; } - -int TabStrip::GetModelIndexOfTab(const Tab* tab) const { - for (int i = 0, model_index = 0; i < GetTabCount(); ++i) { - Tab* current_tab = GetTabAtTabDataIndex(i); - if (!current_tab->closing()) { - if (current_tab == tab) - return model_index; - model_index++; - } - } - return -1; -} - -int TabStrip::ModelIndexToTabDataIndex(int model_index) const { - int current_model_index = 0; - for (size_t i = 0; i < tab_data_.size(); ++i) { - if (!tab_data_[i].tab->closing()) { - if (current_model_index == model_index) - return i; - current_model_index++; - } - } - return tab_data_.size(); -} - -int TabStrip::TabDataIndexOfTab(Tab* tab) const { - for (size_t i = 0; i < tab_data_.size(); ++i) { - if (tab_data_[i].tab == tab) - return i; - } - return -1; -} diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index e1cbfda..af6cc34 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -5,16 +5,11 @@ #ifndef CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_ #define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_ -#include "app/animation_container.h" #include "base/message_loop.h" -#include "base/ref_counted.h" -#include "base/timer.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/views/tabs/base_tab_strip.h" #include "chrome/browser/views/tabs/tab.h" #include "gfx/point.h" -#include "gfx/rect.h" -#include "views/animation/bounds_animator.h" #include "views/controls/button/image_button.h" class DraggedTabController; @@ -47,8 +42,7 @@ class TabStrip : public BaseTabStrip, public TabStripModelObserver, public Tab::TabDelegate, public views::ButtonListener, - public MessageLoopForUI::Observer, - public views::BoundsAnimatorObserver { + public MessageLoopForUI::Observer { public: explicit TabStrip(TabStripModel* model); virtual ~TabStrip(); @@ -68,7 +62,7 @@ class TabStrip : public BaseTabStrip, void DestroyDraggedSourceTab(Tab* tab); // Retrieves the ideal bounds for the Tab at the specified index. - gfx::Rect GetIdealBounds(int tab_data_index); + gfx::Rect GetIdealBounds(int index); // Returns the currently selected tab. Tab* GetSelectedTab() const; @@ -109,9 +103,6 @@ class TabStrip : public BaseTabStrip, virtual views::View* GetViewForPoint(const gfx::Point& point); virtual void ThemeChanged(); - // BoundsAnimator::Observer overrides: - virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator); - protected: // Creates a new tab. virtual Tab* CreateTab(); @@ -123,24 +114,21 @@ class TabStrip : public BaseTabStrip, // TabStripModelObserver implementation: virtual void TabInsertedAt(TabContents* contents, - int model_index, + int index, bool foreground); - virtual void TabDetachedAt(TabContents* contents, int model_index); + virtual void TabDetachedAt(TabContents* contents, int index); virtual void TabSelectedAt(TabContents* old_contents, TabContents* contents, - int model_index, + int index, bool user_gesture); - virtual void TabMoved(TabContents* contents, - int from_model_index, - int to_model_index); - virtual void TabChangedAt(TabContents* contents, - int model_index, + virtual void TabMoved(TabContents* contents, int from_index, int to_index); + virtual void TabChangedAt(TabContents* contents, int index, TabChangeType change_type); virtual void TabReplacedAt(TabContents* old_contents, TabContents* new_contents, - int model_index); - virtual void TabMiniStateChanged(TabContents* contents, int model_index); - virtual void TabBlockedStateChanged(TabContents* contents, int model_index); + int index); + virtual void TabMiniStateChanged(TabContents* contents, int index); + virtual void TabBlockedStateChanged(TabContents* contents, int index); // Tab::Delegate implementation: virtual bool IsTabSelected(const Tab* tab) const; @@ -177,70 +165,22 @@ class TabStrip : public BaseTabStrip, static const int mini_to_non_mini_gap_; private: - class RemoveTabDelegate; + class InsertTabAnimation; + class MiniMoveAnimation; + class MiniTabAnimation; + class MoveTabAnimation; + class RemoveTabAnimation; + class ResizeLayoutAnimation; + class TabAnimation; friend class DraggedTabController; - - // AnimationType used for tracking animations that require additional - // state beyond just animating the bounds of a view. - // - // Currently the only animation special cased is that of inserting the new tab - // page at the end of the tab strip. Here's the steps that take place when - // this happens. - // . The newly inserted tab is set to render for the new tab animation - // |set_render_as_new_tab|. The timer new_tab_timer_ is used to determine - // when to turn this off. This is represented by state ANIMATION_NEW_TAB_1. - // . The new tab is rendered in the background with an ever increasing alpha - // value and the tab goes slightly past the new tab button. The new tab - // button is not visible during this animation. This is represented by the - // state ANIMATION_NEW_TAB_2. - // . The new tab is animated to its final position and the new tab button is - // rendered beneath the selected tab. This is represented by the state - // ANIMATION_NEW_TAB_3. - enum AnimationType { - ANIMATION_DEFAULT, - - ANIMATION_NEW_TAB_1, - ANIMATION_NEW_TAB_2, - ANIMATION_NEW_TAB_3 - }; - - // Used during a drop session of a url. Tracks the position of the drop as - // well as a window used to highlight where the drop occurs. - struct DropInfo { - DropInfo(int index, bool drop_before, bool paint_down); - ~DropInfo(); - - // Index of the tab to drop on. If drop_before is true, the drop should - // occur between the tab at drop_index - 1 and drop_index. - // WARNING: if drop_before is true it is possible this will == tab_count, - // which indicates the drop should create a new tab at the end of the tabs. - int drop_index; - bool drop_before; - - // Direction the arrow should point in. If true, the arrow is displayed - // above the tab and points down. If false, the arrow is displayed beneath - // the tab and points up. - bool point_down; - - // Renders the drop indicator. - // TODO(beng): should be views::Widget. -#if defined(OS_WIN) - views::WidgetWin* arrow_window; -#else - views::WidgetGtk* arrow_window; -#endif - views::ImageView* arrow_view; - - private: - DISALLOW_COPY_AND_ASSIGN(DropInfo); - }; - - // The Tabs we contain, and their last generated "good" bounds. - struct TabData { - Tab* tab; - gfx::Rect ideal_bounds; - }; + friend class InsertTabAnimation; + friend class MiniMoveAnimation; + friend class MiniTabAnimation; + friend class MoveTabAnimation; + friend class RemoveTabAnimation; + friend class ResizeLayoutAnimation; + friend class TabAnimation; TabStrip(); void Init(); @@ -248,9 +188,9 @@ class TabStrip : public BaseTabStrip, // Set the images for the new tab button. void LoadNewTabButtonImage(); - // Retrieves the Tab at the specified index. Remember, the specified index - // is in terms of tab_data, *not* the model. - Tab* GetTabAtTabDataIndex(int tab_data_index) const; + // Retrieves the Tab at the specified index. Take care in using this, you may + // need to use GetTabAtAdjustForAnimation. + Tab* GetTabAt(int index) const; // Returns the tab at the specified index. If a remove animation is on going // and the index is >= the index of the tab being removed, the index is @@ -258,13 +198,10 @@ class TabStrip : public BaseTabStrip, // do not line up with the indices of the view. This method adjusts the index // accordingly. // - // Use this instead of GetTabAtTabDataIndex if the index comes from the model. - Tab* GetTabAtModelIndex(int model_index) const; + // Use this instead of GetTabAt if the index comes from the model. + Tab* GetTabAtAdjustForAnimation(int index) const; // Gets the number of Tabs in the collection. - // WARNING: this is the number of tabs displayed by the tabstrip, which if - // an animation is ongoing is not necessarily the same as the number of tabs - // in the model. int GetTabCount() const; // Returns the number of mini-tabs. @@ -287,6 +224,9 @@ class TabStrip : public BaseTabStrip, double* unselected_width, double* selected_width) const; + // Returns the horizontal offset before the tab at |tab_index|. + int GetTabHOffset(int tab_index); + // Perform an animated resize-relayout of the TabStrip immediately. void ResizeLayoutTabs(); @@ -310,7 +250,7 @@ class TabStrip : public BaseTabStrip, void UpdateDropIndex(const views::DropTargetEvent& event); // Sets the location of the drop, repainting as necessary. - void SetDropIndex(int tab_data_index, bool drop_before); + void SetDropIndex(int index, bool drop_before); // Returns the drop effect for dropping a URL on the tab strip. This does // not query the data in anyway, it only looks at the source operations. @@ -328,38 +268,32 @@ class TabStrip : public BaseTabStrip, // stable representations of Tab positions. void GenerateIdealBounds(); - // Both of these are invoked when a part of the new tab animation completes. - // They configure state for the next step in the animation and start it. - void NewTabAnimation1Done(); - void NewTabAnimation2Done(); - - // Animates all the views to their ideal bounds. - // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds - // currently set in ideal_bounds. - void AnimateToIdealBounds(); + // Lays out the New Tab button, assuming the right edge of the last Tab on + // the TabStrip at |last_tab_right|. + void LayoutNewTabButton(double last_tab_right, double unselected_width); - // Returns true if a new tab inserted at specified index should start the - // new tab animation. See description above AnimationType for details on - // this animation. - bool ShouldStartIntertTabAnimationAtEnd(int model_index, bool foreground); + // A generic Layout method for various classes of TabStrip animations, + // including Insert, Remove and Resize Layout cases/ + void AnimationLayout(double unselected_width); // Starts various types of TabStrip animations. void StartResizeLayoutAnimation(); - void StartInsertTabAnimationAtEnd(); - void StartInsertTabAnimation(int model_index); - void StartRemoveTabAnimation(int model_index); - void StartMoveTabAnimation(int from_model_index, - int to_model_index); - void StartMiniTabAnimation(); - - // Stops any ongoing animations. If |layout| is true and an animation is - // ongoing this does a layout. - void StopAnimating(bool layout); - - // Resets all state related to animations. This is invoked when an animation - // completes, prior to starting an animation or when we cancel an animation. - // If |stop_new_tab_timer| is true, |new_tab_timer_| is stopped. - void ResetAnimationState(bool stop_new_tab_timer); + void StartInsertTabAnimation(int index); + void StartRemoveTabAnimation(int index, TabContents* contents); + void StartMoveTabAnimation(int from_index, int to_index); + void StartMiniTabAnimation(int index); + void StartMiniMoveTabAnimation(int from_index, + int to_index, + const gfx::Rect& start_bounds); + + // Notifies the TabStrip that the specified TabAnimation has completed. + // Optionally a full Layout will be performed, specified by |layout|. + void FinishAnimation(TabAnimation* animation, bool layout); + + // Finds the index of the TabContents corresponding to |tab| in our + // associated TabStripModel, or -1 if there is none (e.g. the specified |tab| + // is being animated closed). + int GetIndexOfTab(const Tab* tab) const; // Calculates the available width for tabs, assuming a Tab is to be closed. int GetAvailableWidthForTabs(Tab* last_tab) const; @@ -368,9 +302,9 @@ class TabStrip : public BaseTabStrip, // hit-test region of the specified Tab. bool IsPointInTab(Tab* tab, const gfx::Point& point_in_tabstrip_coords); - // Cleans up the Tab from the TabStrip. This is called from the tab animation - // code and is not a general-purpose method. - void RemoveTab(Tab* tab); + // Cleans up the Tab from the TabStrip at the specified |index|. This is + // called from the tab animation code and is not a general-purpose method. + void RemoveTabAt(int index); // Called from the message loop observer when a mouse movement has occurred // anywhere over our containing window. @@ -379,19 +313,6 @@ class TabStrip : public BaseTabStrip, // Returns true if any of the tabs are phantom. bool HasPhantomTabs() const; - // Returns the index of the specified tab in the model coordiate system, or - // -1 if tab is closing or not in |tab_data_|. - int GetModelIndexOfTab(const Tab* tab) const; - - // Returns the index into |tab_data_| corresponding to the index from the - // TabStripModel, or |tab_data_.size()| if there is no tab representing - // |model_index|. - int ModelIndexToTabDataIndex(int model_index) const; - - // Returns the index into |tab_data_| corresponding to the specified tab, or - // -1 if the tab isn't in |tab_data_|. - int TabDataIndexOfTab(Tab* tab) const; - // -- Member Variables ------------------------------------------------------ // Our model. @@ -410,9 +331,7 @@ class TabStrip : public BaseTabStrip, // The "New Tab" button. views::ImageButton* newtab_button_; - - // Ideal bounds of the new tab button. - gfx::Rect newtab_button_bounds_; + gfx::Size newtab_button_size_; // The current widths of various types of tabs. We save these so that, as // users close tabs while we're holding them at the same size, we can lay out @@ -440,6 +359,37 @@ class TabStrip : public BaseTabStrip, static const int kNewTabButtonWidth = 28; static const int kNewTabButtonHeight = 18; + // Used during a drop session of a url. Tracks the position of the drop as + // well as a window used to highlight where the drop occurs. + struct DropInfo { + DropInfo(int index, bool drop_before, bool paint_down); + ~DropInfo(); + + // Index of the tab to drop on. If drop_before is true, the drop should + // occur between the tab at drop_index - 1 and drop_index. + // WARNING: if drop_before is true it is possible this will == tab_count, + // which indicates the drop should create a new tab at the end of the tabs. + int drop_index; + bool drop_before; + + // Direction the arrow should point in. If true, the arrow is displayed + // above the tab and points down. If false, the arrow is displayed beneath + // the tab and points up. + bool point_down; + + // Renders the drop indicator. + // TODO(beng): should be views::Widget. +#if defined(OS_WIN) + views::WidgetWin* arrow_window; +#else + views::WidgetGtk* arrow_window; +#endif + views::ImageView* arrow_view; + + private: + DISALLOW_COPY_AND_ASSIGN(DropInfo); + }; + // Valid for the lifetime of a drag over us. scoped_ptr<DropInfo> drop_info_; @@ -447,19 +397,15 @@ class TabStrip : public BaseTabStrip, // the drag session. scoped_ptr<DraggedTabController> drag_controller_; + // The Tabs we contain, and their last generated "good" bounds. + struct TabData { + Tab* tab; + gfx::Rect ideal_bounds; + }; std::vector<TabData> tab_data_; - // To ensure all tabs pulse at the same time they share the same animation - // container. This is that animation container. - scoped_refptr<AnimationContainer> animation_container_; - - views::BoundsAnimator bounds_animator_; - - // Used for stage 1 of new tab animation. - base::OneShotTimer<TabStrip> new_tab_timer_; - - // Set for special animations. - AnimationType animation_type_; + // The currently running animation. + scoped_ptr<TabAnimation> active_animation_; DISALLOW_COPY_AND_ASSIGN(TabStrip); }; diff --git a/chrome/browser/views/toolbar_star_toggle.cc b/chrome/browser/views/toolbar_star_toggle.cc new file mode 100644 index 0000000..710d6fa --- /dev/null +++ b/chrome/browser/views/toolbar_star_toggle.cc @@ -0,0 +1,133 @@ +// Copyright (c) 2006-2008 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/toolbar_star_toggle.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_theme_provider.h" +#include "chrome/browser/bubble_positioner.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/views/browser_dialogs.h" +#include "chrome/browser/view_ids.h" +#include "googleurl/src/gurl.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" + +using base::TimeTicks; + +// The amount of time (in milliseconds) between when the bubble closes and when +// pressing on the button again does something. Yes, this is a hackish. I tried +// many different options, all to no avail: +// . Keying off mouse activation: this didn't work as there is no way to know +// which window receives the activation. Additionally once the mouse +// activation occurs we have no way to tie the next mouse event to the mouse +// activation. +// . Watching all events as we dispatch them in the MessageLoop. Mouse +// activation isn't an observable event though. +// Ideally we could use mouse capture for this, but we can't use mouse capture +// with the bubble because it has other native windows. +static const int64 kDisallowClickMS = 40; + +ToolbarStarToggle::ToolbarStarToggle(views::ButtonListener* listener) + : ToggleImageButton(listener), + profile_(NULL), + host_view_(NULL), + bubble_positioner_(NULL), + ignore_click_(false) { +} + +void ToolbarStarToggle::Init() { + set_tag(IDC_BOOKMARK_PAGE); + SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_STAR)); + SetToggledTooltipText(l10n_util::GetString(IDS_TOOLTIP_STARRED)); + SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_STAR)); + SetID(VIEW_ID_STAR_BUTTON); +} + +void ToolbarStarToggle::LoadImages() { + ThemeProvider* tp = profile_->GetThemeProvider(); + + // Load images. + SkColor color = tp->GetColor(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND); + SkBitmap* background = tp->GetBitmapNamed(IDR_THEME_BUTTON_BACKGROUND); + + SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_STAR)); + SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_STAR_H)); + SetImage(views::CustomButton::BS_PUSHED, tp->GetBitmapNamed(IDR_STAR_P)); + SetImage(views::CustomButton::BS_DISABLED, tp->GetBitmapNamed(IDR_STAR_D)); + SetToggledImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_STARRED)); + SetToggledImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_STARRED_H)); + SetToggledImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_STARRED_P)); + SetBackground(color, background, tp->GetBitmapNamed(IDR_STAR_MASK)); +} + +void ToolbarStarToggle::ShowStarBubble(const GURL& url, bool newly_bookmarked) { + gfx::Rect bounds(bubble_positioner_->GetLocationStackBounds()); + gfx::Point star_location; + views::View::ConvertPointToScreen(this, &star_location); + // The visual center of the star is not centered within the bounds. The star + // has a single central pixel; there are 13 pixels on the "inside" side of it + // (toward the location bar) and 16 on the "outside". This means we need to + // shift the bounds one pixel toward the location bar in order to place the + // star's outside edge at the horizontal center. However, even this isn't + // good enough in RTL mode, because the InfoBubble's arrow's central pixel is + // drawn with its left edge on the target rect center-line in both LTR and RTL + // modes. So in RTL mode, we need to shift the bounds one more pixel left, in + // order to place the star's central pixel on the right side of the bounds' + // center-line, so that the arrow's center will line up. + // + // TODO(pkasting): If the InfoBubble used mirroring transformations maybe this + // could become symmetric (-1 : 1). + bounds.set_x(star_location.x() + (UILayoutIsRightToLeft() ? -2 : 1)); + bounds.set_width(width()); + browser::ShowBookmarkBubbleView(host_view_->GetWindow(), bounds, this, + profile_, url, newly_bookmarked); +} + +bool ToolbarStarToggle::OnMousePressed(const views::MouseEvent& e) { + ignore_click_ = ((TimeTicks::Now() - bubble_closed_time_).InMilliseconds() < + kDisallowClickMS); + return ToggleImageButton::OnMousePressed(e); +} + +void ToolbarStarToggle::OnMouseReleased(const views::MouseEvent& e, + bool canceled) { + ToggleImageButton::OnMouseReleased(e, canceled); + ignore_click_ = false; +} + +void ToolbarStarToggle::OnDragDone() { + ToggleImageButton::OnDragDone(); + ignore_click_ = false; +} + +void ToolbarStarToggle::NotifyClick(const views::Event& event) { + if (!ignore_click_ && !browser::IsBookmarkBubbleViewShowing()) + ToggleImageButton::NotifyClick(event); +} + +SkBitmap ToolbarStarToggle::GetImageToPaint() { + if (browser::IsBookmarkBubbleViewShowing()) { + ResourceBundle &rb = ResourceBundle::GetSharedInstance(); + return *rb.GetBitmapNamed(IDR_STARRED_P); + } + return ImageButton::GetImageToPaint(); +} + +void ToolbarStarToggle::InfoBubbleClosing(InfoBubble* info_bubble, + bool closed_by_escape) { + SchedulePaint(); + bubble_closed_time_ = TimeTicks::Now(); +} + +bool ToolbarStarToggle::CloseOnEscape() { + return true; +} diff --git a/chrome/browser/views/toolbar_star_toggle.h b/chrome/browser/views/toolbar_star_toggle.h new file mode 100644 index 0000000..4966655 --- /dev/null +++ b/chrome/browser/views/toolbar_star_toggle.h @@ -0,0 +1,85 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VIEWS_TOOLBAR_STAR_TOGGLE_H_ +#define CHROME_BROWSER_VIEWS_TOOLBAR_STAR_TOGGLE_H_ + +#include "base/time.h" +#include "chrome/browser/views/info_bubble.h" +#include "views/controls/button/image_button.h" + +class BubblePositioner; +class GURL; +class Profile; + +namespace views { +class ButtonListener; +class View; +} // namespace views + +// ToolbarStarToggle is used for the star button on the toolbar, allowing the +// user to star the current page. ToolbarStarToggle manages showing the +// InfoBubble and rendering the appropriate state while the bubble is visible. + +class ToolbarStarToggle : public views::ToggleImageButton, + public InfoBubbleDelegate { + public: + explicit ToolbarStarToggle(views::ButtonListener* listener); + + void set_profile(Profile* profile) { profile_ = profile; } + void set_host_view(views::View* host_view) { host_view_ = host_view; } + void set_bubble_positioner(BubblePositioner* bubble_positioner) { + bubble_positioner_ = bubble_positioner; + } + + // Sets up all labels for the button. + void Init(); + + // Sets up all images for the button. + void LoadImages(); + + // If the bubble isn't showing, shows it. + void ShowStarBubble(const GURL& url, bool newly_bookmarked); + + // Overridden to update ignore_click_ based on whether the mouse was clicked + // quickly after the bubble was hidden. + virtual bool OnMousePressed(const views::MouseEvent& e); + + // Overridden to set ignore_click_ to false. + virtual void OnMouseReleased(const views::MouseEvent& e, bool canceled); + virtual void OnDragDone(); + + protected: + // Only invokes super if ignore_click_ is true and the bubble isn't showing. + virtual void NotifyClick(const views::Event& event); + + // Overridden to so that we appear pressed while the bubble is showing. + virtual SkBitmap GetImageToPaint(); + + private: + // InfoBubbleDelegate. + virtual void InfoBubbleClosing(InfoBubble* info_bubble, + bool closed_by_escape); + virtual bool CloseOnEscape(); + + // Profile with bookmarks info. + Profile* profile_; + + // View that hosts us. + views::View* host_view_; + + // Positioner for bookmark bubble. + BubblePositioner* bubble_positioner_; + + // Time the bubble last closed. + base::TimeTicks bubble_closed_time_; + + // If true NotifyClick does nothing. This is set in OnMousePressed based on + // the amount of time between when the bubble clicked and now. + bool ignore_click_; + + DISALLOW_COPY_AND_ASSIGN(ToolbarStarToggle); +}; + +#endif // CHROME_BROWSER_VIEWS_TOOLBAR_STAR_TOGGLE_H_ diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index e69ff0f..52854e67 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -4,20 +4,42 @@ #include "chrome/browser/views/toolbar_view.h" +#include <algorithm> +#include <string> + +#include "app/drag_drop_types.h" #include "app/l10n_util.h" +#include "app/os_exchange_data.h" #include "app/resource_bundle.h" #include "base/command_line.h" +#include "base/keyboard_codes.h" +#include "base/logging.h" +#include "base/path_service.h" #include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/character_encoding.h" +#include "chrome/browser/defaults.h" +#include "chrome/browser/encoding_menu_controller.h" +#include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" -#include "chrome/browser/view_ids.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/sync_ui_util.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/views/bookmark_menu_button.h" #include "chrome/browser/views/browser_actions_container.h" #include "chrome/browser/views/event_utils.h" #include "chrome/browser/views/frame/browser_view.h" +#include "chrome/browser/views/go_button.h" +#include "chrome/browser/views/location_bar_view.h" +#include "chrome/browser/views/toolbar_star_toggle.h" +#include "chrome/browser/view_ids.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" @@ -25,7 +47,12 @@ #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" +#include "net/base/net_util.h" +#include "views/background.h" #include "views/controls/button/button_dropdown.h" +#include "views/controls/label.h" +#include "views/controls/menu/menu_2.h" +#include "views/drag_utils.h" #include "views/focus/view_storage.h" #include "views/widget/tooltip_manager.h" #include "views/window/non_client_view.h" @@ -55,8 +82,9 @@ ToolbarView::ToolbarView(Browser* browser) : model_(browser->toolbar_model()), back_(NULL), forward_(NULL), - home_(NULL), reload_(NULL), + home_(NULL), + star_(NULL), location_bar_(NULL), go_(NULL), browser_actions_(NULL), @@ -72,8 +100,9 @@ ToolbarView::ToolbarView(Browser* browser) SetID(VIEW_ID_TOOLBAR); browser_->command_updater()->AddCommandObserver(IDC_BACK, this); browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this); - browser_->command_updater()->AddCommandObserver(IDC_HOME, this); browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this); + browser_->command_updater()->AddCommandObserver(IDC_HOME, this); + browser_->command_updater()->AddCommandObserver(IDC_BOOKMARK_PAGE, this); if (browser->type() == Browser::TYPE_NORMAL) display_mode_ = DISPLAYMODE_NORMAL; else @@ -267,11 +296,14 @@ void ToolbarView::EnabledStateChangedForCommand(int id, bool enabled) { case IDC_FORWARD: button = forward_; break; + case IDC_RELOAD: + button = reload_; + break; case IDC_HOME: button = home_; break; - case IDC_RELOAD: - button = reload_; + case IDC_BOOKMARK_PAGE: + button = star_; break; } if (button) @@ -281,8 +313,8 @@ void ToolbarView::EnabledStateChangedForCommand(int id, bool enabled) { //////////////////////////////////////////////////////////////////////////////// // ToolbarView, views::Button::ButtonListener implementation: -void ToolbarView::ButtonPressed(views::Button* sender, - const views::Event& event) { +void ToolbarView::ButtonPressed( + views::Button* sender, const views::Event& event) { int id = sender->tag(); switch (id) { case IDC_BACK: @@ -305,6 +337,30 @@ void ToolbarView::ButtonPressed(views::Button* sender, } //////////////////////////////////////////////////////////////////////////////// +// ToolbarView, BubblePositioner implementation: + +gfx::Rect ToolbarView::GetLocationStackBounds() const { + // The number of pixels from the left or right edges of the location stack to + // "just inside the visible borders". When the omnibox bubble contents are + // aligned with this, the visible borders tacked on to the outsides will line + // up with the visible borders on the location stack. + const int kLocationStackEdgeWidth = 2; + + gfx::Point origin; + views::View::ConvertPointToScreen(star_, &origin); + gfx::Rect stack_bounds(origin.x(), origin.y(), + star_->width() + location_bar_->width() + go_->width(), + location_bar_->height()); + if (UILayoutIsRightToLeft()) { + stack_bounds.set_x( + stack_bounds.x() - location_bar_->width() - go_->width()); + } + // Inset the bounds to just inside the visible edges (see comment above). + stack_bounds.Inset(kLocationStackEdgeWidth, 0); + return stack_bounds; +} + +//////////////////////////////////////////////////////////////////////////////// // ToolbarView, NotificationObserver implementation: void ToolbarView::Observe(NotificationType type, @@ -400,12 +456,11 @@ gfx::Size ToolbarView::GetPreferredSize() { if (IsDisplayModeNormal()) { int min_width = kControlIndent + back_->GetPreferredSize().width() + forward_->GetPreferredSize().width() + kControlHorizOffset + - (show_home_button_.GetValue() ? - (home_->GetPreferredSize().width() + kControlHorizOffset) : 0) + - reload_->GetPreferredSize().width() + - browser_actions_->GetPreferredSize().width() + - go_->GetPreferredSize().width() + + reload_->GetPreferredSize().width() + (show_home_button_.GetValue() ? + (home_->GetPreferredSize().width() + kControlHorizOffset) : 0) + + star_->GetPreferredSize().width() + go_->GetPreferredSize().width() + kMenuButtonOffset + + browser_actions_->GetPreferredSize().width() + (bookmark_menu_ ? bookmark_menu_->GetPreferredSize().width() : 0) + page_menu_->GetPreferredSize().width() + app_menu_->GetPreferredSize().width() + kPaddingRight; @@ -460,18 +515,21 @@ void ToolbarView::Layout() { forward_->SetBounds(back_->x() + back_->width(), child_y, forward_->GetPreferredSize().width(), child_height); + reload_->SetBounds(forward_->x() + forward_->width() + kControlHorizOffset, + child_y, reload_->GetPreferredSize().width(), + child_height); + if (show_home_button_.GetValue()) { home_->SetVisible(true); - home_->SetBounds(forward_->x() + forward_->width() + kControlHorizOffset, + home_->SetBounds(reload_->x() + reload_->width() + kControlHorizOffset, child_y, home_->GetPreferredSize().width(), child_height); } else { home_->SetVisible(false); - home_->SetBounds(forward_->x() + forward_->width(), child_y, 0, - child_height); + home_->SetBounds(reload_->x() + reload_->width(), child_y, 0, child_height); } - reload_->SetBounds(home_->x() + home_->width() + kControlHorizOffset, child_y, - reload_->GetPreferredSize().width(), child_height); + star_->SetBounds(home_->x() + home_->width() + kControlHorizOffset, + child_y, star_->GetPreferredSize().width(), child_height); int go_button_width = go_->GetPreferredSize().width(); int browser_actions_width = browser_actions_->GetPreferredSize().width(); @@ -479,7 +537,7 @@ void ToolbarView::Layout() { int app_menu_width = app_menu_->GetPreferredSize().width(); int bookmark_menu_width = bookmark_menu_ ? bookmark_menu_->GetPreferredSize().width() : 0; - int location_x = reload_->x() + reload_->width(); + int location_x = star_->x() + star_->width(); int available_width = width() - kPaddingRight - bookmark_menu_width - app_menu_width - page_menu_width - browser_actions_width - kMenuButtonOffset - go_button_width - location_x; @@ -546,6 +604,51 @@ void ToolbarView::ThemeChanged() { } //////////////////////////////////////////////////////////////////////////////// +// ToolbarView, views::DragController implementation: + +void ToolbarView::WriteDragData(views::View* sender, + const gfx::Point& press_pt, + OSExchangeData* data) { + DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE); + + UserMetrics::RecordAction(UserMetricsAction("Toolbar_DragStar"), profile_); + + // If there is a bookmark for the URL, add the bookmark drag data for it. We + // do this to ensure the bookmark is moved, rather than creating an new + // bookmark. + TabContents* tab = browser_->GetSelectedTabContents(); + if (tab) { + if (profile_ && profile_->GetBookmarkModel()) { + const BookmarkNode* node = profile_->GetBookmarkModel()-> + GetMostRecentlyAddedNodeForURL(tab->GetURL()); + if (node) { + BookmarkDragData bookmark_data(node); + bookmark_data.Write(profile_, data); + } + } + + drag_utils::SetURLAndDragImage(tab->GetURL(), + UTF16ToWideHack(tab->GetTitle()), + tab->GetFavIcon(), + data); + } +} + +int ToolbarView::GetDragOperations(views::View* sender, const gfx::Point& p) { + DCHECK(sender == star_); + TabContents* tab = browser_->GetSelectedTabContents(); + if (!tab || !tab->ShouldDisplayURL() || !tab->GetURL().is_valid()) { + return DragDropTypes::DRAG_NONE; + } + if (profile_ && profile_->GetBookmarkModel() && + profile_->GetBookmarkModel()->IsBookmarked(tab->GetURL())) { + return DragDropTypes::DRAG_MOVE | DragDropTypes::DRAG_COPY | + DragDropTypes::DRAG_LINK; + } + return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK; +} + +//////////////////////////////////////////////////////////////////////////////// // ToolbarView, private: int ToolbarView::PopupTopSpacing() const { @@ -572,6 +675,12 @@ void ToolbarView::CreateLeftSideControls() { forward_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_FORWARD)); forward_->SetID(VIEW_ID_FORWARD_BUTTON); + reload_ = new views::ImageButton(this); + reload_->set_tag(IDC_RELOAD); + reload_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_RELOAD)); + reload_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_RELOAD)); + reload_->SetID(VIEW_ID_RELOAD_BUTTON); + home_ = new views::ImageButton(this); home_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN | views::Event::EF_MIDDLE_BUTTON_DOWN); @@ -584,19 +693,22 @@ void ToolbarView::CreateLeftSideControls() { AddChildView(back_); AddChildView(forward_); + AddChildView(reload_); AddChildView(home_); } void ToolbarView::CreateCenterStack(Profile *profile) { - reload_ = new views::ImageButton(this); - reload_->set_tag(IDC_RELOAD); - reload_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_RELOAD)); - reload_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_RELOAD)); - reload_->SetID(VIEW_ID_RELOAD_BUTTON); + star_ = new ToolbarStarToggle(this); + star_->SetDragController(this); + star_->set_profile(profile); + star_->set_host_view(this); + star_->set_bubble_positioner(this); + star_->Init(); location_bar_ = new LocationBarView(profile, browser_->command_updater(), model_, this, - display_mode_ == DISPLAYMODE_LOCATION); + display_mode_ == DISPLAYMODE_LOCATION, + this); // The Go button. go_ = new GoButton(location_bar_, browser_); @@ -605,7 +717,7 @@ void ToolbarView::CreateCenterStack(Profile *profile) { LoadCenterStackImages(); - AddChildView(reload_); + AddChildView(star_); location_bar_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_LOCATION)); AddChildView(location_bar_); location_bar_->Init(); @@ -667,6 +779,15 @@ void ToolbarView::LoadLeftSideControlsImages() { forward_->SetBackground(color, background, tp->GetBitmapNamed(IDR_FORWARD_MASK)); + reload_->SetImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_RELOAD)); + reload_->SetImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_RELOAD_H)); + reload_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_RELOAD_P)); + reload_->SetBackground(color, background, + tp->GetBitmapNamed(IDR_BUTTON_MASK)); + home_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_HOME)); home_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_HOME_H)); home_->SetImage(views::CustomButton::BS_PUSHED, @@ -676,20 +797,13 @@ void ToolbarView::LoadLeftSideControlsImages() { } void ToolbarView::LoadCenterStackImages() { + star_->LoadImages(); + ThemeProvider* tp = GetThemeProvider(); SkColor color = tp->GetColor(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND); SkBitmap* background = tp->GetBitmapNamed(IDR_THEME_BUTTON_BACKGROUND); - reload_->SetImage(views::CustomButton::BS_NORMAL, - tp->GetBitmapNamed(IDR_RELOAD)); - reload_->SetImage(views::CustomButton::BS_HOT, - tp->GetBitmapNamed(IDR_RELOAD_H)); - reload_->SetImage(views::CustomButton::BS_PUSHED, - tp->GetBitmapNamed(IDR_RELOAD_P)); - reload_->SetBackground(color, background, - tp->GetBitmapNamed(IDR_RELOAD_MASK)); - go_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_GO)); go_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_GO_H)); go_->SetImage(views::CustomButton::BS_PUSHED, tp->GetBitmapNamed(IDR_GO_P)); diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h index 6e45799..62faebf 100644 --- a/chrome/browser/views/toolbar_view.h +++ b/chrome/browser/views/toolbar_view.h @@ -11,6 +11,7 @@ #include "base/scoped_ptr.h" #include "chrome/browser/app_menu_model.h" #include "chrome/browser/back_forward_menu_model.h" +#include "chrome/browser/bubble_positioner.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/page_menu_model.h" #include "chrome/browser/pref_member.h" @@ -26,6 +27,7 @@ class BrowserActionsContainer; class Browser; class Profile; +class ToolbarStarToggle; namespace views { class Menu2; @@ -34,12 +36,14 @@ class Menu2; // The Browser Window's toolbar. class ToolbarView : public AccessibleToolbarView, public views::ViewMenuDelegate, + public views::DragController, public views::FocusChangeListener, public menus::SimpleMenuModel::Delegate, public LocationBarView::Delegate, public NotificationObserver, public CommandUpdater::CommandObserver, - public views::ButtonListener { + public views::ButtonListener, + public BubblePositioner { public: explicit ToolbarView(Browser* browser); virtual ~ToolbarView(); @@ -82,6 +86,7 @@ class ToolbarView : public AccessibleToolbarView, // Accessors... Browser* browser() const { return browser_; } BrowserActionsContainer* browser_actions() const { return browser_actions_; } + ToolbarStarToggle* star_button() const { return star_; } GoButton* go_button() const { return go_; } LocationBarView* location_bar() const { return location_bar_; } views::MenuButton* page_menu() const { return page_menu_; } @@ -110,6 +115,9 @@ class ToolbarView : public AccessibleToolbarView, // Overridden from views::BaseButton::ButtonListener: virtual void ButtonPressed(views::Button* sender, const views::Event& event); + // BubblePositioner: + virtual gfx::Rect GetLocationStackBounds() const; + // Overridden from NotificationObserver: virtual void Observe(NotificationType type, const NotificationSource& source, @@ -130,6 +138,17 @@ class ToolbarView : public AccessibleToolbarView, virtual void ThemeChanged(); private: + // Overridden from views::DragController: + virtual void WriteDragData(View* sender, + const gfx::Point& press_pt, + OSExchangeData* data); + virtual int GetDragOperations(View* sender, const gfx::Point& p); + virtual bool CanStartDrag(View* sender, + const gfx::Point& press_pt, + const gfx::Point& p) { + return true; + } + // Returns the number of pixels above the location bar in non-normal display. int PopupTopSpacing() const; @@ -179,8 +198,9 @@ class ToolbarView : public AccessibleToolbarView, // Controls views::ImageButton* back_; views::ImageButton* forward_; - views::ImageButton* home_; views::ImageButton* reload_; + views::ImageButton* home_; + ToolbarStarToggle* star_; LocationBarView* location_bar_; GoButton* go_; BrowserActionsContainer* browser_actions_; diff --git a/chrome/browser/views/url_picker.cc b/chrome/browser/views/url_picker.cc index 3d275d4..5f82832 100644 --- a/chrome/browser/views/url_picker.cc +++ b/chrome/browser/views/url_picker.cc @@ -221,10 +221,10 @@ void UrlPicker::OnSelectionChanged() { if (selection >= 0 && selection < url_table_model_->RowCount()) { std::wstring languages = profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); - // Because the url_field_ is user-editable, we don't strip anything. + // Because the url_field_ is user-editable, we set the URL with + // username:password and escaped path and query. std::wstring formatted = net::FormatUrl(url_table_model_->GetURL(selection), - languages, net::kFormatUrlOmitNothing, UnescapeRule::NONE, NULL, NULL, - NULL); + languages, false, UnescapeRule::NONE, NULL, NULL, NULL); url_field_->SetText(formatted); GetDialogClientView()->UpdateDialogButtons(); } |