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 |