| 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 |