Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: ui/views/controls/tabbed_pane/tabbed_pane.cc

Issue 2415633002: TabbedPane: refactor away manual layout and selected_tab_index_ (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "ui/views/controls/tabbed_pane/tabbed_pane.h" 5 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "third_party/skia/include/core/SkPaint.h" 9 #include "third_party/skia/include/core/SkPaint.h"
10 #include "third_party/skia/include/core/SkPath.h" 10 #include "third_party/skia/include/core/SkPath.h"
11 #include "ui/accessibility/ax_view_state.h" 11 #include "ui/accessibility/ax_view_state.h"
12 #include "ui/base/default_style.h" 12 #include "ui/base/default_style.h"
13 #include "ui/base/material_design/material_design_controller.h" 13 #include "ui/base/material_design/material_design_controller.h"
14 #include "ui/base/resource/resource_bundle.h" 14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/events/keycodes/keyboard_codes.h" 15 #include "ui/events/keycodes/keyboard_codes.h"
16 #include "ui/gfx/canvas.h" 16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/font_list.h" 17 #include "ui/gfx/font_list.h"
18 #include "ui/native_theme/native_theme.h" 18 #include "ui/native_theme/native_theme.h"
19 #include "ui/views/border.h" 19 #include "ui/views/border.h"
20 #include "ui/views/controls/label.h" 20 #include "ui/views/controls/label.h"
21 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h" 21 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
22 #include "ui/views/layout/box_layout.h" 22 #include "ui/views/layout/box_layout.h"
23 #include "ui/views/layout/fill_layout.h"
23 #include "ui/views/layout/layout_manager.h" 24 #include "ui/views/layout/layout_manager.h"
24 #include "ui/views/widget/widget.h" 25 #include "ui/views/widget/widget.h"
25 26
26 namespace { 27 namespace {
27 28
28 // TODO(markusheintz|msw): Use NativeTheme colors. 29 // TODO(markusheintz|msw): Use NativeTheme colors.
29 const SkColor kTabTitleColor_Inactive = SkColorSetRGB(0x64, 0x64, 0x64); 30 const SkColor kTabTitleColor_Inactive = SkColorSetRGB(0x64, 0x64, 0x64);
30 const SkColor kTabTitleColor_Active = SK_ColorBLACK; 31 const SkColor kTabTitleColor_Active = SK_ColorBLACK;
31 const SkColor kTabTitleColor_Hovered = SK_ColorBLACK; 32 const SkColor kTabTitleColor_Hovered = SK_ColorBLACK;
32 const SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8); 33 const SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8);
(...skipping 17 matching lines...) Expand all
50 class MdTab : public Tab { 51 class MdTab : public Tab {
51 public: 52 public:
52 MdTab(TabbedPane* tabbed_pane, const base::string16& title, View* contents); 53 MdTab(TabbedPane* tabbed_pane, const base::string16& title, View* contents);
53 ~MdTab() override; 54 ~MdTab() override;
54 55
55 // Overridden from Tab: 56 // Overridden from Tab:
56 void OnStateChanged() override; 57 void OnStateChanged() override;
57 58
58 // Overridden from View: 59 // Overridden from View:
59 void OnPaintBorder(gfx::Canvas* canvas) override; 60 void OnPaintBorder(gfx::Canvas* canvas) override;
61 gfx::Size GetPreferredSize() const override;
msw 2016/10/12 20:18:35 nit: order above OnPaintBorder to match base class
Elly Fong-Jones 2016/10/12 21:23:05 Done.
60 62
61 private: 63 private:
62 DISALLOW_COPY_AND_ASSIGN(MdTab); 64 DISALLOW_COPY_AND_ASSIGN(MdTab);
63 }; 65 };
64 66
65 // The tab strip shown above the tab contents. 67 // The tab strip shown above the tab contents.
66 class TabStrip : public View { 68 class TabStrip : public View {
67 public: 69 public:
68 // Internal class name. 70 // Internal class name.
69 static const char kViewClassName[]; 71 static const char kViewClassName[];
70 72
71 explicit TabStrip(TabbedPane* tabbed_pane); 73 TabStrip();
72 ~TabStrip() override; 74 ~TabStrip() override;
73 75
74 // Overridden from View: 76 // Overridden from View:
75 gfx::Size GetPreferredSize() const override;
76 void Layout() override;
77 const char* GetClassName() const override; 77 const char* GetClassName() const override;
78 void OnPaint(gfx::Canvas* canvas) override; 78 void OnPaintBorder(gfx::Canvas* canvas) override;
79
80 Tab* GetSelectedTab() const;
81 Tab* GetTabAtDeltaFromSelected(int delta) const;
82 Tab* GetTabAtIndex(int index) const;
83 int GetSelectedTabIndex() const;
79 84
80 private: 85 private:
81 TabbedPane* tabbed_pane_;
82
83 DISALLOW_COPY_AND_ASSIGN(TabStrip); 86 DISALLOW_COPY_AND_ASSIGN(TabStrip);
84 }; 87 };
85 88
86 // A subclass of TabStrip that implements the Harmony visual styling. This 89 // A subclass of TabStrip that implements the Harmony visual styling. This
87 // class uses a BoxLayout to position tabs. 90 // class uses a BoxLayout to position tabs.
88 class MdTabStrip : public TabStrip { 91 class MdTabStrip : public TabStrip {
89 public: 92 public:
90 explicit MdTabStrip(TabbedPane* tabbed_pane); 93 MdTabStrip();
91 ~MdTabStrip() override; 94 ~MdTabStrip() override;
92 95
93 // Overridden from View: 96 // Overridden from View:
94 gfx::Size GetPreferredSize() const override; 97 void OnPaintBorder(gfx::Canvas* canvas) override;
95 void Layout() override;
96 void OnPaint(gfx::Canvas* canvas) override;
97 98
98 private: 99 private:
99 DISALLOW_COPY_AND_ASSIGN(MdTabStrip); 100 DISALLOW_COPY_AND_ASSIGN(MdTabStrip);
100 }; 101 };
101 102
102 // static 103 // static
103 const char Tab::kViewClassName[] = "Tab"; 104 const char Tab::kViewClassName[] = "Tab";
104 105
105 Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents) 106 Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
106 : tabbed_pane_(tabbed_pane), 107 : tabbed_pane_(tabbed_pane),
107 title_(new Label( 108 title_(new Label(
108 title, 109 title,
109 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( 110 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta(
110 ui::kLabelFontSizeDelta, 111 ui::kLabelFontSizeDelta,
111 gfx::Font::NORMAL, 112 gfx::Font::NORMAL,
112 kActiveWeight))), 113 kActiveWeight))),
113 tab_state_(TAB_ACTIVE), 114 tab_state_(TAB_ACTIVE),
114 contents_(contents) { 115 contents_(contents) {
115 // Calculate this now while the font list is guaranteed to be bold. 116 // Calculate this now while the font list is guaranteed to be bold.
116 preferred_title_size_ = title_->GetPreferredSize(); 117 preferred_title_size_ = title_->GetPreferredSize();
117 118
119 SetBorder(Border::CreateEmptyBorder(gfx::Insets(5, 10)));
msw 2016/10/12 20:18:35 nit: please use constants defined here or bonus po
Elly Fong-Jones 2016/10/12 21:23:05 Done.
120 SetLayoutManager(new FillLayout);
121
118 SetState(TAB_INACTIVE); 122 SetState(TAB_INACTIVE);
119 AddChildView(title_); 123 AddChildView(title_);
120 } 124 }
121 125
122 Tab::~Tab() {} 126 Tab::~Tab() {}
123 127
124 void Tab::SetSelected(bool selected) { 128 void Tab::SetSelected(bool selected) {
125 contents_->SetVisible(selected); 129 contents_->SetVisible(selected);
126 SetState(selected ? TAB_ACTIVE : TAB_INACTIVE); 130 SetState(selected ? TAB_ACTIVE : TAB_INACTIVE);
127 #if defined(OS_MACOSX) 131 #if defined(OS_MACOSX)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 SetState(selected() ? TAB_ACTIVE : TAB_INACTIVE); 184 SetState(selected() ? TAB_ACTIVE : TAB_INACTIVE);
181 break; 185 break;
182 default: 186 default:
183 break; 187 break;
184 } 188 }
185 event->SetHandled(); 189 event->SetHandled();
186 } 190 }
187 191
188 gfx::Size Tab::GetPreferredSize() const { 192 gfx::Size Tab::GetPreferredSize() const {
189 gfx::Size size(preferred_title_size_); 193 gfx::Size size(preferred_title_size_);
190 size.Enlarge(21, 9); 194 size.Enlarge(GetInsets().width(), GetInsets().height());
191 const int kTabMinWidth = 54;
192 if (size.width() < kTabMinWidth)
193 size.set_width(kTabMinWidth);
194 return size; 195 return size;
195 } 196 }
196 197
197 void Tab::Layout() {
198 gfx::Rect bounds = GetLocalBounds();
199 bounds.Inset(0, 1, 0, 0);
200 bounds.ClampToCenteredSize(preferred_title_size_);
201 title_->SetBoundsRect(bounds);
202 }
203
204 const char* Tab::GetClassName() const { 198 const char* Tab::GetClassName() const {
205 return kViewClassName; 199 return kViewClassName;
206 } 200 }
207 201
208 void Tab::SetState(TabState tab_state) { 202 void Tab::SetState(TabState tab_state) {
209 if (tab_state == tab_state_) 203 if (tab_state == tab_state_)
210 return; 204 return;
211 tab_state_ = tab_state; 205 tab_state_ = tab_state;
212 OnStateChanged(); 206 OnStateChanged();
213 SchedulePaint(); 207 SchedulePaint();
214 } 208 }
215 209
216 bool Tab::ContainerHasFocus() {
217 return tabbed_pane_->HasFocus();
218 }
219
220 void Tab::OnFocus() { 210 void Tab::OnFocus() {
221 OnStateChanged(); 211 OnStateChanged();
222 // When the tab gains focus, send an accessibility event indicating that the 212 // When the tab gains focus, send an accessibility event indicating that the
223 // contents are focused. When the tab loses focus, whichever new View ends up 213 // contents are focused. When the tab loses focus, whichever new View ends up
224 // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to 214 // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to
225 // send one in OnBlur(). 215 // send one in OnBlur().
226 if (contents()) 216 if (contents())
227 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); 217 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
228 SchedulePaint(); 218 SchedulePaint();
229 } 219 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 285
296 // Draw the lighter-colored stroke first, then draw the heavier stroke over 286 // Draw the lighter-colored stroke first, then draw the heavier stroke over
297 // the bottom of it. This is fine because the heavier stroke has 1.0 alpha, so 287 // the bottom of it. This is fine because the heavier stroke has 1.0 alpha, so
298 // the lighter stroke won't show through. 288 // the lighter stroke won't show through.
299 canvas->DrawRect(bounds, paint); 289 canvas->DrawRect(bounds, paint);
300 canvas->FillRect( 290 canvas->FillRect(
301 gfx::Rect(0, height() - kBorderStrokeWidth, width(), kBorderStrokeWidth), 291 gfx::Rect(0, height() - kBorderStrokeWidth, width(), kBorderStrokeWidth),
302 base_color); 292 base_color);
303 } 293 }
304 294
295 gfx::Size MdTab::GetPreferredSize() const {
296 return gfx::Size(Tab::GetPreferredSize().width(), kHarmonyTabStripTabHeight);
297 }
298
305 // static 299 // static
306 const char TabStrip::kViewClassName[] = "TabStrip"; 300 const char TabStrip::kViewClassName[] = "TabStrip";
307 301
308 TabStrip::TabStrip(TabbedPane* tabbed_pane) : tabbed_pane_(tabbed_pane) {} 302 TabStrip::TabStrip() {
303 BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal, 9, 0, 0);
msw 2016/10/12 20:18:35 ditto nit: 9 -> constant, shared if possible.
Elly Fong-Jones 2016/10/12 21:23:05 Done.
304 layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
305 layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END);
306 layout->SetDefaultFlex(0);
307 SetLayoutManager(layout);
308 }
309 309
310 TabStrip::~TabStrip() {} 310 TabStrip::~TabStrip() {}
311 311
312 gfx::Size TabStrip::GetPreferredSize() const {
313 gfx::Size size;
314 for (int i = 0; i < child_count(); ++i) {
315 const gfx::Size child_size = child_at(i)->GetPreferredSize();
316 size.SetSize(size.width() + child_size.width(),
317 std::max(size.height(), child_size.height()));
318 }
319 return size;
320 }
321
322 void TabStrip::Layout() {
323 const int kTabOffset = 9;
324 int x = kTabOffset; // Layout tabs with an offset to the tabstrip border.
325 for (int i = 0; i < child_count(); ++i) {
326 gfx::Size ps = child_at(i)->GetPreferredSize();
327 child_at(i)->SetBounds(x, 0, ps.width(), ps.height());
328 x = child_at(i)->bounds().right();
329 }
330 }
331
332 const char* TabStrip::GetClassName() const { 312 const char* TabStrip::GetClassName() const {
333 return kViewClassName; 313 return kViewClassName;
334 } 314 }
335 315
336 void TabStrip::OnPaint(gfx::Canvas* canvas) { 316 void TabStrip::OnPaintBorder(gfx::Canvas* canvas) {
337 OnPaintBackground(canvas);
338
339 // Draw the TabStrip border.
340 SkPaint paint; 317 SkPaint paint;
341 paint.setColor(kTabBorderColor); 318 paint.setColor(kTabBorderColor);
342 paint.setStrokeWidth(kTabBorderThickness); 319 paint.setStrokeWidth(kTabBorderThickness);
343 SkScalar line_y = SkIntToScalar(height()) - (kTabBorderThickness / 2); 320 SkScalar line_y = SkIntToScalar(height()) - (kTabBorderThickness / 2);
344 SkScalar line_end = SkIntToScalar(width()); 321 SkScalar line_end = SkIntToScalar(width());
345 int selected_tab_index = tabbed_pane_->selected_tab_index(); 322 int selected_tab_index = GetSelectedTabIndex();
346 if (selected_tab_index >= 0) { 323 if (selected_tab_index >= 0) {
347 Tab* selected_tab = tabbed_pane_->GetTabAt(selected_tab_index); 324 Tab* selected_tab = GetTabAtIndex(selected_tab_index);
348 SkPath path; 325 SkPath path;
349 SkScalar tab_height = 326 SkScalar tab_height =
350 SkIntToScalar(selected_tab->height()) - kTabBorderThickness; 327 SkIntToScalar(selected_tab->height()) - kTabBorderThickness;
351 SkScalar tab_width = 328 SkScalar tab_width =
352 SkIntToScalar(selected_tab->width()) - kTabBorderThickness; 329 SkIntToScalar(selected_tab->width()) - kTabBorderThickness;
353 SkScalar tab_start = SkIntToScalar(selected_tab->GetMirroredX()); 330 SkScalar tab_start = SkIntToScalar(selected_tab->GetMirroredX());
354 path.moveTo(0, line_y); 331 path.moveTo(0, line_y);
355 path.rLineTo(tab_start, 0); 332 path.rLineTo(tab_start, 0);
356 path.rLineTo(0, -tab_height); 333 path.rLineTo(0, -tab_height);
357 path.rLineTo(tab_width, 0); 334 path.rLineTo(tab_width, 0);
358 path.rLineTo(0, tab_height); 335 path.rLineTo(0, tab_height);
359 path.lineTo(line_end, line_y); 336 path.lineTo(line_end, line_y);
360 337
361 SkPaint paint; 338 SkPaint paint;
362 paint.setStyle(SkPaint::kStroke_Style); 339 paint.setStyle(SkPaint::kStroke_Style);
363 paint.setColor(kTabBorderColor); 340 paint.setColor(kTabBorderColor);
364 paint.setStrokeWidth(kTabBorderThickness); 341 paint.setStrokeWidth(kTabBorderThickness);
365 canvas->DrawPath(path, paint); 342 canvas->DrawPath(path, paint);
366 } else { 343 } else {
367 canvas->sk_canvas()->drawLine(0, line_y, line_end, line_y, paint); 344 canvas->sk_canvas()->drawLine(0, line_y, line_end, line_y, paint);
368 } 345 }
369 } 346 }
370 347
371 MdTabStrip::MdTabStrip(TabbedPane* tabbed_pane) : TabStrip(tabbed_pane) { 348 Tab* TabStrip::GetTabAtIndex(int index) const {
349 return static_cast<Tab*>(const_cast<View*>(child_at(index)));
350 }
351
352 int TabStrip::GetSelectedTabIndex() const {
353 for (int i = 0; i < child_count(); ++i)
354 if (GetTabAtIndex(i)->selected())
355 return i;
356 return -1;
357 }
358
359 Tab* TabStrip::GetSelectedTab() const {
360 int index = GetSelectedTabIndex();
361 return index >= 0 ? GetTabAtIndex(index) : nullptr;
362 }
363
364 Tab* TabStrip::GetTabAtDeltaFromSelected(int delta) const {
365 int index = (GetSelectedTabIndex() + delta) % child_count();
366 if (index < 0)
367 index += child_count();
368 return GetTabAtIndex(index);
369 }
370
371 MdTabStrip::MdTabStrip() {
372 BoxLayout* layout = 372 BoxLayout* layout =
373 new BoxLayout(BoxLayout::kHorizontal, 0, kHarmonyTabStripVerticalPad, 0); 373 new BoxLayout(BoxLayout::kHorizontal, 0, kHarmonyTabStripVerticalPad, 0);
374 layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); 374 layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
375 layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); 375 layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
376 layout->SetDefaultFlex(1); 376 layout->SetDefaultFlex(1);
377 SetLayoutManager(layout); 377 SetLayoutManager(layout);
378 } 378 }
379 379
380 MdTabStrip::~MdTabStrip() {} 380 MdTabStrip::~MdTabStrip() {}
381 381
382 gfx::Size MdTabStrip::GetPreferredSize() const { 382 // The tab strip "border" is drawn as part of the tabs.
383 return gfx::Size(width(), 383 void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) { }
msw 2016/10/12 20:18:35 nit: {}
Elly Fong-Jones 2016/10/12 21:23:05 Done.
384 kHarmonyTabStripVerticalPad * 2 + kHarmonyTabStripTabHeight);
385 }
386
387 // Let this class's LayoutManager handle the layout.
388 void MdTabStrip::Layout() {
389 return View::Layout();
390 }
391
392 // The tab strip "border" is drawn as part of the tabs, so all this method needs
393 // to do is paint the background.
394 void MdTabStrip::OnPaint(gfx::Canvas* canvas) {
395 OnPaintBackground(canvas);
396 }
397 384
398 TabbedPane::TabbedPane() 385 TabbedPane::TabbedPane()
399 : listener_(NULL), 386 : listener_(NULL),
400 tab_strip_(ui::MaterialDesignController::IsSecondaryUiMaterial() 387 tab_strip_(ui::MaterialDesignController::IsSecondaryUiMaterial()
401 ? new MdTabStrip(this) 388 ? new MdTabStrip
402 : new TabStrip(this)), 389 : new TabStrip),
403 contents_(new View()), 390 contents_(new View()) {
404 selected_tab_index_(-1) {
405 AddChildView(tab_strip_); 391 AddChildView(tab_strip_);
406 AddChildView(contents_); 392 AddChildView(contents_);
407 } 393 }
408 394
409 TabbedPane::~TabbedPane() {} 395 TabbedPane::~TabbedPane() {}
410 396
397 int TabbedPane::GetSelectedTabIndex() const {
398 return tab_strip_->GetSelectedTabIndex();
399 }
400
411 int TabbedPane::GetTabCount() { 401 int TabbedPane::GetTabCount() {
412 DCHECK_EQ(tab_strip_->child_count(), contents_->child_count()); 402 DCHECK_EQ(tab_strip_->child_count(), contents_->child_count());
413 return contents_->child_count(); 403 return contents_->child_count();
414 } 404 }
415 405
416 void TabbedPane::AddTab(const base::string16& title, View* contents) { 406 void TabbedPane::AddTab(const base::string16& title, View* contents) {
417 AddTabAtIndex(tab_strip_->child_count(), title, contents); 407 AddTabAtIndex(tab_strip_->child_count(), title, contents);
418 } 408 }
419 409
420 void TabbedPane::AddTabAtIndex(int index, 410 void TabbedPane::AddTabAtIndex(int index,
421 const base::string16& title, 411 const base::string16& title,
422 View* contents) { 412 View* contents) {
423 DCHECK(index >= 0 && index <= GetTabCount()); 413 DCHECK(index >= 0 && index <= GetTabCount());
424 contents->SetVisible(false); 414 contents->SetVisible(false);
425 415
426 tab_strip_->AddChildViewAt( 416 tab_strip_->AddChildViewAt(
427 ui::MaterialDesignController::IsSecondaryUiMaterial() 417 ui::MaterialDesignController::IsSecondaryUiMaterial()
428 ? new MdTab(this, title, contents) 418 ? new MdTab(this, title, contents)
429 : new Tab(this, title, contents), 419 : new Tab(this, title, contents),
430 index); 420 index);
431 contents_->AddChildViewAt(contents, index); 421 contents_->AddChildViewAt(contents, index);
432 // TODO(ellyjones): if index < selected_tab_index(), selected_tab_index() gets 422 if (!GetSelectedTab())
433 // out of sync with which tab believes it is selected. This class should
434 // directly ask Tabs whether they are selected.
435 if (selected_tab_index() < 0)
436 SelectTabAt(index); 423 SelectTabAt(index);
437 424
438 PreferredSizeChanged(); 425 PreferredSizeChanged();
439 } 426 }
440 427
441 void TabbedPane::SelectTabAt(int index) { 428 void TabbedPane::SelectTab(Tab* new_selected_tab) {
442 DCHECK(index >= 0 && index < GetTabCount()); 429 Tab* old_selected_tab = tab_strip_->GetSelectedTab();
443 if (index == selected_tab_index()) 430 if (old_selected_tab == new_selected_tab)
444 return; 431 return;
445 432
446 Tab* old_selected_tab = GetSelectedTab();
447 Tab* new_selected_tab = GetTabAt(index);
448 new_selected_tab->SetSelected(true); 433 new_selected_tab->SetSelected(true);
449 selected_tab_index_ = index;
450 if (old_selected_tab) { 434 if (old_selected_tab) {
451 if (old_selected_tab->HasFocus()) 435 if (old_selected_tab->HasFocus())
452 new_selected_tab->RequestFocus(); 436 new_selected_tab->RequestFocus();
453 old_selected_tab->SetSelected(false); 437 old_selected_tab->SetSelected(false);
454 } 438 }
455 tab_strip_->SchedulePaint(); 439 tab_strip_->SchedulePaint();
456 440
457 FocusManager* focus_manager = new_selected_tab->contents()->GetFocusManager(); 441 FocusManager* focus_manager = new_selected_tab->contents()->GetFocusManager();
458 if (focus_manager) { 442 if (focus_manager) {
459 const View* focused_view = focus_manager->GetFocusedView(); 443 const View* focused_view = focus_manager->GetFocusedView();
460 if (focused_view && contents_->Contains(focused_view) && 444 if (focused_view && contents_->Contains(focused_view) &&
461 !new_selected_tab->contents()->Contains(focused_view)) 445 !new_selected_tab->contents()->Contains(focused_view))
462 focus_manager->SetFocusedView(new_selected_tab->contents()); 446 focus_manager->SetFocusedView(new_selected_tab->contents());
463 } 447 }
464 448
465 if (listener()) 449 if (listener())
466 listener()->TabSelectedAt(index); 450 listener()->TabSelectedAt(tab_strip_->GetIndexOf(new_selected_tab));
467 } 451 }
468 452
469 void TabbedPane::SelectTab(Tab* tab) { 453 void TabbedPane::SelectTabAt(int index) {
470 const int index = tab_strip_->GetIndexOf(tab); 454 Tab* tab = tab_strip_->GetTabAtIndex(index);
471 if (index >= 0) 455 if (tab)
472 SelectTabAt(index); 456 SelectTab(tab);
473 } 457 }
474 458
475 gfx::Size TabbedPane::GetPreferredSize() const { 459 gfx::Size TabbedPane::GetPreferredSize() const {
476 gfx::Size size; 460 gfx::Size size;
477 for (int i = 0; i < contents_->child_count(); ++i) 461 for (int i = 0; i < contents_->child_count(); ++i)
478 size.SetToMax(contents_->child_at(i)->GetPreferredSize()); 462 size.SetToMax(contents_->child_at(i)->GetPreferredSize());
479 size.Enlarge(0, tab_strip_->GetPreferredSize().height()); 463 size.Enlarge(0, tab_strip_->GetPreferredSize().height());
480 return size; 464 return size;
481 } 465 }
482 466
483 Tab* TabbedPane::GetTabAt(int index) {
484 return static_cast<Tab*>(tab_strip_->child_at(index));
485 }
486
487 Tab* TabbedPane::GetSelectedTab() { 467 Tab* TabbedPane::GetSelectedTab() {
488 return selected_tab_index() >= 0 ? GetTabAt(selected_tab_index()) : nullptr; 468 return tab_strip_->GetSelectedTab();
489 } 469 }
490 470
491 bool TabbedPane::MoveSelectionBy(int delta) { 471 bool TabbedPane::MoveSelectionBy(int delta) {
492 const int tab_count = GetTabCount(); 472 if (contents_->child_count() <= 1)
493 if (tab_count <= 1)
494 return false; 473 return false;
495 int next_selected_index = (selected_tab_index() + delta) % tab_count; 474 SelectTab(tab_strip_->GetTabAtDeltaFromSelected(delta));
msw 2016/10/12 20:18:35 nit: it might make sense to just keep this inlined
Elly Fong-Jones 2016/10/12 21:23:05 I de-inlined it so TabbedPane could stop dealing w
496 if (next_selected_index < 0)
497 next_selected_index += tab_count;
498 SelectTabAt(next_selected_index);
499 return true; 475 return true;
500 } 476 }
501 477
502 void TabbedPane::Layout() { 478 void TabbedPane::Layout() {
503 const gfx::Size size = tab_strip_->GetPreferredSize(); 479 const gfx::Size size = tab_strip_->GetPreferredSize();
504 tab_strip_->SetBounds(0, 0, width(), size.height()); 480 tab_strip_->SetBounds(0, 0, width(), size.height());
505 contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(), 481 contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(),
506 std::max(0, height() - size.height())); 482 std::max(0, height() - size.height()));
507 for (int i = 0; i < contents_->child_count(); ++i) 483 for (int i = 0; i < contents_->child_count(); ++i)
508 contents_->child_at(i)->SetSize(contents_->size()); 484 contents_->child_at(i)->SetSize(contents_->size());
(...skipping 21 matching lines...) Expand all
530 506
531 View* TabbedPane::GetSelectedTabContentView() { 507 View* TabbedPane::GetSelectedTabContentView() {
532 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr; 508 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr;
533 } 509 }
534 510
535 void TabbedPane::GetAccessibleState(ui::AXViewState* state) { 511 void TabbedPane::GetAccessibleState(ui::AXViewState* state) {
536 state->role = ui::AX_ROLE_TAB_LIST; 512 state->role = ui::AX_ROLE_TAB_LIST;
537 } 513 }
538 514
539 } // namespace views 515 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/tabbed_pane/tabbed_pane.h ('k') | ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698