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 13 matching lines...) Expand all Loading... |
24 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h" | 24 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h" |
25 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" | 25 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" |
26 #include "grit/generated_resources.h" | 26 #include "grit/generated_resources.h" |
27 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
28 #include "grit/theme_resources_standard.h" | 28 #include "grit/theme_resources_standard.h" |
29 #include "ui/base/accessibility/accessible_view_state.h" | 29 #include "ui/base/accessibility/accessible_view_state.h" |
30 #include "ui/base/animation/animation_container.h" | 30 #include "ui/base/animation/animation_container.h" |
31 #include "ui/base/animation/throb_animation.h" | 31 #include "ui/base/animation/throb_animation.h" |
32 #include "ui/base/dragdrop/drag_drop_types.h" | 32 #include "ui/base/dragdrop/drag_drop_types.h" |
33 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
| 34 #include "ui/base/layout.h" |
34 #include "ui/base/resource/resource_bundle.h" | 35 #include "ui/base/resource/resource_bundle.h" |
35 #include "ui/base/touch/touch_mode_support.h" | 36 #include "ui/base/touch/touch_mode_support.h" |
36 #include "ui/gfx/canvas.h" | 37 #include "ui/gfx/canvas.h" |
37 #include "ui/gfx/path.h" | 38 #include "ui/gfx/path.h" |
38 #include "ui/gfx/screen.h" | 39 #include "ui/gfx/screen.h" |
39 #include "ui/gfx/size.h" | 40 #include "ui/gfx/size.h" |
40 #include "ui/gfx/skbitmap_operations.h" | 41 #include "ui/gfx/skbitmap_operations.h" |
41 #include "ui/views/controls/image_view.h" | 42 #include "ui/views/controls/image_view.h" |
42 #include "ui/views/mouse_watcher_view_host.h" | 43 #include "ui/views/mouse_watcher_view_host.h" |
43 #include "ui/views/view_model_utils.h" | 44 #include "ui/views/view_model_utils.h" |
44 #include "ui/views/widget/default_theme_provider.h" | 45 #include "ui/views/widget/default_theme_provider.h" |
45 #include "ui/views/widget/root_view.h" | 46 #include "ui/views/widget/root_view.h" |
46 #include "ui/views/widget/widget.h" | 47 #include "ui/views/widget/widget.h" |
47 #include "ui/views/window/non_client_view.h" | 48 #include "ui/views/window/non_client_view.h" |
48 | 49 |
49 #if defined(OS_WIN) | 50 #if defined(OS_WIN) |
50 #include "ui/base/win/hwnd_util.h" | 51 #include "ui/base/win/hwnd_util.h" |
51 #include "ui/views/widget/monitor_win.h" | 52 #include "ui/views/widget/monitor_win.h" |
52 #endif | 53 #endif |
53 | 54 |
54 using views::DropTargetEvent; | 55 using views::DropTargetEvent; |
55 | 56 |
56 // Offset for the new tab button to bring it closer to the rightmost tab. | 57 namespace { |
57 #if defined(USE_ASH) | 58 |
58 static const int kNewTabButtonHOffset = -11; | |
59 static const int kNewTabButtonVOffset = 7; | |
60 #else | |
61 static const int kNewTabButtonHOffset = -5; | |
62 static const int kNewTabButtonVOffset = 5; | |
63 #endif | |
64 // Amount the left edge of a tab is offset from the rectangle of the tab's | |
65 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. | |
66 #if defined(USE_ASH) | |
67 static const int kTabHOffset = -27; | |
68 #else | |
69 static const int kTabHOffset = -16; | |
70 #endif | |
71 static const int kTabStripAnimationVSlop = 40; | 59 static const int kTabStripAnimationVSlop = 40; |
72 // Inactive tabs in a native frame are slightly transparent. | 60 // Inactive tabs in a native frame are slightly transparent. |
73 static const int kNativeFrameInactiveTabAlpha = 200; | 61 static const int kNativeFrameInactiveTabAlpha = 200; |
74 // If there are multiple tabs selected then make non-selected inactive tabs | 62 // If there are multiple tabs selected then make non-selected inactive tabs |
75 // even more transparent. | 63 // even more transparent. |
76 static const int kNativeFrameInactiveTabAlphaMultiSelection = 150; | 64 static const int kNativeFrameInactiveTabAlphaMultiSelection = 150; |
77 | 65 |
78 // Inverse ratio of the width of a tab edge to the width of the tab. When | 66 // Inverse ratio of the width of a tab edge to the width of the tab. When |
79 // hovering over the left or right edge of a tab, the drop indicator will | 67 // hovering over the left or right edge of a tab, the drop indicator will |
80 // point between tabs. | 68 // point between tabs. |
81 static const int kTabEdgeRatioInverse = 4; | 69 static const int kTabEdgeRatioInverse = 4; |
82 | 70 |
83 // Size of the drop indicator. | 71 // Size of the drop indicator. |
84 static int drop_indicator_width; | 72 static int drop_indicator_width; |
85 static int drop_indicator_height; | 73 static int drop_indicator_height; |
86 | 74 |
87 static inline int Round(double x) { | 75 static inline int Round(double x) { |
88 // Why oh why is this not in a standard header? | 76 // Why oh why is this not in a standard header? |
89 return static_cast<int>(floor(x + 0.5)); | 77 return static_cast<int>(floor(x + 0.5)); |
90 } | 78 } |
91 | 79 |
92 // Max width reserved for stacked tabs along a particular edge. | 80 // Max width reserved for stacked tabs along a particular edge. |
93 static const double kMaxEdgeStackWidth = 24; | 81 static const double kMaxEdgeStackWidth = 24; |
94 | 82 |
95 namespace { | 83 // Horizontal offset for the new tab button to bring it closer to the |
| 84 // rightmost tab. |
| 85 const int GetNewTabButtonHOffset() { |
| 86 static int value = -1; |
| 87 if (value == -1) { |
| 88 switch (ui::GetDisplayLayout()) { |
| 89 case ui::LAYOUT_ASH: |
| 90 value = -11; |
| 91 break; |
| 92 case ui::LAYOUT_METRO: |
| 93 value = -6; |
| 94 break; |
| 95 default: |
| 96 value = -5; |
| 97 } |
| 98 } |
| 99 return value; |
| 100 } |
| 101 |
| 102 // Vertical offset for the new tab button to bring it closer to the |
| 103 // rightmost tab. |
| 104 const int GetNewTabButtonVOffset() { |
| 105 static int value = -1; |
| 106 if (value == -1) { |
| 107 switch (ui::GetDisplayLayout()) { |
| 108 case ui::LAYOUT_ASH: |
| 109 value = 7; |
| 110 break; |
| 111 case ui::LAYOUT_METRO: |
| 112 value = 10; |
| 113 break; |
| 114 default: |
| 115 value = 5; |
| 116 } |
| 117 } |
| 118 return value; |
| 119 } |
| 120 |
| 121 // Amount the left edge of a tab is offset from the rectangle of the tab's |
| 122 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. |
| 123 const int GetTabHOffset() { |
| 124 static int value = -1; |
| 125 if (value == -1) { |
| 126 switch (ui::GetDisplayLayout()) { |
| 127 case ui::LAYOUT_ASH: |
| 128 value = -27; |
| 129 break; |
| 130 case ui::LAYOUT_METRO: |
| 131 value = -16; |
| 132 break; |
| 133 default: |
| 134 value = -16; |
| 135 } |
| 136 } |
| 137 return value; |
| 138 } |
96 | 139 |
97 // Animation delegate used when a dragged tab is released. When done sets the | 140 // Animation delegate used when a dragged tab is released. When done sets the |
98 // dragging state to false. | 141 // dragging state to false. |
99 class ResetDraggingStateDelegate | 142 class ResetDraggingStateDelegate |
100 : public views::BoundsAnimator::OwnedAnimationDelegate { | 143 : public views::BoundsAnimator::OwnedAnimationDelegate { |
101 public: | 144 public: |
102 explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { | 145 explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { |
103 } | 146 } |
104 | 147 |
105 virtual void AnimationEnded(const ui::Animation* animation) { | 148 virtual void AnimationEnded(const ui::Animation* animation) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 int height = mask->height(); | 288 int height = mask->height(); |
246 int width = mask->width(); | 289 int width = mask->width(); |
247 gfx::Canvas canvas(gfx::Size(width, height), false); | 290 gfx::Canvas canvas(gfx::Size(width, height), false); |
248 | 291 |
249 // For custom images the background starts at the top of the tab strip. | 292 // For custom images the background starts at the top of the tab strip. |
250 // Otherwise the background starts at the top of the frame. | 293 // Otherwise the background starts at the top of the frame. |
251 SkBitmap* background = GetThemeProvider()->GetBitmapNamed(background_id); | 294 SkBitmap* background = GetThemeProvider()->GetBitmapNamed(background_id); |
252 int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? | 295 int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? |
253 0 : background_offset_.y(); | 296 0 : background_offset_.y(); |
254 canvas.TileImageInt(*background, GetMirroredX() + background_offset_.x(), | 297 canvas.TileImageInt(*background, GetMirroredX() + background_offset_.x(), |
255 kNewTabButtonVOffset + offset_y, 0, 0, width, height); | 298 GetNewTabButtonVOffset() + offset_y, 0, 0, width, height); |
256 | 299 |
257 if (alpha != 255) { | 300 if (alpha != 255) { |
258 SkPaint paint; | 301 SkPaint paint; |
259 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); | 302 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); |
260 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); | 303 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); |
261 paint.setStyle(SkPaint::kFill_Style); | 304 paint.setStyle(SkPaint::kFill_Style); |
262 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); | 305 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); |
263 } | 306 } |
264 | 307 |
265 // White highlight on hover. | 308 // White highlight on hover. |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 | 532 |
490 int model_count = GetModelCount(); | 533 int model_count = GetModelCount(); |
491 if (model_index + 1 != model_count && model_count > 1) { | 534 if (model_index + 1 != model_count && model_count > 1) { |
492 // The user is about to close a tab other than the last tab. Set | 535 // The user is about to close a tab other than the last tab. Set |
493 // available_width_for_tabs_ so that if we do a layout we don't position a | 536 // available_width_for_tabs_ so that if we do a layout we don't position a |
494 // tab past the end of the second to last tab. We do this so that as the | 537 // tab past the end of the second to last tab. We do this so that as the |
495 // user closes tabs with the mouse a tab continues to fall under the mouse. | 538 // user closes tabs with the mouse a tab continues to fall under the mouse. |
496 Tab* last_tab = tab_at(model_count - 1); | 539 Tab* last_tab = tab_at(model_count - 1); |
497 Tab* tab_being_removed = tab_at(model_index); | 540 Tab* tab_being_removed = tab_at(model_index); |
498 available_width_for_tabs_ = last_tab->x() + last_tab->width() - | 541 available_width_for_tabs_ = last_tab->x() + last_tab->width() - |
499 tab_being_removed->width() - kTabHOffset; | 542 tab_being_removed->width() - GetTabHOffset(); |
500 if (model_index == 0 && tab_being_removed->data().mini && | 543 if (model_index == 0 && tab_being_removed->data().mini && |
501 !tab_at(1)->data().mini) { | 544 !tab_at(1)->data().mini) { |
502 available_width_for_tabs_ -= kMiniToNonMiniGap; | 545 available_width_for_tabs_ -= kMiniToNonMiniGap; |
503 } | 546 } |
504 } | 547 } |
505 | 548 |
506 in_tab_close_ = true; | 549 in_tab_close_ = true; |
507 AddMessageLoopObserver(); | 550 AddMessageLoopObserver(); |
508 } | 551 } |
509 | 552 |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 std::string TabStrip::GetClassName() const { | 957 std::string TabStrip::GetClassName() const { |
915 return kViewClassName; | 958 return kViewClassName; |
916 } | 959 } |
917 | 960 |
918 gfx::Size TabStrip::GetPreferredSize() { | 961 gfx::Size TabStrip::GetPreferredSize() { |
919 // Report the minimum width as the size required for a single selected tab | 962 // Report the minimum width as the size required for a single selected tab |
920 // plus the new tab button. Don't base it on the actual number of tabs because | 963 // plus the new tab button. Don't base it on the actual number of tabs because |
921 // it's undesirable to have the minimum window size change when a new tab is | 964 // it's undesirable to have the minimum window size change when a new tab is |
922 // opened. | 965 // opened. |
923 int needed_width = Tab::GetMinimumSelectedSize().width(); | 966 int needed_width = Tab::GetMinimumSelectedSize().width(); |
924 needed_width += kNewTabButtonHOffset - kTabHOffset; | 967 needed_width += GetNewTabButtonHOffset() - GetTabHOffset(); |
925 needed_width += newtab_button_bounds_.width(); | 968 needed_width += newtab_button_bounds_.width(); |
926 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); | 969 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); |
927 } | 970 } |
928 | 971 |
929 void TabStrip::OnDragEntered(const DropTargetEvent& event) { | 972 void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
930 // Force animations to stop, otherwise it makes the index calculation tricky. | 973 // Force animations to stop, otherwise it makes the index calculation tricky. |
931 StopAnimating(true); | 974 StopAnimating(true); |
932 | 975 |
933 UpdateDropIndex(event); | 976 UpdateDropIndex(event); |
934 } | 977 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 available_width_for_tabs_ = -1; | 1134 available_width_for_tabs_ = -1; |
1092 | 1135 |
1093 GenerateIdealBounds(); | 1136 GenerateIdealBounds(); |
1094 | 1137 |
1095 BaseTab* tab = tab_at(model_index); | 1138 BaseTab* tab = tab_at(model_index); |
1096 if (model_index == 0) { | 1139 if (model_index == 0) { |
1097 tab->SetBounds(0, ideal_bounds(model_index).y(), 0, | 1140 tab->SetBounds(0, ideal_bounds(model_index).y(), 0, |
1098 ideal_bounds(model_index).height()); | 1141 ideal_bounds(model_index).height()); |
1099 } else { | 1142 } else { |
1100 BaseTab* last_tab = tab_at(model_index - 1); | 1143 BaseTab* last_tab = tab_at(model_index - 1); |
1101 tab->SetBounds(last_tab->bounds().right() + kTabHOffset, | 1144 tab->SetBounds(last_tab->bounds().right() + GetTabHOffset(), |
1102 ideal_bounds(model_index).y(), 0, | 1145 ideal_bounds(model_index).y(), 0, |
1103 ideal_bounds(model_index).height()); | 1146 ideal_bounds(model_index).height()); |
1104 } | 1147 } |
1105 | 1148 |
1106 AnimateToIdealBounds(); | 1149 AnimateToIdealBounds(); |
1107 } | 1150 } |
1108 | 1151 |
1109 void TabStrip::StartMoveTabAnimation() { | 1152 void TabStrip::StartMoveTabAnimation() { |
1110 PrepareForAnimation(); | 1153 PrepareForAnimation(); |
1111 GenerateIdealBounds(); | 1154 GenerateIdealBounds(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 GenerateIdealBounds(); | 1219 GenerateIdealBounds(); |
1177 | 1220 |
1178 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); | 1221 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); |
1179 | 1222 |
1180 SchedulePaint(); | 1223 SchedulePaint(); |
1181 | 1224 |
1182 // It is possible we don't have a new tab button yet. | 1225 // It is possible we don't have a new tab button yet. |
1183 if (newtab_button_) { | 1226 if (newtab_button_) { |
1184 if (SizeTabButtonToTopOfTabStrip()) { | 1227 if (SizeTabButtonToTopOfTabStrip()) { |
1185 newtab_button_bounds_.set_height( | 1228 newtab_button_bounds_.set_height( |
1186 kNewTabButtonHeight + kNewTabButtonVOffset); | 1229 kNewTabButtonHeight + GetNewTabButtonVOffset()); |
1187 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1230 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
1188 views::ImageButton::ALIGN_BOTTOM); | 1231 views::ImageButton::ALIGN_BOTTOM); |
1189 } else { | 1232 } else { |
1190 newtab_button_bounds_.set_height(kNewTabButtonHeight); | 1233 newtab_button_bounds_.set_height(kNewTabButtonHeight); |
1191 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1234 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
1192 views::ImageButton::ALIGN_TOP); | 1235 views::ImageButton::ALIGN_TOP); |
1193 } | 1236 } |
1194 newtab_button_->SetBoundsRect(newtab_button_bounds_); | 1237 newtab_button_->SetBoundsRect(newtab_button_bounds_); |
1195 } | 1238 } |
1196 } | 1239 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<BaseTab*>& tabs, | 1284 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<BaseTab*>& tabs, |
1242 std::vector<gfx::Rect>* bounds) { | 1285 std::vector<gfx::Rect>* bounds) { |
1243 int x = 0; | 1286 int x = 0; |
1244 for (size_t i = 0; i < tabs.size(); ++i) { | 1287 for (size_t i = 0; i < tabs.size(); ++i) { |
1245 BaseTab* tab = tabs[i]; | 1288 BaseTab* tab = tabs[i]; |
1246 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) | 1289 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) |
1247 x += kMiniToNonMiniGap; | 1290 x += kMiniToNonMiniGap; |
1248 gfx::Rect new_bounds = tab->bounds(); | 1291 gfx::Rect new_bounds = tab->bounds(); |
1249 new_bounds.set_origin(gfx::Point(x, 0)); | 1292 new_bounds.set_origin(gfx::Point(x, 0)); |
1250 bounds->push_back(new_bounds); | 1293 bounds->push_back(new_bounds); |
1251 x += tab->width() + kTabHOffset; | 1294 x += tab->width() + GetTabHOffset(); |
1252 } | 1295 } |
1253 } | 1296 } |
1254 | 1297 |
1255 int TabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { | 1298 int TabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { |
1256 int width = 0; | 1299 int width = 0; |
1257 for (size_t i = 0; i < tabs.size(); ++i) { | 1300 for (size_t i = 0; i < tabs.size(); ++i) { |
1258 BaseTab* tab = tabs[i]; | 1301 BaseTab* tab = tabs[i]; |
1259 width += tab->width(); | 1302 width += tab->width(); |
1260 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) | 1303 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) |
1261 width += kMiniToNonMiniGap; | 1304 width += kMiniToNonMiniGap; |
1262 } | 1305 } |
1263 if (tabs.size() > 0) | 1306 if (tabs.size() > 0) |
1264 width += kTabHOffset * static_cast<int>(tabs.size() - 1); | 1307 width += GetTabHOffset() * static_cast<int>(tabs.size() - 1); |
1265 return width; | 1308 return width; |
1266 } | 1309 } |
1267 | 1310 |
1268 void TabStrip::RemoveTabFromViewModel(int index) { | 1311 void TabStrip::RemoveTabFromViewModel(int index) { |
1269 // We still need to paint the tab until we actually remove it. Put it | 1312 // We still need to paint the tab until we actually remove it. Put it |
1270 // in tabs_closing_map_ so we can find it. | 1313 // in tabs_closing_map_ so we can find it. |
1271 tabs_closing_map_[index].push_back(tab_at(index)); | 1314 tabs_closing_map_[index].push_back(tab_at(index)); |
1272 UpdateTabsClosingMap(index + 1, -1); | 1315 UpdateTabsClosingMap(index + 1, -1); |
1273 tabs_.Remove(index); | 1316 tabs_.Remove(index); |
1274 } | 1317 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 for (int i = index1; i < index2; ++i) { | 1436 for (int i = index1; i < index2; ++i) { |
1394 if (!tab_at(i)->closing()) | 1437 if (!tab_at(i)->closing()) |
1395 count++; | 1438 count++; |
1396 } | 1439 } |
1397 return count; | 1440 return count; |
1398 } | 1441 } |
1399 | 1442 |
1400 void TabStrip::UpdateNumVisibleTabs(int non_closing_tab_count, | 1443 void TabStrip::UpdateNumVisibleTabs(int non_closing_tab_count, |
1401 int width, | 1444 int width, |
1402 double tab_size) { | 1445 double tab_size) { |
1403 num_visible_tabs_ = (width + kTabHOffset) / (tab_size + kTabHOffset); | 1446 num_visible_tabs_ = (width + GetTabHOffset()) / (tab_size + GetTabHOffset()); |
1404 num_visible_tabs_ = std::max(1, num_visible_tabs_); | 1447 num_visible_tabs_ = std::max(1, num_visible_tabs_); |
1405 // Make sure the first_visible_tab_index_ is valid. | 1448 // Make sure the first_visible_tab_index_ is valid. |
1406 // TODO: this isn't quite right, it doesn't take into account closing tabs. | 1449 // TODO: this isn't quite right, it doesn't take into account closing tabs. |
1407 first_visible_tab_index_ = | 1450 first_visible_tab_index_ = |
1408 std::min(first_visible_tab_index_, non_closing_tab_count - | 1451 std::min(first_visible_tab_index_, non_closing_tab_count - |
1409 num_visible_tabs_); | 1452 num_visible_tabs_); |
1410 first_visible_tab_index_ = std::max(0, first_visible_tab_index_); | 1453 first_visible_tab_index_ = std::max(0, first_visible_tab_index_); |
1411 } | 1454 } |
1412 | 1455 |
1413 void TabStrip::EnsureModelIndexIsVisible(int model_index) { | 1456 void TabStrip::EnsureModelIndexIsVisible(int model_index) { |
(...skipping 27 matching lines...) Expand all Loading... |
1441 | 1484 |
1442 if (tab_count == 0) { | 1485 if (tab_count == 0) { |
1443 // Return immediately to avoid divide-by-zero below. | 1486 // Return immediately to avoid divide-by-zero below. |
1444 return; | 1487 return; |
1445 } | 1488 } |
1446 | 1489 |
1447 // Determine how much space we can actually allocate to tabs. | 1490 // Determine how much space we can actually allocate to tabs. |
1448 int available_width; | 1491 int available_width; |
1449 if (available_width_for_tabs_ < 0) { | 1492 if (available_width_for_tabs_ < 0) { |
1450 available_width = width(); | 1493 available_width = width(); |
1451 available_width -= (kNewTabButtonHOffset + newtab_button_bounds_.width()); | 1494 available_width -= |
| 1495 (GetNewTabButtonHOffset() + newtab_button_bounds_.width()); |
1452 } else { | 1496 } else { |
1453 // Interesting corner case: if |available_width_for_tabs_| > the result | 1497 // Interesting corner case: if |available_width_for_tabs_| > the result |
1454 // of the calculation in the conditional arm above, the strip is in | 1498 // of the calculation in the conditional arm above, the strip is in |
1455 // overflow. We can either use the specified width or the true available | 1499 // overflow. We can either use the specified width or the true available |
1456 // width here; the first preserves the consistent "leave the last tab under | 1500 // width here; the first preserves the consistent "leave the last tab under |
1457 // the user's mouse so they can close many tabs" behavior at the cost of | 1501 // the user's mouse so they can close many tabs" behavior at the cost of |
1458 // prolonging the glitchy appearance of the overflow state, while the second | 1502 // prolonging the glitchy appearance of the overflow state, while the second |
1459 // gets us out of overflow as soon as possible but forces the user to move | 1503 // gets us out of overflow as soon as possible but forces the user to move |
1460 // their mouse for a few tabs' worth of closing. We choose visual | 1504 // their mouse for a few tabs' worth of closing. We choose visual |
1461 // imperfection over behavioral imperfection and select the first option. | 1505 // imperfection over behavioral imperfection and select the first option. |
1462 available_width = available_width_for_tabs_; | 1506 available_width = available_width_for_tabs_; |
1463 } | 1507 } |
1464 | 1508 |
1465 if (mini_tab_count > 0) { | 1509 if (mini_tab_count > 0) { |
1466 available_width -= mini_tab_count * (Tab::GetMiniWidth() + kTabHOffset); | 1510 available_width -= mini_tab_count * (Tab::GetMiniWidth() + GetTabHOffset()); |
1467 tab_count -= mini_tab_count; | 1511 tab_count -= mini_tab_count; |
1468 if (tab_count == 0) { | 1512 if (tab_count == 0) { |
1469 *selected_width = *unselected_width = Tab::GetStandardSize().width(); | 1513 *selected_width = *unselected_width = Tab::GetStandardSize().width(); |
1470 return; | 1514 return; |
1471 } | 1515 } |
1472 // Account for gap between the last mini-tab and first non-mini-tab. | 1516 // Account for gap between the last mini-tab and first non-mini-tab. |
1473 available_width -= kMiniToNonMiniGap; | 1517 available_width -= kMiniToNonMiniGap; |
1474 } | 1518 } |
1475 | 1519 |
1476 // Calculate the desired tab widths by dividing the available space into equal | 1520 // Calculate the desired tab widths by dividing the available space into equal |
1477 // portions. Don't let tabs get larger than the "standard width" or smaller | 1521 // portions. Don't let tabs get larger than the "standard width" or smaller |
1478 // than the minimum width for each type, respectively. | 1522 // than the minimum width for each type, respectively. |
1479 const int total_offset = kTabHOffset * (tab_count - 1); | 1523 const int total_offset = GetTabHOffset() * (tab_count - 1); |
1480 const double desired_tab_width = std::min((static_cast<double>( | 1524 const double desired_tab_width = std::min((static_cast<double>( |
1481 available_width - total_offset) / static_cast<double>(tab_count)), | 1525 available_width - total_offset) / static_cast<double>(tab_count)), |
1482 static_cast<double>(Tab::GetStandardSize().width())); | 1526 static_cast<double>(Tab::GetStandardSize().width())); |
1483 *unselected_width = std::max(desired_tab_width, min_unselected_width); | 1527 *unselected_width = std::max(desired_tab_width, min_unselected_width); |
1484 *selected_width = std::max(desired_tab_width, min_selected_width); | 1528 *selected_width = std::max(desired_tab_width, min_selected_width); |
1485 | 1529 |
1486 // When there are multiple tabs, we'll have one selected and some unselected | 1530 // When there are multiple tabs, we'll have one selected and some unselected |
1487 // tabs. If the desired width was between the minimum sizes of these types, | 1531 // tabs. If the desired width was between the minimum sizes of these types, |
1488 // try to shrink the tabs with the smaller minimum. For example, if we have | 1532 // try to shrink the tabs with the smaller minimum. For example, if we have |
1489 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If | 1533 // 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... |
1562 } | 1606 } |
1563 | 1607 |
1564 gfx::Rect TabStrip::GetDropBounds(int drop_index, | 1608 gfx::Rect TabStrip::GetDropBounds(int drop_index, |
1565 bool drop_before, | 1609 bool drop_before, |
1566 bool* is_beneath) { | 1610 bool* is_beneath) { |
1567 DCHECK_NE(drop_index, -1); | 1611 DCHECK_NE(drop_index, -1); |
1568 int center_x; | 1612 int center_x; |
1569 if (drop_index < tab_count()) { | 1613 if (drop_index < tab_count()) { |
1570 Tab* tab = tab_at(drop_index); | 1614 Tab* tab = tab_at(drop_index); |
1571 if (drop_before) | 1615 if (drop_before) |
1572 center_x = tab->x() - (kTabHOffset / 2); | 1616 center_x = tab->x() - (GetTabHOffset() / 2); |
1573 else | 1617 else |
1574 center_x = tab->x() + (tab->width() / 2); | 1618 center_x = tab->x() + (tab->width() / 2); |
1575 } else { | 1619 } else { |
1576 Tab* last_tab = tab_at(drop_index - 1); | 1620 Tab* last_tab = tab_at(drop_index - 1); |
1577 center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2); | 1621 center_x = last_tab->x() + last_tab->width() + (GetTabHOffset() / 2); |
1578 } | 1622 } |
1579 | 1623 |
1580 // Mirror the center point if necessary. | 1624 // Mirror the center point if necessary. |
1581 center_x = GetMirroredXInView(center_x); | 1625 center_x = GetMirroredXInView(center_x); |
1582 | 1626 |
1583 // Determine the screen bounds. | 1627 // Determine the screen bounds. |
1584 gfx::Point drop_loc(center_x - drop_indicator_width / 2, | 1628 gfx::Point drop_loc(center_x - drop_indicator_width / 2, |
1585 -drop_indicator_height); | 1629 -drop_indicator_height); |
1586 ConvertPointToScreen(this, &drop_loc); | 1630 ConvertPointToScreen(this, &drop_loc); |
1587 gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, | 1631 gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 tab_x += kMiniToNonMiniGap; | 1797 tab_x += kMiniToNonMiniGap; |
1754 } | 1798 } |
1755 if (tab->IsActive()) | 1799 if (tab->IsActive()) |
1756 tab_width = selected; | 1800 tab_width = selected; |
1757 } | 1801 } |
1758 double end_of_tab = tab_x + tab_width; | 1802 double end_of_tab = tab_x + tab_width; |
1759 int rounded_tab_x = Round(tab_x); | 1803 int rounded_tab_x = Round(tab_x); |
1760 set_ideal_bounds(i, | 1804 set_ideal_bounds(i, |
1761 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, | 1805 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, |
1762 tab_height)); | 1806 tab_height)); |
1763 tab_x = end_of_tab + kTabHOffset; | 1807 tab_x = end_of_tab + GetTabHOffset(); |
1764 last_was_mini = tab->data().mini; | 1808 last_was_mini = tab->data().mini; |
1765 } | 1809 } |
1766 } | 1810 } |
1767 | 1811 |
1768 // If we're in stacking mode, update the positions now that we have | 1812 // If we're in stacking mode, update the positions now that we have |
1769 // appropriate widths. | 1813 // appropriate widths. |
1770 if (stacking_ && tab_x - kTabHOffset > | 1814 if (stacking_ && tab_x - GetTabHOffset() > |
1771 width() - newtab_button_bounds_.width()) { | 1815 width() - newtab_button_bounds_.width()) { |
1772 tab_x = GenerateIdealBoundsWithStacking( | 1816 tab_x = GenerateIdealBoundsWithStacking( |
1773 mini_tab_count, non_closing_tab_count, tab_x, selected); | 1817 mini_tab_count, non_closing_tab_count, tab_x, selected); |
1774 } | 1818 } |
1775 | 1819 |
1776 // Update bounds of new tab button. | 1820 // Update bounds of new tab button. |
1777 int new_tab_x; | 1821 int new_tab_x; |
1778 int new_tab_y = SizeTabButtonToTopOfTabStrip() ? 0 : kNewTabButtonVOffset; | 1822 int new_tab_y = SizeTabButtonToTopOfTabStrip() ? 0 : GetNewTabButtonVOffset(); |
1779 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && | 1823 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && |
1780 !in_tab_close_) { | 1824 !in_tab_close_) { |
1781 // We're shrinking tabs, so we need to anchor the New Tab button to the | 1825 // We're shrinking tabs, so we need to anchor the New Tab button to the |
1782 // right edge of the TabStrip's bounds, rather than the right edge of the | 1826 // right edge of the TabStrip's bounds, rather than the right edge of the |
1783 // right-most Tab, otherwise it'll bounce when animating. | 1827 // right-most Tab, otherwise it'll bounce when animating. |
1784 new_tab_x = width() - newtab_button_bounds_.width(); | 1828 new_tab_x = width() - newtab_button_bounds_.width(); |
1785 } else { | 1829 } else { |
1786 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; | 1830 new_tab_x = Round(tab_x - GetTabHOffset()) + GetNewTabButtonHOffset(); |
1787 } | 1831 } |
1788 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); | 1832 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); |
1789 } | 1833 } |
1790 | 1834 |
1791 double TabStrip::GenerateIdealBoundsWithStacking(int mini_tab_count, | 1835 double TabStrip::GenerateIdealBoundsWithStacking(int mini_tab_count, |
1792 int non_closing_tab_count, | 1836 int non_closing_tab_count, |
1793 double new_tab_x, | 1837 double new_tab_x, |
1794 double selected_size) { | 1838 double selected_size) { |
1795 if (non_closing_tab_count == mini_tab_count) | 1839 if (non_closing_tab_count == mini_tab_count) |
1796 return new_tab_x; | 1840 return new_tab_x; |
1797 | 1841 |
1798 // Pinned tabs always have their desired size, and don't stack. We rely on | 1842 // Pinned tabs always have their desired size, and don't stack. We rely on |
1799 // GenerateIdealBounds to have positioned pinned tabs already, so don't move | 1843 // GenerateIdealBounds to have positioned pinned tabs already, so don't move |
1800 // them. | 1844 // them. |
1801 int tab_index = 0; | 1845 int tab_index = 0; |
1802 double next_x = 0; | 1846 double next_x = 0; |
1803 for (; tab_index < tab_count(); ++tab_index) { | 1847 for (; tab_index < tab_count(); ++tab_index) { |
1804 BaseTab* tab = tab_at(tab_index); | 1848 BaseTab* tab = tab_at(tab_index); |
1805 if (!tab->closing() && !tab->data().mini) { | 1849 if (!tab->closing() && !tab->data().mini) { |
1806 next_x = ideal_bounds(tab_index).x(); | 1850 next_x = ideal_bounds(tab_index).x(); |
1807 break; | 1851 break; |
1808 } | 1852 } |
1809 } | 1853 } |
1810 if (tab_index == tab_count()) | 1854 if (tab_index == tab_count()) |
1811 return new_tab_x; | 1855 return new_tab_x; |
1812 | 1856 |
1813 // Always reserve kMaxEdgeStackWidth on each side for stacking. We don't | 1857 // Always reserve kMaxEdgeStackWidth on each side for stacking. We don't |
1814 // later try to adjust as it can lead to tabs bouncing around. | 1858 // later try to adjust as it can lead to tabs bouncing around. |
1815 int available_width = width() - | 1859 int available_width = width() - |
1816 (kNewTabButtonHOffset + newtab_button_bounds_.width()) - next_x - | 1860 (GetNewTabButtonHOffset() + newtab_button_bounds_.width()) - next_x - |
1817 2 * kMaxEdgeStackWidth; | 1861 2 * kMaxEdgeStackWidth; |
1818 if (available_width <= 0) | 1862 if (available_width <= 0) |
1819 return new_tab_x; | 1863 return new_tab_x; |
1820 UpdateNumVisibleTabs(non_closing_tab_count, available_width, selected_size); | 1864 UpdateNumVisibleTabs(non_closing_tab_count, available_width, selected_size); |
1821 int stacked_leading_index = tab_index; | 1865 int stacked_leading_index = tab_index; |
1822 int stacked_trailing_index = first_visible_tab_index_; | 1866 int stacked_trailing_index = first_visible_tab_index_; |
1823 for (int visible_count = 0; | 1867 for (int visible_count = 0; |
1824 stacked_trailing_index < tab_count() && | 1868 stacked_trailing_index < tab_count() && |
1825 visible_count < num_visible_tabs_; ++stacked_trailing_index) { | 1869 visible_count < num_visible_tabs_; ++stacked_trailing_index) { |
1826 if (!tab_at(stacked_trailing_index)->closing()) | 1870 if (!tab_at(stacked_trailing_index)->closing()) |
(...skipping 18 matching lines...) Expand all Loading... |
1845 } | 1889 } |
1846 } else { | 1890 } else { |
1847 tab_index = first_visible_tab_index_; | 1891 tab_index = first_visible_tab_index_; |
1848 } | 1892 } |
1849 | 1893 |
1850 if (stacked_leading_count > 0 && stacked_trailing_count == 0) { | 1894 if (stacked_leading_count > 0 && stacked_trailing_count == 0) { |
1851 // If there are no stacked tabs on the right and there is extra space, give | 1895 // If there are no stacked tabs on the right and there is extra space, give |
1852 // it to the last stacked tab on the left. | 1896 // it to the last stacked tab on the left. |
1853 next_x += available_width + kMaxEdgeStackWidth - | 1897 next_x += available_width + kMaxEdgeStackWidth - |
1854 (num_visible_tabs_ * selected_size + | 1898 (num_visible_tabs_ * selected_size + |
1855 std::max(num_visible_tabs_ - 1, 0) * kTabHOffset); | 1899 std::max(num_visible_tabs_ - 1, 0) * GetTabHOffset()); |
1856 } | 1900 } |
1857 | 1901 |
1858 // Totally visible tabs. | 1902 // Totally visible tabs. |
1859 for (int visible_count = 0; | 1903 for (int visible_count = 0; |
1860 tab_index < tab_count() && visible_count < num_visible_tabs_; | 1904 tab_index < tab_count() && visible_count < num_visible_tabs_; |
1861 tab_index++) { | 1905 tab_index++) { |
1862 if (tab_at(tab_index)->closing()) | 1906 if (tab_at(tab_index)->closing()) |
1863 continue; | 1907 continue; |
1864 gfx::Rect bounds = ideal_bounds(tab_index); | 1908 gfx::Rect bounds = ideal_bounds(tab_index); |
1865 bounds.set_x(next_x); | 1909 bounds.set_x(next_x); |
1866 next_x = bounds.right() + kTabHOffset; | 1910 next_x = bounds.right() + GetTabHOffset(); |
1867 set_ideal_bounds(tab_index, bounds); | 1911 set_ideal_bounds(tab_index, bounds); |
1868 visible_count++; | 1912 visible_count++; |
1869 } | 1913 } |
1870 | 1914 |
1871 // Stacked tabs to the right. | 1915 // Stacked tabs to the right. |
1872 if (stacked_trailing_count == 0) | 1916 if (stacked_trailing_count == 0) |
1873 return next_x; | 1917 return next_x; |
1874 | 1918 |
1875 double stacked_offset = | 1919 double stacked_offset = |
1876 kMaxEdgeStackWidth / static_cast<double>(stacked_trailing_count); | 1920 kMaxEdgeStackWidth / static_cast<double>(stacked_trailing_count); |
1877 next_x = width() - (kNewTabButtonHOffset + newtab_button_bounds_.width()) - | 1921 next_x = width() - |
| 1922 (GetNewTabButtonHOffset() + newtab_button_bounds_.width()) - |
1878 (stacked_trailing_count - 1) * stacked_offset - selected_size; | 1923 (stacked_trailing_count - 1) * stacked_offset - selected_size; |
1879 for (; tab_index < tab_count(); ++tab_index) { | 1924 for (; tab_index < tab_count(); ++tab_index) { |
1880 if (tab_at(tab_index)->closing()) | 1925 if (tab_at(tab_index)->closing()) |
1881 continue; | 1926 continue; |
1882 gfx::Rect bounds = ideal_bounds(tab_index); | 1927 gfx::Rect bounds = ideal_bounds(tab_index); |
1883 bounds.set_x(next_x); | 1928 bounds.set_x(next_x); |
1884 set_ideal_bounds(tab_index, bounds); | 1929 set_ideal_bounds(tab_index, bounds); |
1885 next_x += stacked_offset; | 1930 next_x += stacked_offset; |
1886 } | 1931 } |
1887 | 1932 |
1888 return next_x + kTabHOffset; | 1933 return next_x + GetTabHOffset(); |
1889 } | 1934 } |
1890 | 1935 |
1891 void TabStrip::StartResizeLayoutAnimation() { | 1936 void TabStrip::StartResizeLayoutAnimation() { |
1892 PrepareForAnimation(); | 1937 PrepareForAnimation(); |
1893 GenerateIdealBounds(); | 1938 GenerateIdealBounds(); |
1894 AnimateToIdealBounds(); | 1939 AnimateToIdealBounds(); |
1895 } | 1940 } |
1896 | 1941 |
1897 void TabStrip::StartMiniTabAnimation() { | 1942 void TabStrip::StartMiniTabAnimation() { |
1898 in_tab_close_ = false; | 1943 in_tab_close_ = false; |
1899 available_width_for_tabs_ = -1; | 1944 available_width_for_tabs_ = -1; |
1900 | 1945 |
1901 PrepareForAnimation(); | 1946 PrepareForAnimation(); |
1902 | 1947 |
1903 GenerateIdealBounds(); | 1948 GenerateIdealBounds(); |
1904 AnimateToIdealBounds(); | 1949 AnimateToIdealBounds(); |
1905 } | 1950 } |
1906 | 1951 |
1907 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { | 1952 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { |
1908 // The user initiated the close. We want to persist the bounds of all the | 1953 // The user initiated the close. We want to persist the bounds of all the |
1909 // existing tabs, so we manually shift ideal_bounds then animate. | 1954 // existing tabs, so we manually shift ideal_bounds then animate. |
1910 BaseTab* tab_closing = tab_at(model_index); | 1955 BaseTab* tab_closing = tab_at(model_index); |
1911 int delta = tab_closing->width() + kTabHOffset; | 1956 int delta = tab_closing->width() + GetTabHOffset(); |
1912 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to | 1957 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to |
1913 // add the extra padding. | 1958 // add the extra padding. |
1914 DCHECK_NE(model_index + 1, tab_count()); | 1959 DCHECK_NE(model_index + 1, tab_count()); |
1915 if (tab_closing->data().mini && model_index + 1 < tab_count() && | 1960 if (tab_closing->data().mini && model_index + 1 < tab_count() && |
1916 !tab_at(model_index + 1)->data().mini) { | 1961 !tab_at(model_index + 1)->data().mini) { |
1917 delta += kMiniToNonMiniGap; | 1962 delta += kMiniToNonMiniGap; |
1918 } | 1963 } |
1919 | 1964 |
1920 for (int i = model_index + 1; i < tab_count(); ++i) { | 1965 for (int i = model_index + 1; i < tab_count(); ++i) { |
1921 gfx::Rect bounds = ideal_bounds(i); | 1966 gfx::Rect bounds = ideal_bounds(i); |
(...skipping 24 matching lines...) Expand all Loading... |
1946 new RemoveTabDelegate(this, tab_closing), | 1991 new RemoveTabDelegate(this, tab_closing), |
1947 true); | 1992 true); |
1948 } | 1993 } |
1949 | 1994 |
1950 bool TabStrip::IsPointInTab(Tab* tab, | 1995 bool TabStrip::IsPointInTab(Tab* tab, |
1951 const gfx::Point& point_in_tabstrip_coords) { | 1996 const gfx::Point& point_in_tabstrip_coords) { |
1952 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); | 1997 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); |
1953 View::ConvertPointToView(this, tab, &point_in_tab_coords); | 1998 View::ConvertPointToView(this, tab, &point_in_tab_coords); |
1954 return tab->HitTest(point_in_tab_coords); | 1999 return tab->HitTest(point_in_tab_coords); |
1955 } | 2000 } |
OLD | NEW |