OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" | 25 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" |
26 #include "chrome/browser/ui/views/tabs/touch_tab_strip_layout.h" | 26 #include "chrome/browser/ui/views/tabs/touch_tab_strip_layout.h" |
27 #include "grit/generated_resources.h" | 27 #include "grit/generated_resources.h" |
28 #include "grit/theme_resources.h" | 28 #include "grit/theme_resources.h" |
29 #include "grit/theme_resources_standard.h" | 29 #include "grit/theme_resources_standard.h" |
30 #include "ui/base/accessibility/accessible_view_state.h" | 30 #include "ui/base/accessibility/accessible_view_state.h" |
31 #include "ui/base/animation/animation_container.h" | 31 #include "ui/base/animation/animation_container.h" |
32 #include "ui/base/animation/throb_animation.h" | 32 #include "ui/base/animation/throb_animation.h" |
33 #include "ui/base/dragdrop/drag_drop_types.h" | 33 #include "ui/base/dragdrop/drag_drop_types.h" |
34 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
| 35 #include "ui/base/layout.h" |
35 #include "ui/base/resource/resource_bundle.h" | 36 #include "ui/base/resource/resource_bundle.h" |
36 #include "ui/base/touch/touch_mode_support.h" | 37 #include "ui/base/touch/touch_mode_support.h" |
37 #include "ui/gfx/canvas.h" | 38 #include "ui/gfx/canvas.h" |
38 #include "ui/gfx/path.h" | 39 #include "ui/gfx/path.h" |
39 #include "ui/gfx/screen.h" | 40 #include "ui/gfx/screen.h" |
40 #include "ui/gfx/size.h" | 41 #include "ui/gfx/size.h" |
41 #include "ui/gfx/skbitmap_operations.h" | 42 #include "ui/gfx/skbitmap_operations.h" |
42 #include "ui/views/controls/image_view.h" | 43 #include "ui/views/controls/image_view.h" |
43 #include "ui/views/mouse_watcher_view_host.h" | 44 #include "ui/views/mouse_watcher_view_host.h" |
44 #include "ui/views/view_model_utils.h" | 45 #include "ui/views/view_model_utils.h" |
45 #include "ui/views/widget/default_theme_provider.h" | 46 #include "ui/views/widget/default_theme_provider.h" |
46 #include "ui/views/widget/root_view.h" | 47 #include "ui/views/widget/root_view.h" |
47 #include "ui/views/widget/widget.h" | 48 #include "ui/views/widget/widget.h" |
48 #include "ui/views/window/non_client_view.h" | 49 #include "ui/views/window/non_client_view.h" |
49 | 50 |
50 #if defined(OS_WIN) | 51 #if defined(OS_WIN) |
51 #include "ui/base/win/hwnd_util.h" | 52 #include "ui/base/win/hwnd_util.h" |
52 #include "ui/views/widget/monitor_win.h" | 53 #include "ui/views/widget/monitor_win.h" |
53 #endif | 54 #endif |
54 | 55 |
55 using views::DropTargetEvent; | 56 using views::DropTargetEvent; |
56 | 57 |
57 // Offset for the new tab button to bring it closer to the rightmost tab. | 58 namespace { |
58 #if defined(USE_ASH) | 59 |
59 static const int kNewTabButtonHOffset = -11; | |
60 static const int kNewTabButtonVOffset = 7; | |
61 #else | |
62 static const int kNewTabButtonHOffset = -5; | |
63 static const int kNewTabButtonVOffset = 5; | |
64 #endif | |
65 // Amount the left edge of a tab is offset from the rectangle of the tab's | |
66 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. | |
67 #if defined(USE_ASH) | |
68 static const int kTabHOffset = -27; | |
69 #else | |
70 static const int kTabHOffset = -16; | |
71 #endif | |
72 static const int kTabStripAnimationVSlop = 40; | 60 static const int kTabStripAnimationVSlop = 40; |
73 // Inactive tabs in a native frame are slightly transparent. | 61 // Inactive tabs in a native frame are slightly transparent. |
74 static const int kNativeFrameInactiveTabAlpha = 200; | 62 static const int kNativeFrameInactiveTabAlpha = 200; |
75 // If there are multiple tabs selected then make non-selected inactive tabs | 63 // If there are multiple tabs selected then make non-selected inactive tabs |
76 // even more transparent. | 64 // even more transparent. |
77 static const int kNativeFrameInactiveTabAlphaMultiSelection = 150; | 65 static const int kNativeFrameInactiveTabAlphaMultiSelection = 150; |
78 | 66 |
79 // Inverse ratio of the width of a tab edge to the width of the tab. When | 67 // Inverse ratio of the width of a tab edge to the width of the tab. When |
80 // hovering over the left or right edge of a tab, the drop indicator will | 68 // hovering over the left or right edge of a tab, the drop indicator will |
81 // point between tabs. | 69 // point between tabs. |
82 static const int kTabEdgeRatioInverse = 4; | 70 static const int kTabEdgeRatioInverse = 4; |
83 | 71 |
84 // Size of the drop indicator. | 72 // Size of the drop indicator. |
85 static int drop_indicator_width; | 73 static int drop_indicator_width; |
86 static int drop_indicator_height; | 74 static int drop_indicator_height; |
87 | 75 |
88 static inline int Round(double x) { | 76 static inline int Round(double x) { |
89 // Why oh why is this not in a standard header? | 77 // Why oh why is this not in a standard header? |
90 return static_cast<int>(floor(x + 0.5)); | 78 return static_cast<int>(floor(x + 0.5)); |
91 } | 79 } |
92 | 80 |
93 // Max number of stacked tabs. | 81 // Max number of stacked tabs. |
94 static const int kMaxStackedCount = 4; | 82 static const int kMaxStackedCount = 4; |
95 | 83 |
96 // Padding between stacked tabs. | 84 // Padding between stacked tabs. |
97 static const int kStackedPadding = 6; | 85 static const int kStackedPadding = 6; |
98 | 86 |
99 namespace { | 87 // Horizontal offset for the new tab button to bring it closer to the |
| 88 // rightmost tab. |
| 89 const int GetNewTabButtonHOffset() { |
| 90 static int value = -1; |
| 91 if (value == -1) { |
| 92 switch (ui::GetDisplayLayout()) { |
| 93 case ui::LAYOUT_ASH: |
| 94 value = -11; |
| 95 break; |
| 96 case ui::LAYOUT_TOUCH: |
| 97 value = -6; |
| 98 break; |
| 99 default: |
| 100 value = -5; |
| 101 } |
| 102 } |
| 103 return value; |
| 104 } |
| 105 |
| 106 // Vertical offset for the new tab button to bring it closer to the |
| 107 // rightmost tab. |
| 108 const int GetNewTabButtonVOffset() { |
| 109 static int value = -1; |
| 110 if (value == -1) { |
| 111 switch (ui::GetDisplayLayout()) { |
| 112 case ui::LAYOUT_ASH: |
| 113 value = 7; |
| 114 break; |
| 115 case ui::LAYOUT_TOUCH: |
| 116 value = 10; |
| 117 break; |
| 118 default: |
| 119 value = 5; |
| 120 } |
| 121 } |
| 122 return value; |
| 123 } |
| 124 |
| 125 // Amount the left edge of a tab is offset from the rectangle of the tab's |
| 126 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. |
| 127 const int GetTabHOffset() { |
| 128 static int value = -1; |
| 129 if (value == -1) { |
| 130 switch (ui::GetDisplayLayout()) { |
| 131 case ui::LAYOUT_ASH: |
| 132 value = -27; |
| 133 break; |
| 134 case ui::LAYOUT_TOUCH: |
| 135 value = -16; |
| 136 break; |
| 137 default: |
| 138 value = -16; |
| 139 } |
| 140 } |
| 141 return value; |
| 142 } |
100 | 143 |
101 // Animation delegate used when a dragged tab is released. When done sets the | 144 // Animation delegate used when a dragged tab is released. When done sets the |
102 // dragging state to false. | 145 // dragging state to false. |
103 class ResetDraggingStateDelegate | 146 class ResetDraggingStateDelegate |
104 : public views::BoundsAnimator::OwnedAnimationDelegate { | 147 : public views::BoundsAnimator::OwnedAnimationDelegate { |
105 public: | 148 public: |
106 explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { | 149 explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { |
107 } | 150 } |
108 | 151 |
109 virtual void AnimationEnded(const ui::Animation* animation) { | 152 virtual void AnimationEnded(const ui::Animation* animation) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 int height = mask->height(); | 292 int height = mask->height(); |
250 int width = mask->width(); | 293 int width = mask->width(); |
251 gfx::Canvas canvas(gfx::Size(width, height), false); | 294 gfx::Canvas canvas(gfx::Size(width, height), false); |
252 | 295 |
253 // For custom images the background starts at the top of the tab strip. | 296 // For custom images the background starts at the top of the tab strip. |
254 // Otherwise the background starts at the top of the frame. | 297 // Otherwise the background starts at the top of the frame. |
255 SkBitmap* background = GetThemeProvider()->GetBitmapNamed(background_id); | 298 SkBitmap* background = GetThemeProvider()->GetBitmapNamed(background_id); |
256 int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? | 299 int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? |
257 0 : background_offset_.y(); | 300 0 : background_offset_.y(); |
258 canvas.TileImageInt(*background, GetMirroredX() + background_offset_.x(), | 301 canvas.TileImageInt(*background, GetMirroredX() + background_offset_.x(), |
259 kNewTabButtonVOffset + offset_y, 0, 0, width, height); | 302 GetNewTabButtonVOffset() + offset_y, 0, 0, width, height); |
260 | 303 |
261 if (alpha != 255) { | 304 if (alpha != 255) { |
262 SkPaint paint; | 305 SkPaint paint; |
263 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); | 306 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); |
264 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); | 307 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); |
265 paint.setStyle(SkPaint::kFill_Style); | 308 paint.setStyle(SkPaint::kFill_Style); |
266 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); | 309 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); |
267 } | 310 } |
268 | 311 |
269 // White highlight on hover. | 312 // White highlight on hover. |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 | 568 |
526 int model_count = GetModelCount(); | 569 int model_count = GetModelCount(); |
527 if (model_index + 1 != model_count && model_count > 1) { | 570 if (model_index + 1 != model_count && model_count > 1) { |
528 // The user is about to close a tab other than the last tab. Set | 571 // The user is about to close a tab other than the last tab. Set |
529 // available_width_for_tabs_ so that if we do a layout we don't position a | 572 // available_width_for_tabs_ so that if we do a layout we don't position a |
530 // tab past the end of the second to last tab. We do this so that as the | 573 // tab past the end of the second to last tab. We do this so that as the |
531 // user closes tabs with the mouse a tab continues to fall under the mouse. | 574 // user closes tabs with the mouse a tab continues to fall under the mouse. |
532 Tab* last_tab = tab_at(model_count - 1); | 575 Tab* last_tab = tab_at(model_count - 1); |
533 Tab* tab_being_removed = tab_at(model_index); | 576 Tab* tab_being_removed = tab_at(model_index); |
534 available_width_for_tabs_ = last_tab->x() + last_tab->width() - | 577 available_width_for_tabs_ = last_tab->x() + last_tab->width() - |
535 tab_being_removed->width() - kTabHOffset; | 578 tab_being_removed->width() - GetTabHOffset(); |
536 if (model_index == 0 && tab_being_removed->data().mini && | 579 if (model_index == 0 && tab_being_removed->data().mini && |
537 !tab_at(1)->data().mini) { | 580 !tab_at(1)->data().mini) { |
538 available_width_for_tabs_ -= kMiniToNonMiniGap; | 581 available_width_for_tabs_ -= kMiniToNonMiniGap; |
539 } | 582 } |
540 } | 583 } |
541 | 584 |
542 in_tab_close_ = true; | 585 in_tab_close_ = true; |
543 AddMessageLoopObserver(); | 586 AddMessageLoopObserver(); |
544 } | 587 } |
545 | 588 |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 | 997 |
955 std::string TabStrip::GetClassName() const { | 998 std::string TabStrip::GetClassName() const { |
956 return kViewClassName; | 999 return kViewClassName; |
957 } | 1000 } |
958 | 1001 |
959 gfx::Size TabStrip::GetPreferredSize() { | 1002 gfx::Size TabStrip::GetPreferredSize() { |
960 // Report the minimum width as the size required for a single selected tab | 1003 // Report the minimum width as the size required for a single selected tab |
961 // plus the new tab button. Don't base it on the actual number of tabs because | 1004 // plus the new tab button. Don't base it on the actual number of tabs because |
962 // it's undesirable to have the minimum window size change when a new tab is | 1005 // it's undesirable to have the minimum window size change when a new tab is |
963 // opened. | 1006 // opened. |
964 int needed_width = Tab::GetMinimumSelectedSize().width() - kTabHOffset + | 1007 int needed_width = Tab::GetMinimumSelectedSize().width() - |
965 new_tab_button_width(); | 1008 GetTabHOffset() + new_tab_button_width(); |
966 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); | 1009 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); |
967 } | 1010 } |
968 | 1011 |
969 void TabStrip::OnDragEntered(const DropTargetEvent& event) { | 1012 void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
970 // Force animations to stop, otherwise it makes the index calculation tricky. | 1013 // Force animations to stop, otherwise it makes the index calculation tricky. |
971 StopAnimating(true); | 1014 StopAnimating(true); |
972 | 1015 |
973 UpdateDropIndex(event); | 1016 UpdateDropIndex(event); |
974 } | 1017 } |
975 | 1018 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 AddChildView(newtab_button_); | 1154 AddChildView(newtab_button_); |
1112 if (drop_indicator_width == 0) { | 1155 if (drop_indicator_width == 0) { |
1113 // Direction doesn't matter, both images are the same size. | 1156 // Direction doesn't matter, both images are the same size. |
1114 SkBitmap* drop_image = GetDropArrowImage(true); | 1157 SkBitmap* drop_image = GetDropArrowImage(true); |
1115 drop_indicator_width = drop_image->width(); | 1158 drop_indicator_width = drop_image->width(); |
1116 drop_indicator_height = drop_image->height(); | 1159 drop_indicator_height = drop_image->height(); |
1117 } | 1160 } |
1118 if (TouchModeSupport::IsTouchOptimized()) { | 1161 if (TouchModeSupport::IsTouchOptimized()) { |
1119 touch_layout_.reset(new TouchTabStripLayout( | 1162 touch_layout_.reset(new TouchTabStripLayout( |
1120 Tab::GetStandardSize(), | 1163 Tab::GetStandardSize(), |
1121 kTabHOffset, | 1164 GetTabHOffset(), |
1122 kStackedPadding, | 1165 kStackedPadding, |
1123 kMaxStackedCount, | 1166 kMaxStackedCount, |
1124 &tabs_)); | 1167 &tabs_)); |
1125 } | 1168 } |
1126 } | 1169 } |
1127 | 1170 |
1128 BaseTab* TabStrip::CreateTab() { | 1171 BaseTab* TabStrip::CreateTab() { |
1129 Tab* tab = new Tab(this); | 1172 Tab* tab = new Tab(this); |
1130 tab->set_animation_container(animation_container_.get()); | 1173 tab->set_animation_container(animation_container_.get()); |
1131 return tab; | 1174 return tab; |
1132 } | 1175 } |
1133 | 1176 |
1134 void TabStrip::StartInsertTabAnimation(int model_index) { | 1177 void TabStrip::StartInsertTabAnimation(int model_index) { |
1135 PrepareForAnimation(); | 1178 PrepareForAnimation(); |
1136 | 1179 |
1137 // The TabStrip can now use its entire width to lay out Tabs. | 1180 // The TabStrip can now use its entire width to lay out Tabs. |
1138 in_tab_close_ = false; | 1181 in_tab_close_ = false; |
1139 available_width_for_tabs_ = -1; | 1182 available_width_for_tabs_ = -1; |
1140 | 1183 |
1141 GenerateIdealBounds(); | 1184 GenerateIdealBounds(); |
1142 | 1185 |
1143 BaseTab* tab = tab_at(model_index); | 1186 BaseTab* tab = tab_at(model_index); |
1144 if (model_index == 0) { | 1187 if (model_index == 0) { |
1145 tab->SetBounds(0, ideal_bounds(model_index).y(), 0, | 1188 tab->SetBounds(0, ideal_bounds(model_index).y(), 0, |
1146 ideal_bounds(model_index).height()); | 1189 ideal_bounds(model_index).height()); |
1147 } else { | 1190 } else { |
1148 BaseTab* last_tab = tab_at(model_index - 1); | 1191 BaseTab* last_tab = tab_at(model_index - 1); |
1149 tab->SetBounds(last_tab->bounds().right() + kTabHOffset, | 1192 tab->SetBounds(last_tab->bounds().right() + GetTabHOffset(), |
1150 ideal_bounds(model_index).y(), 0, | 1193 ideal_bounds(model_index).y(), 0, |
1151 ideal_bounds(model_index).height()); | 1194 ideal_bounds(model_index).height()); |
1152 } | 1195 } |
1153 | 1196 |
1154 AnimateToIdealBounds(); | 1197 AnimateToIdealBounds(); |
1155 } | 1198 } |
1156 | 1199 |
1157 void TabStrip::StartMoveTabAnimation() { | 1200 void TabStrip::StartMoveTabAnimation() { |
1158 PrepareForAnimation(); | 1201 PrepareForAnimation(); |
1159 GenerateIdealBounds(); | 1202 GenerateIdealBounds(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 touch_layout_->SetWidth(size().width() - new_tab_button_width()); | 1272 touch_layout_->SetWidth(size().width() - new_tab_button_width()); |
1230 | 1273 |
1231 GenerateIdealBounds(); | 1274 GenerateIdealBounds(); |
1232 | 1275 |
1233 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); | 1276 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); |
1234 | 1277 |
1235 SchedulePaint(); | 1278 SchedulePaint(); |
1236 | 1279 |
1237 if (SizeTabButtonToTopOfTabStrip()) { | 1280 if (SizeTabButtonToTopOfTabStrip()) { |
1238 newtab_button_bounds_.set_height( | 1281 newtab_button_bounds_.set_height( |
1239 kNewTabButtonHeight + kNewTabButtonVOffset); | 1282 kNewTabButtonHeight + GetNewTabButtonVOffset()); |
1240 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1283 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
1241 views::ImageButton::ALIGN_BOTTOM); | 1284 views::ImageButton::ALIGN_BOTTOM); |
1242 } else { | 1285 } else { |
1243 newtab_button_bounds_.set_height(kNewTabButtonHeight); | 1286 newtab_button_bounds_.set_height(kNewTabButtonHeight); |
1244 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1287 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
1245 views::ImageButton::ALIGN_TOP); | 1288 views::ImageButton::ALIGN_TOP); |
1246 } | 1289 } |
1247 newtab_button_->SetBoundsRect(newtab_button_bounds_); | 1290 newtab_button_->SetBoundsRect(newtab_button_bounds_); |
1248 } | 1291 } |
1249 | 1292 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1287 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<BaseTab*>& tabs, | 1330 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<BaseTab*>& tabs, |
1288 std::vector<gfx::Rect>* bounds) { | 1331 std::vector<gfx::Rect>* bounds) { |
1289 int x = 0; | 1332 int x = 0; |
1290 for (size_t i = 0; i < tabs.size(); ++i) { | 1333 for (size_t i = 0; i < tabs.size(); ++i) { |
1291 BaseTab* tab = tabs[i]; | 1334 BaseTab* tab = tabs[i]; |
1292 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) | 1335 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) |
1293 x += kMiniToNonMiniGap; | 1336 x += kMiniToNonMiniGap; |
1294 gfx::Rect new_bounds = tab->bounds(); | 1337 gfx::Rect new_bounds = tab->bounds(); |
1295 new_bounds.set_origin(gfx::Point(x, 0)); | 1338 new_bounds.set_origin(gfx::Point(x, 0)); |
1296 bounds->push_back(new_bounds); | 1339 bounds->push_back(new_bounds); |
1297 x += tab->width() + kTabHOffset; | 1340 x += tab->width() + GetTabHOffset(); |
1298 } | 1341 } |
1299 } | 1342 } |
1300 | 1343 |
1301 int TabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { | 1344 int TabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { |
1302 int width = 0; | 1345 int width = 0; |
1303 for (size_t i = 0; i < tabs.size(); ++i) { | 1346 for (size_t i = 0; i < tabs.size(); ++i) { |
1304 BaseTab* tab = tabs[i]; | 1347 BaseTab* tab = tabs[i]; |
1305 width += tab->width(); | 1348 width += tab->width(); |
1306 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) | 1349 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) |
1307 width += kMiniToNonMiniGap; | 1350 width += kMiniToNonMiniGap; |
1308 } | 1351 } |
1309 if (tabs.size() > 0) | 1352 if (tabs.size() > 0) |
1310 width += kTabHOffset * static_cast<int>(tabs.size() - 1); | 1353 width += GetTabHOffset() * static_cast<int>(tabs.size() - 1); |
1311 return width; | 1354 return width; |
1312 } | 1355 } |
1313 | 1356 |
1314 void TabStrip::RemoveTabFromViewModel(int index) { | 1357 void TabStrip::RemoveTabFromViewModel(int index) { |
1315 // We still need to paint the tab until we actually remove it. Put it | 1358 // We still need to paint the tab until we actually remove it. Put it |
1316 // in tabs_closing_map_ so we can find it. | 1359 // in tabs_closing_map_ so we can find it. |
1317 tabs_closing_map_[index].push_back(tab_at(index)); | 1360 tabs_closing_map_[index].push_back(tab_at(index)); |
1318 UpdateTabsClosingMap(index + 1, -1); | 1361 UpdateTabsClosingMap(index + 1, -1); |
1319 tabs_.Remove(index); | 1362 tabs_.Remove(index); |
1320 } | 1363 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1460 // width here; the first preserves the consistent "leave the last tab under | 1503 // width here; the first preserves the consistent "leave the last tab under |
1461 // the user's mouse so they can close many tabs" behavior at the cost of | 1504 // the user's mouse so they can close many tabs" behavior at the cost of |
1462 // prolonging the glitchy appearance of the overflow state, while the second | 1505 // prolonging the glitchy appearance of the overflow state, while the second |
1463 // gets us out of overflow as soon as possible but forces the user to move | 1506 // gets us out of overflow as soon as possible but forces the user to move |
1464 // their mouse for a few tabs' worth of closing. We choose visual | 1507 // their mouse for a few tabs' worth of closing. We choose visual |
1465 // imperfection over behavioral imperfection and select the first option. | 1508 // imperfection over behavioral imperfection and select the first option. |
1466 available_width = available_width_for_tabs_; | 1509 available_width = available_width_for_tabs_; |
1467 } | 1510 } |
1468 | 1511 |
1469 if (mini_tab_count > 0) { | 1512 if (mini_tab_count > 0) { |
1470 available_width -= mini_tab_count * (Tab::GetMiniWidth() + kTabHOffset); | 1513 available_width -= mini_tab_count * (Tab::GetMiniWidth() + GetTabHOffset()); |
1471 tab_count -= mini_tab_count; | 1514 tab_count -= mini_tab_count; |
1472 if (tab_count == 0) { | 1515 if (tab_count == 0) { |
1473 *selected_width = *unselected_width = Tab::GetStandardSize().width(); | 1516 *selected_width = *unselected_width = Tab::GetStandardSize().width(); |
1474 return; | 1517 return; |
1475 } | 1518 } |
1476 // Account for gap between the last mini-tab and first non-mini-tab. | 1519 // Account for gap between the last mini-tab and first non-mini-tab. |
1477 available_width -= kMiniToNonMiniGap; | 1520 available_width -= kMiniToNonMiniGap; |
1478 } | 1521 } |
1479 | 1522 |
1480 // Calculate the desired tab widths by dividing the available space into equal | 1523 // Calculate the desired tab widths by dividing the available space into equal |
1481 // portions. Don't let tabs get larger than the "standard width" or smaller | 1524 // portions. Don't let tabs get larger than the "standard width" or smaller |
1482 // than the minimum width for each type, respectively. | 1525 // than the minimum width for each type, respectively. |
1483 const int total_offset = kTabHOffset * (tab_count - 1); | 1526 const int total_offset = GetTabHOffset() * (tab_count - 1); |
1484 const double desired_tab_width = std::min((static_cast<double>( | 1527 const double desired_tab_width = std::min((static_cast<double>( |
1485 available_width - total_offset) / static_cast<double>(tab_count)), | 1528 available_width - total_offset) / static_cast<double>(tab_count)), |
1486 static_cast<double>(Tab::GetStandardSize().width())); | 1529 static_cast<double>(Tab::GetStandardSize().width())); |
1487 *unselected_width = std::max(desired_tab_width, min_unselected_width); | 1530 *unselected_width = std::max(desired_tab_width, min_unselected_width); |
1488 *selected_width = std::max(desired_tab_width, min_selected_width); | 1531 *selected_width = std::max(desired_tab_width, min_selected_width); |
1489 | 1532 |
1490 // When there are multiple tabs, we'll have one selected and some unselected | 1533 // When there are multiple tabs, we'll have one selected and some unselected |
1491 // tabs. If the desired width was between the minimum sizes of these types, | 1534 // tabs. If the desired width was between the minimum sizes of these types, |
1492 // try to shrink the tabs with the smaller minimum. For example, if we have | 1535 // try to shrink the tabs with the smaller minimum. For example, if we have |
1493 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If | 1536 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1566 } | 1609 } |
1567 | 1610 |
1568 gfx::Rect TabStrip::GetDropBounds(int drop_index, | 1611 gfx::Rect TabStrip::GetDropBounds(int drop_index, |
1569 bool drop_before, | 1612 bool drop_before, |
1570 bool* is_beneath) { | 1613 bool* is_beneath) { |
1571 DCHECK_NE(drop_index, -1); | 1614 DCHECK_NE(drop_index, -1); |
1572 int center_x; | 1615 int center_x; |
1573 if (drop_index < tab_count()) { | 1616 if (drop_index < tab_count()) { |
1574 Tab* tab = tab_at(drop_index); | 1617 Tab* tab = tab_at(drop_index); |
1575 if (drop_before) | 1618 if (drop_before) |
1576 center_x = tab->x() - (kTabHOffset / 2); | 1619 center_x = tab->x() - (GetTabHOffset() / 2); |
1577 else | 1620 else |
1578 center_x = tab->x() + (tab->width() / 2); | 1621 center_x = tab->x() + (tab->width() / 2); |
1579 } else { | 1622 } else { |
1580 Tab* last_tab = tab_at(drop_index - 1); | 1623 Tab* last_tab = tab_at(drop_index - 1); |
1581 center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2); | 1624 center_x = last_tab->x() + last_tab->width() + (GetTabHOffset() / 2); |
1582 } | 1625 } |
1583 | 1626 |
1584 // Mirror the center point if necessary. | 1627 // Mirror the center point if necessary. |
1585 center_x = GetMirroredXInView(center_x); | 1628 center_x = GetMirroredXInView(center_x); |
1586 | 1629 |
1587 // Determine the screen bounds. | 1630 // Determine the screen bounds. |
1588 gfx::Point drop_loc(center_x - drop_indicator_width / 2, | 1631 gfx::Point drop_loc(center_x - drop_indicator_width / 2, |
1589 -drop_indicator_height); | 1632 -drop_indicator_height); |
1590 ConvertPointToScreen(this, &drop_loc); | 1633 ConvertPointToScreen(this, &drop_loc); |
1591 gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, | 1634 gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1715 } | 1758 } |
1716 | 1759 |
1717 void TabStrip::PrepareForAnimation() { | 1760 void TabStrip::PrepareForAnimation() { |
1718 if (!IsDragSessionActive() && !TabDragController::IsAttachedTo(this)) { | 1761 if (!IsDragSessionActive() && !TabDragController::IsAttachedTo(this)) { |
1719 for (int i = 0; i < tab_count(); ++i) | 1762 for (int i = 0; i < tab_count(); ++i) |
1720 tab_at(i)->set_dragging(false); | 1763 tab_at(i)->set_dragging(false); |
1721 } | 1764 } |
1722 } | 1765 } |
1723 | 1766 |
1724 void TabStrip::GenerateIdealBounds() { | 1767 void TabStrip::GenerateIdealBounds() { |
1725 int new_tab_y = SizeTabButtonToTopOfTabStrip() ? 0 : kNewTabButtonVOffset; | 1768 int new_tab_y = |
| 1769 SizeTabButtonToTopOfTabStrip() ? 0 : GetNewTabButtonVOffset(); |
1726 | 1770 |
1727 if (touch_layout_.get()) { | 1771 if (touch_layout_.get()) { |
1728 if (tabs_.view_size() == 0) | 1772 if (tabs_.view_size() == 0) |
1729 return; | 1773 return; |
1730 | 1774 |
1731 int new_tab_x = tabs_.ideal_bounds(tabs_.view_size() - 1).right() + | 1775 int new_tab_x = tabs_.ideal_bounds(tabs_.view_size() - 1).right() + |
1732 kNewTabButtonHOffset; | 1776 GetNewTabButtonHOffset(); |
1733 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); | 1777 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); |
1734 return; | 1778 return; |
1735 } | 1779 } |
1736 | 1780 |
1737 double unselected, selected; | 1781 double unselected, selected; |
1738 GetDesiredTabWidths(tab_count(), GetMiniTabCount(), &unselected, &selected); | 1782 GetDesiredTabWidths(tab_count(), GetMiniTabCount(), &unselected, &selected); |
1739 current_unselected_width_ = unselected; | 1783 current_unselected_width_ = unselected; |
1740 current_selected_width_ = selected; | 1784 current_selected_width_ = selected; |
1741 | 1785 |
1742 // NOTE: This currently assumes a tab's height doesn't differ based on | 1786 // NOTE: This currently assumes a tab's height doesn't differ based on |
1743 // selected state or the number of tabs in the strip! | 1787 // selected state or the number of tabs in the strip! |
1744 int tab_height = Tab::GetStandardSize().height(); | 1788 int tab_height = Tab::GetStandardSize().height(); |
1745 int first_non_mini_index = 0; | 1789 int first_non_mini_index = 0; |
1746 double tab_x = GenerateIdealBoundsForMiniTabs(&first_non_mini_index); | 1790 double tab_x = GenerateIdealBoundsForMiniTabs(&first_non_mini_index); |
1747 for (int i = first_non_mini_index; i < tab_count(); ++i) { | 1791 for (int i = first_non_mini_index; i < tab_count(); ++i) { |
1748 Tab* tab = tab_at(i); | 1792 Tab* tab = tab_at(i); |
1749 DCHECK(!tab->data().mini); | 1793 DCHECK(!tab->data().mini); |
1750 double tab_width = tab->IsActive() ? selected : unselected; | 1794 double tab_width = tab->IsActive() ? selected : unselected; |
1751 double end_of_tab = tab_x + tab_width; | 1795 double end_of_tab = tab_x + tab_width; |
1752 int rounded_tab_x = Round(tab_x); | 1796 int rounded_tab_x = Round(tab_x); |
1753 set_ideal_bounds( | 1797 set_ideal_bounds( |
1754 i, | 1798 i, |
1755 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, | 1799 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, |
1756 tab_height)); | 1800 tab_height)); |
1757 tab_x = end_of_tab + kTabHOffset; | 1801 tab_x = end_of_tab + GetTabHOffset(); |
1758 } | 1802 } |
1759 | 1803 |
1760 // Update bounds of new tab button. | 1804 // Update bounds of new tab button. |
1761 int new_tab_x; | 1805 int new_tab_x; |
1762 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && | 1806 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && |
1763 !in_tab_close_) { | 1807 !in_tab_close_) { |
1764 // We're shrinking tabs, so we need to anchor the New Tab button to the | 1808 // We're shrinking tabs, so we need to anchor the New Tab button to the |
1765 // right edge of the TabStrip's bounds, rather than the right edge of the | 1809 // right edge of the TabStrip's bounds, rather than the right edge of the |
1766 // right-most Tab, otherwise it'll bounce when animating. | 1810 // right-most Tab, otherwise it'll bounce when animating. |
1767 new_tab_x = width() - newtab_button_bounds_.width(); | 1811 new_tab_x = width() - newtab_button_bounds_.width(); |
1768 } else { | 1812 } else { |
1769 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; | 1813 new_tab_x = Round(tab_x - GetTabHOffset()) + GetNewTabButtonHOffset(); |
1770 } | 1814 } |
1771 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); | 1815 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); |
1772 } | 1816 } |
1773 | 1817 |
1774 int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) { | 1818 int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) { |
1775 int next_x = 0; | 1819 int next_x = 0; |
1776 int mini_width = Tab::GetMiniWidth(); | 1820 int mini_width = Tab::GetMiniWidth(); |
1777 int tab_height = Tab::GetStandardSize().height(); | 1821 int tab_height = Tab::GetStandardSize().height(); |
1778 int index = 0; | 1822 int index = 0; |
1779 for (; index < tab_count() && tab_at(index)->data().mini; ++index) { | 1823 for (; index < tab_count() && tab_at(index)->data().mini; ++index) { |
1780 set_ideal_bounds(index, | 1824 set_ideal_bounds(index, |
1781 gfx::Rect(next_x, 0, mini_width, tab_height)); | 1825 gfx::Rect(next_x, 0, mini_width, tab_height)); |
1782 next_x += mini_width + kTabHOffset; | 1826 next_x += mini_width + GetTabHOffset(); |
1783 } | 1827 } |
1784 if (index > 0 && index < tab_count()) | 1828 if (index > 0 && index < tab_count()) |
1785 next_x += kMiniToNonMiniGap; | 1829 next_x += kMiniToNonMiniGap; |
1786 if (first_non_mini_index) | 1830 if (first_non_mini_index) |
1787 *first_non_mini_index = index; | 1831 *first_non_mini_index = index; |
1788 return next_x; | 1832 return next_x; |
1789 } | 1833 } |
1790 | 1834 |
1791 int TabStrip::new_tab_button_width() const { | 1835 int TabStrip::new_tab_button_width() const { |
1792 return kNewTabButtonWidth + kNewTabButtonHOffset; | 1836 return kNewTabButtonWidth + GetNewTabButtonHOffset(); |
1793 } | 1837 } |
1794 | 1838 |
1795 void TabStrip::StartResizeLayoutAnimation() { | 1839 void TabStrip::StartResizeLayoutAnimation() { |
1796 PrepareForAnimation(); | 1840 PrepareForAnimation(); |
1797 GenerateIdealBounds(); | 1841 GenerateIdealBounds(); |
1798 AnimateToIdealBounds(); | 1842 AnimateToIdealBounds(); |
1799 } | 1843 } |
1800 | 1844 |
1801 void TabStrip::StartMiniTabAnimation() { | 1845 void TabStrip::StartMiniTabAnimation() { |
1802 in_tab_close_ = false; | 1846 in_tab_close_ = false; |
1803 available_width_for_tabs_ = -1; | 1847 available_width_for_tabs_ = -1; |
1804 | 1848 |
1805 PrepareForAnimation(); | 1849 PrepareForAnimation(); |
1806 | 1850 |
1807 GenerateIdealBounds(); | 1851 GenerateIdealBounds(); |
1808 AnimateToIdealBounds(); | 1852 AnimateToIdealBounds(); |
1809 } | 1853 } |
1810 | 1854 |
1811 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { | 1855 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { |
1812 // The user initiated the close. We want to persist the bounds of all the | 1856 // The user initiated the close. We want to persist the bounds of all the |
1813 // existing tabs, so we manually shift ideal_bounds then animate. | 1857 // existing tabs, so we manually shift ideal_bounds then animate. |
1814 BaseTab* tab_closing = tab_at(model_index); | 1858 BaseTab* tab_closing = tab_at(model_index); |
1815 int delta = tab_closing->width() + kTabHOffset; | 1859 int delta = tab_closing->width() + GetTabHOffset(); |
1816 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to | 1860 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to |
1817 // add the extra padding. | 1861 // add the extra padding. |
1818 DCHECK_NE(model_index + 1, tab_count()); | 1862 DCHECK_NE(model_index + 1, tab_count()); |
1819 if (tab_closing->data().mini && model_index + 1 < tab_count() && | 1863 if (tab_closing->data().mini && model_index + 1 < tab_count() && |
1820 !tab_at(model_index + 1)->data().mini) { | 1864 !tab_at(model_index + 1)->data().mini) { |
1821 delta += kMiniToNonMiniGap; | 1865 delta += kMiniToNonMiniGap; |
1822 } | 1866 } |
1823 | 1867 |
1824 for (int i = model_index + 1; i < tab_count(); ++i) { | 1868 for (int i = model_index + 1; i < tab_count(); ++i) { |
1825 gfx::Rect bounds = ideal_bounds(i); | 1869 gfx::Rect bounds = ideal_bounds(i); |
(...skipping 29 matching lines...) Expand all Loading... |
1855 const gfx::Point& point_in_tabstrip_coords) { | 1899 const gfx::Point& point_in_tabstrip_coords) { |
1856 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); | 1900 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); |
1857 View::ConvertPointToView(this, tab, &point_in_tab_coords); | 1901 View::ConvertPointToView(this, tab, &point_in_tab_coords); |
1858 return tab->HitTest(point_in_tab_coords); | 1902 return tab->HitTest(point_in_tab_coords); |
1859 } | 1903 } |
1860 | 1904 |
1861 int TabStrip::GetStartXForNormalTabs() const { | 1905 int TabStrip::GetStartXForNormalTabs() const { |
1862 int mini_tab_count = GetMiniTabCount(); | 1906 int mini_tab_count = GetMiniTabCount(); |
1863 if (mini_tab_count == 0) | 1907 if (mini_tab_count == 0) |
1864 return 0; | 1908 return 0; |
1865 return mini_tab_count * (Tab::GetMiniWidth() + kTabHOffset) + | 1909 return mini_tab_count * (Tab::GetMiniWidth() + GetTabHOffset()) + |
1866 kMiniToNonMiniGap; | 1910 kMiniToNonMiniGap; |
1867 } | 1911 } |
1868 | 1912 |
1869 Tab* TabStrip::FindTabForEvent(const gfx::Point& point, int start, int delta) { | 1913 Tab* TabStrip::FindTabForEvent(const gfx::Point& point, int start, int delta) { |
1870 for (int i = start; i >= 0 && i < tab_count(); i += delta) { | 1914 for (int i = start; i >= 0 && i < tab_count(); i += delta) { |
1871 if (IsPointInTab(tab_at(i), point)) | 1915 if (IsPointInTab(tab_at(i), point)) |
1872 return tab_at(i); | 1916 return tab_at(i); |
1873 } | 1917 } |
1874 return NULL; | 1918 return NULL; |
1875 } | 1919 } |
OLD | NEW |