summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views')
-rw-r--r--chrome/browser/views/accelerator_table_gtk.cc3
-rw-r--r--chrome/browser/views/app_launcher.cc76
-rw-r--r--chrome/browser/views/app_launcher.h16
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc149
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h6
-rw-r--r--chrome/browser/views/bookmark_editor_view.cc5
-rw-r--r--chrome/browser/views/browser_views_accessibility_browsertest.cc5
-rw-r--r--chrome/browser/views/bubble_border.cc107
-rw-r--r--chrome/browser/views/bubble_border.h33
-rw-r--r--chrome/browser/views/constrained_window_win.cc20
-rw-r--r--chrome/browser/views/frame/browser_frame_win.cc6
-rw-r--r--chrome/browser/views/frame/browser_root_view.cc15
-rw-r--r--chrome/browser/views/frame/browser_view.cc32
-rw-r--r--chrome/browser/views/frame/glass_browser_frame_view.cc47
-rw-r--r--chrome/browser/views/frame/opaque_browser_frame_view.cc88
-rw-r--r--chrome/browser/views/info_bubble.cc74
-rw-r--r--chrome/browser/views/info_bubble.h77
-rw-r--r--chrome/browser/views/location_bar_view.cc1254
-rw-r--r--chrome/browser/views/location_bar_view.h327
-rw-r--r--chrome/browser/views/pinned_contents_info_bubble.cc74
-rw-r--r--chrome/browser/views/pinned_contents_info_bubble.h89
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.cc9
-rw-r--r--chrome/browser/views/tabs/tab_renderer.cc204
-rw-r--r--chrome/browser/views/tabs/tab_renderer.h52
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc1369
-rw-r--r--chrome/browser/views/tabs/tab_strip.h248
-rw-r--r--chrome/browser/views/toolbar_star_toggle.cc133
-rw-r--r--chrome/browser/views/toolbar_star_toggle.h85
-rw-r--r--chrome/browser/views/toolbar_view.cc182
-rw-r--r--chrome/browser/views/toolbar_view.h24
-rw-r--r--chrome/browser/views/url_picker.cc6
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();
}