| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/tabs/tab_strip.h" | 5 #include "chrome/browser/ui/views/tabs/tab_strip.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/stl_util-inl.h" | 12 #include "base/stl_util-inl.h" |
| 13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "chrome/browser/defaults.h" | |
| 15 #include "chrome/browser/tabs/tab_strip_selection_model.h" | 14 #include "chrome/browser/tabs/tab_strip_selection_model.h" |
| 16 #include "chrome/browser/themes/theme_service.h" | 15 #include "chrome/browser/themes/theme_service.h" |
| 17 #include "chrome/browser/ui/view_ids.h" | 16 #include "chrome/browser/ui/view_ids.h" |
| 18 #include "chrome/browser/ui/views/tabs/tab.h" | 17 #include "chrome/browser/ui/views/tabs/tab.h" |
| 19 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" | 18 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" |
| 20 #include "grit/generated_resources.h" | 19 #include "grit/generated_resources.h" |
| 21 #include "grit/theme_resources.h" | 20 #include "grit/theme_resources.h" |
| 22 #include "grit/theme_resources_standard.h" | 21 #include "grit/theme_resources_standard.h" |
| 23 #include "ui/base/accessibility/accessible_view_state.h" | 22 #include "ui/base/accessibility/accessible_view_state.h" |
| 24 #include "ui/base/animation/animation_container.h" | 23 #include "ui/base/animation/animation_container.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 69 |
| 71 namespace { | 70 namespace { |
| 72 | 71 |
| 73 /////////////////////////////////////////////////////////////////////////////// | 72 /////////////////////////////////////////////////////////////////////////////// |
| 74 // NewTabButton | 73 // NewTabButton |
| 75 // | 74 // |
| 76 // A subclass of button that hit-tests to the shape of the new tab button. | 75 // A subclass of button that hit-tests to the shape of the new tab button. |
| 77 | 76 |
| 78 class NewTabButton : public views::ImageButton { | 77 class NewTabButton : public views::ImageButton { |
| 79 public: | 78 public: |
| 80 explicit NewTabButton(views::ButtonListener* listener) | 79 explicit NewTabButton(TabStrip* tab_strip, views::ButtonListener* listener) |
| 81 : views::ImageButton(listener) { | 80 : views::ImageButton(listener), |
| 81 tab_strip_(tab_strip) { |
| 82 } | 82 } |
| 83 virtual ~NewTabButton() {} | 83 virtual ~NewTabButton() {} |
| 84 | 84 |
| 85 protected: | 85 protected: |
| 86 // Overridden from views::View: | 86 // Overridden from views::View: |
| 87 virtual bool HasHitTestMask() const { | 87 virtual bool HasHitTestMask() const { |
| 88 // When the button is sized to the top of the tab strip we want the user to | 88 // When the button is sized to the top of the tab strip we want the user to |
| 89 // be able to click on complete bounds, and so don't return a custom hit | 89 // be able to click on complete bounds, and so don't return a custom hit |
| 90 // mask. | 90 // mask. |
| 91 return !browser_defaults::kSizeTabButtonToTopOfTabStrip; | 91 return !tab_strip_->SizeTabButtonToTopOfTabStrip(); |
| 92 } | 92 } |
| 93 virtual void GetHitTestMask(gfx::Path* path) const { | 93 virtual void GetHitTestMask(gfx::Path* path) const { |
| 94 DCHECK(path); | 94 DCHECK(path); |
| 95 | 95 |
| 96 SkScalar w = SkIntToScalar(width()); | 96 SkScalar w = SkIntToScalar(width()); |
| 97 | 97 |
| 98 // These values are defined by the shape of the new tab bitmap. Should that | 98 // These values are defined by the shape of the new tab bitmap. Should that |
| 99 // bitmap ever change, these values will need to be updated. They're so | 99 // bitmap ever change, these values will need to be updated. They're so |
| 100 // custom it's not really worth defining constants for. | 100 // custom it's not really worth defining constants for. |
| 101 path->moveTo(0, 1); | 101 path->moveTo(0, 1); |
| 102 path->lineTo(w - 7, 1); | 102 path->lineTo(w - 7, 1); |
| 103 path->lineTo(w - 4, 4); | 103 path->lineTo(w - 4, 4); |
| 104 path->lineTo(w, 16); | 104 path->lineTo(w, 16); |
| 105 path->lineTo(w - 1, 17); | 105 path->lineTo(w - 1, 17); |
| 106 path->lineTo(7, 17); | 106 path->lineTo(7, 17); |
| 107 path->lineTo(4, 13); | 107 path->lineTo(4, 13); |
| 108 path->lineTo(0, 1); | 108 path->lineTo(0, 1); |
| 109 path->close(); | 109 path->close(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 private: | 112 private: |
| 113 // Tab strip that contains this button. |
| 114 TabStrip* tab_strip_; |
| 115 |
| 113 DISALLOW_COPY_AND_ASSIGN(NewTabButton); | 116 DISALLOW_COPY_AND_ASSIGN(NewTabButton); |
| 114 }; | 117 }; |
| 115 | 118 |
| 116 } // namespace | 119 } // namespace |
| 117 | 120 |
| 118 /////////////////////////////////////////////////////////////////////////////// | 121 /////////////////////////////////////////////////////////////////////////////// |
| 119 // TabStrip, public: | 122 // TabStrip, public: |
| 120 | 123 |
| 121 // static | 124 // static |
| 122 const int TabStrip::mini_to_non_mini_gap_ = 3; | 125 const int TabStrip::mini_to_non_mini_gap_ = 3; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 142 // Make sure we unhook ourselves as a message loop observer so that we don't | 145 // Make sure we unhook ourselves as a message loop observer so that we don't |
| 143 // crash in the case where the user closes the window after closing a tab | 146 // crash in the case where the user closes the window after closing a tab |
| 144 // but before moving the mouse. | 147 // but before moving the mouse. |
| 145 RemoveMessageLoopObserver(); | 148 RemoveMessageLoopObserver(); |
| 146 | 149 |
| 147 // The children (tabs) may callback to us from their destructor. Delete them | 150 // The children (tabs) may callback to us from their destructor. Delete them |
| 148 // so that if they call back we aren't in a weird state. | 151 // so that if they call back we aren't in a weird state. |
| 149 RemoveAllChildViews(true); | 152 RemoveAllChildViews(true); |
| 150 } | 153 } |
| 151 | 154 |
| 152 void TabStrip::InitTabStripButtons() { | |
| 153 newtab_button_ = new NewTabButton(this); | |
| 154 if (browser_defaults::kSizeTabButtonToTopOfTabStrip) { | |
| 155 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | |
| 156 views::ImageButton::ALIGN_BOTTOM); | |
| 157 } | |
| 158 LoadNewTabButtonImage(); | |
| 159 newtab_button_->SetAccessibleName( | |
| 160 l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); | |
| 161 AddChildView(newtab_button_); | |
| 162 } | |
| 163 | |
| 164 gfx::Rect TabStrip::GetNewTabButtonBounds() { | 155 gfx::Rect TabStrip::GetNewTabButtonBounds() { |
| 165 return newtab_button_->bounds(); | 156 return newtab_button_->bounds(); |
| 166 } | 157 } |
| 167 | 158 |
| 159 bool TabStrip::SizeTabButtonToTopOfTabStrip() { |
| 160 return controller()->SizeTabButtonToTopOfTabStrip(); |
| 161 } |
| 162 |
| 168 void TabStrip::MouseMovedOutOfView() { | 163 void TabStrip::MouseMovedOutOfView() { |
| 169 ResizeLayoutTabs(); | 164 ResizeLayoutTabs(); |
| 170 } | 165 } |
| 171 | 166 |
| 172 //////////////////////////////////////////////////////////////////////////////// | 167 //////////////////////////////////////////////////////////////////////////////// |
| 173 // TabStrip, AbstractTabStripView implementation: | 168 // TabStrip, AbstractTabStripView implementation: |
| 174 | 169 |
| 175 bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) { | 170 bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) { |
| 176 views::View* v = GetEventHandlerForPoint(point); | 171 views::View* v = GetEventHandlerForPoint(point); |
| 177 | 172 |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 469 } |
| 475 | 470 |
| 476 bool TabStrip::ShouldHighlightCloseButtonAfterRemove() { | 471 bool TabStrip::ShouldHighlightCloseButtonAfterRemove() { |
| 477 return in_tab_close_; | 472 return in_tab_close_; |
| 478 } | 473 } |
| 479 | 474 |
| 480 void TabStrip::DoLayout() { | 475 void TabStrip::DoLayout() { |
| 481 BaseTabStrip::DoLayout(); | 476 BaseTabStrip::DoLayout(); |
| 482 | 477 |
| 483 // It is possible we don't have a new tab button yet. | 478 // It is possible we don't have a new tab button yet. |
| 484 if (newtab_button_) | 479 if (newtab_button_) { |
| 480 if (SizeTabButtonToTopOfTabStrip()) { |
| 481 newtab_button_bounds_.set_height( |
| 482 kNewTabButtonHeight + kNewTabButtonVOffset); |
| 483 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
| 484 views::ImageButton::ALIGN_BOTTOM); |
| 485 } else { |
| 486 newtab_button_bounds_.set_height(kNewTabButtonHeight); |
| 487 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
| 488 views::ImageButton::ALIGN_TOP); |
| 489 } |
| 485 newtab_button_->SetBoundsRect(newtab_button_bounds_); | 490 newtab_button_->SetBoundsRect(newtab_button_bounds_); |
| 491 } |
| 486 } | 492 } |
| 487 | 493 |
| 488 void TabStrip::LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, | 494 void TabStrip::LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, |
| 489 BaseTab* active_tab, | 495 BaseTab* active_tab, |
| 490 const gfx::Point& location, | 496 const gfx::Point& location, |
| 491 bool initial_drag) { | 497 bool initial_drag) { |
| 492 std::vector<gfx::Rect> bounds; | 498 std::vector<gfx::Rect> bounds; |
| 493 CalculateBoundsForDraggedTabs(tabs, &bounds); | 499 CalculateBoundsForDraggedTabs(tabs, &bounds); |
| 494 DCHECK_EQ(tabs.size(), bounds.size()); | 500 DCHECK_EQ(tabs.size(), bounds.size()); |
| 495 int active_tab_model_index = GetModelIndexOfBaseTab(active_tab); | 501 int active_tab_model_index = GetModelIndexOfBaseTab(active_tab); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 if (sender == newtab_button_) | 561 if (sender == newtab_button_) |
| 556 controller()->CreateNewTab(); | 562 controller()->CreateNewTab(); |
| 557 } | 563 } |
| 558 | 564 |
| 559 /////////////////////////////////////////////////////////////////////////////// | 565 /////////////////////////////////////////////////////////////////////////////// |
| 560 // TabStrip, private: | 566 // TabStrip, private: |
| 561 | 567 |
| 562 void TabStrip::Init() { | 568 void TabStrip::Init() { |
| 563 set_id(VIEW_ID_TAB_STRIP); | 569 set_id(VIEW_ID_TAB_STRIP); |
| 564 newtab_button_bounds_.SetRect(0, 0, kNewTabButtonWidth, kNewTabButtonHeight); | 570 newtab_button_bounds_.SetRect(0, 0, kNewTabButtonWidth, kNewTabButtonHeight); |
| 565 if (browser_defaults::kSizeTabButtonToTopOfTabStrip) { | |
| 566 newtab_button_bounds_.set_height( | |
| 567 kNewTabButtonHeight + kNewTabButtonVOffset); | |
| 568 } | |
| 569 if (drop_indicator_width == 0) { | 571 if (drop_indicator_width == 0) { |
| 570 // Direction doesn't matter, both images are the same size. | 572 // Direction doesn't matter, both images are the same size. |
| 571 SkBitmap* drop_image = GetDropArrowImage(true); | 573 SkBitmap* drop_image = GetDropArrowImage(true); |
| 572 drop_indicator_width = drop_image->width(); | 574 drop_indicator_width = drop_image->width(); |
| 573 drop_indicator_height = drop_image->height(); | 575 drop_indicator_height = drop_image->height(); |
| 574 } | 576 } |
| 575 } | 577 } |
| 576 | 578 |
| 579 void TabStrip::InitTabStripButtons() { |
| 580 newtab_button_ = new NewTabButton(this, this); |
| 581 LoadNewTabButtonImage(); |
| 582 newtab_button_->SetAccessibleName( |
| 583 l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); |
| 584 AddChildView(newtab_button_); |
| 585 } |
| 586 |
| 577 void TabStrip::LoadNewTabButtonImage() { | 587 void TabStrip::LoadNewTabButtonImage() { |
| 578 ui::ThemeProvider* tp = GetThemeProvider(); | 588 ui::ThemeProvider* tp = GetThemeProvider(); |
| 579 | 589 |
| 580 // If we don't have a theme provider yet, it means we do not have a | 590 // If we don't have a theme provider yet, it means we do not have a |
| 581 // root view, and are therefore in a test. | 591 // root view, and are therefore in a test. |
| 582 bool in_test = false; | 592 bool in_test = false; |
| 583 if (tp == NULL) { | 593 if (tp == NULL) { |
| 584 tp = new views::DefaultThemeProvider(); | 594 tp = new views::DefaultThemeProvider(); |
| 585 in_test = true; | 595 in_test = true; |
| 586 } | 596 } |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 set_ideal_bounds(i, | 941 set_ideal_bounds(i, |
| 932 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, | 942 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, |
| 933 tab_height)); | 943 tab_height)); |
| 934 tab_x = end_of_tab + kTabHOffset; | 944 tab_x = end_of_tab + kTabHOffset; |
| 935 last_was_mini = tab->data().mini; | 945 last_was_mini = tab->data().mini; |
| 936 } | 946 } |
| 937 } | 947 } |
| 938 | 948 |
| 939 // Update bounds of new tab button. | 949 // Update bounds of new tab button. |
| 940 int new_tab_x; | 950 int new_tab_x; |
| 941 int new_tab_y = browser_defaults::kSizeTabButtonToTopOfTabStrip ? | 951 int new_tab_y = SizeTabButtonToTopOfTabStrip() ? 0 : kNewTabButtonVOffset; |
| 942 0 : kNewTabButtonVOffset; | |
| 943 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && | 952 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && |
| 944 !in_tab_close_) { | 953 !in_tab_close_) { |
| 945 // We're shrinking tabs, so we need to anchor the New Tab button to the | 954 // We're shrinking tabs, so we need to anchor the New Tab button to the |
| 946 // right edge of the TabStrip's bounds, rather than the right edge of the | 955 // right edge of the TabStrip's bounds, rather than the right edge of the |
| 947 // right-most Tab, otherwise it'll bounce when animating. | 956 // right-most Tab, otherwise it'll bounce when animating. |
| 948 new_tab_x = width() - newtab_button_bounds_.width(); | 957 new_tab_x = width() - newtab_button_bounds_.width(); |
| 949 } else { | 958 } else { |
| 950 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; | 959 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; |
| 951 } | 960 } |
| 952 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); | 961 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 } | 1035 } |
| 1027 return mini_count; | 1036 return mini_count; |
| 1028 } | 1037 } |
| 1029 | 1038 |
| 1030 bool TabStrip::IsPointInTab(Tab* tab, | 1039 bool TabStrip::IsPointInTab(Tab* tab, |
| 1031 const gfx::Point& point_in_tabstrip_coords) { | 1040 const gfx::Point& point_in_tabstrip_coords) { |
| 1032 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); | 1041 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); |
| 1033 View::ConvertPointToView(this, tab, &point_in_tab_coords); | 1042 View::ConvertPointToView(this, tab, &point_in_tab_coords); |
| 1034 return tab->HitTest(point_in_tab_coords); | 1043 return tab->HitTest(point_in_tab_coords); |
| 1035 } | 1044 } |
| OLD | NEW |