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