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

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: nits for msw 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 16 matching lines...) Expand all
49 // A subclass of Tab that implements the Harmony visual styling. 50 // A subclass of Tab that implements the Harmony visual styling.
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:
60 gfx::Size GetPreferredSize() const override;
59 void OnPaintBorder(gfx::Canvas* canvas) override; 61 void OnPaintBorder(gfx::Canvas* canvas) override;
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 const int kTabVerticalPadding = 5;
120 const int kTabHorizontalPadding = 10;
121
122 SetBorder(Border::CreateEmptyBorder(
123 gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding)));
124 SetLayoutManager(new FillLayout);
125
118 SetState(TAB_INACTIVE); 126 SetState(TAB_INACTIVE);
119 AddChildView(title_); 127 AddChildView(title_);
120 } 128 }
121 129
122 Tab::~Tab() {} 130 Tab::~Tab() {}
123 131
124 void Tab::SetSelected(bool selected) { 132 void Tab::SetSelected(bool selected) {
125 contents_->SetVisible(selected); 133 contents_->SetVisible(selected);
126 SetState(selected ? TAB_ACTIVE : TAB_INACTIVE); 134 SetState(selected ? TAB_ACTIVE : TAB_INACTIVE);
127 #if defined(OS_MACOSX) 135 #if defined(OS_MACOSX)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 SetState(selected() ? TAB_ACTIVE : TAB_INACTIVE); 188 SetState(selected() ? TAB_ACTIVE : TAB_INACTIVE);
181 break; 189 break;
182 default: 190 default:
183 break; 191 break;
184 } 192 }
185 event->SetHandled(); 193 event->SetHandled();
186 } 194 }
187 195
188 gfx::Size Tab::GetPreferredSize() const { 196 gfx::Size Tab::GetPreferredSize() const {
189 gfx::Size size(preferred_title_size_); 197 gfx::Size size(preferred_title_size_);
190 size.Enlarge(21, 9); 198 size.Enlarge(GetInsets().width(), GetInsets().height());
191 const int kTabMinWidth = 54;
192 if (size.width() < kTabMinWidth)
193 size.set_width(kTabMinWidth);
194 return size; 199 return size;
195 } 200 }
196 201
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 { 202 const char* Tab::GetClassName() const {
205 return kViewClassName; 203 return kViewClassName;
206 } 204 }
207 205
208 void Tab::SetState(TabState tab_state) { 206 void Tab::SetState(TabState tab_state) {
209 if (tab_state == tab_state_) 207 if (tab_state == tab_state_)
210 return; 208 return;
211 tab_state_ = tab_state; 209 tab_state_ = tab_state;
212 OnStateChanged(); 210 OnStateChanged();
213 SchedulePaint(); 211 SchedulePaint();
214 } 212 }
215 213
216 bool Tab::ContainerHasFocus() {
217 return tabbed_pane_->HasFocus();
218 }
219
220 void Tab::OnFocus() { 214 void Tab::OnFocus() {
221 OnStateChanged(); 215 OnStateChanged();
222 // When the tab gains focus, send an accessibility event indicating that the 216 // 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 217 // 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 218 // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to
225 // send one in OnBlur(). 219 // send one in OnBlur().
226 if (contents()) 220 if (contents())
227 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); 221 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
228 SchedulePaint(); 222 SchedulePaint();
229 } 223 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 289
296 // Draw the lighter-colored stroke first, then draw the heavier stroke over 290 // 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 291 // the bottom of it. This is fine because the heavier stroke has 1.0 alpha, so
298 // the lighter stroke won't show through. 292 // the lighter stroke won't show through.
299 canvas->DrawRect(bounds, paint); 293 canvas->DrawRect(bounds, paint);
300 canvas->FillRect( 294 canvas->FillRect(
301 gfx::Rect(0, height() - kBorderStrokeWidth, width(), kBorderStrokeWidth), 295 gfx::Rect(0, height() - kBorderStrokeWidth, width(), kBorderStrokeWidth),
302 base_color); 296 base_color);
303 } 297 }
304 298
299 gfx::Size MdTab::GetPreferredSize() const {
300 return gfx::Size(Tab::GetPreferredSize().width(), kHarmonyTabStripTabHeight);
301 }
302
305 // static 303 // static
306 const char TabStrip::kViewClassName[] = "TabStrip"; 304 const char TabStrip::kViewClassName[] = "TabStrip";
307 305
308 TabStrip::TabStrip(TabbedPane* tabbed_pane) : tabbed_pane_(tabbed_pane) {} 306 TabStrip::TabStrip() {
307 const int kTabStripLeadingEdgePadding = 9;
308 BoxLayout* layout =
309 new BoxLayout(BoxLayout::kHorizontal, kTabStripLeadingEdgePadding, 0, 0);
310 layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
311 layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END);
312 layout->SetDefaultFlex(0);
313 SetLayoutManager(layout);
314 }
309 315
310 TabStrip::~TabStrip() {} 316 TabStrip::~TabStrip() {}
311 317
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 { 318 const char* TabStrip::GetClassName() const {
333 return kViewClassName; 319 return kViewClassName;
334 } 320 }
335 321
336 void TabStrip::OnPaint(gfx::Canvas* canvas) { 322 void TabStrip::OnPaintBorder(gfx::Canvas* canvas) {
337 OnPaintBackground(canvas);
338
339 // Draw the TabStrip border.
340 SkPaint paint; 323 SkPaint paint;
341 paint.setColor(kTabBorderColor); 324 paint.setColor(kTabBorderColor);
342 paint.setStrokeWidth(kTabBorderThickness); 325 paint.setStrokeWidth(kTabBorderThickness);
343 SkScalar line_y = SkIntToScalar(height()) - (kTabBorderThickness / 2); 326 SkScalar line_y = SkIntToScalar(height()) - (kTabBorderThickness / 2);
344 SkScalar line_end = SkIntToScalar(width()); 327 SkScalar line_end = SkIntToScalar(width());
345 int selected_tab_index = tabbed_pane_->selected_tab_index(); 328 int selected_tab_index = GetSelectedTabIndex();
346 if (selected_tab_index >= 0) { 329 if (selected_tab_index >= 0) {
347 Tab* selected_tab = tabbed_pane_->GetTabAt(selected_tab_index); 330 Tab* selected_tab = GetTabAtIndex(selected_tab_index);
348 SkPath path; 331 SkPath path;
349 SkScalar tab_height = 332 SkScalar tab_height =
350 SkIntToScalar(selected_tab->height()) - kTabBorderThickness; 333 SkIntToScalar(selected_tab->height()) - kTabBorderThickness;
351 SkScalar tab_width = 334 SkScalar tab_width =
352 SkIntToScalar(selected_tab->width()) - kTabBorderThickness; 335 SkIntToScalar(selected_tab->width()) - kTabBorderThickness;
353 SkScalar tab_start = SkIntToScalar(selected_tab->GetMirroredX()); 336 SkScalar tab_start = SkIntToScalar(selected_tab->GetMirroredX());
354 path.moveTo(0, line_y); 337 path.moveTo(0, line_y);
355 path.rLineTo(tab_start, 0); 338 path.rLineTo(tab_start, 0);
356 path.rLineTo(0, -tab_height); 339 path.rLineTo(0, -tab_height);
357 path.rLineTo(tab_width, 0); 340 path.rLineTo(tab_width, 0);
358 path.rLineTo(0, tab_height); 341 path.rLineTo(0, tab_height);
359 path.lineTo(line_end, line_y); 342 path.lineTo(line_end, line_y);
360 343
361 SkPaint paint; 344 SkPaint paint;
362 paint.setStyle(SkPaint::kStroke_Style); 345 paint.setStyle(SkPaint::kStroke_Style);
363 paint.setColor(kTabBorderColor); 346 paint.setColor(kTabBorderColor);
364 paint.setStrokeWidth(kTabBorderThickness); 347 paint.setStrokeWidth(kTabBorderThickness);
365 canvas->DrawPath(path, paint); 348 canvas->DrawPath(path, paint);
366 } else { 349 } else {
367 canvas->sk_canvas()->drawLine(0, line_y, line_end, line_y, paint); 350 canvas->sk_canvas()->drawLine(0, line_y, line_end, line_y, paint);
368 } 351 }
369 } 352 }
370 353
371 MdTabStrip::MdTabStrip(TabbedPane* tabbed_pane) : TabStrip(tabbed_pane) { 354 Tab* TabStrip::GetTabAtIndex(int index) const {
355 return static_cast<Tab*>(const_cast<View*>(child_at(index)));
356 }
357
358 int TabStrip::GetSelectedTabIndex() const {
359 for (int i = 0; i < child_count(); ++i)
360 if (GetTabAtIndex(i)->selected())
361 return i;
362 return -1;
363 }
364
365 Tab* TabStrip::GetSelectedTab() const {
366 int index = GetSelectedTabIndex();
367 return index >= 0 ? GetTabAtIndex(index) : nullptr;
368 }
369
370 Tab* TabStrip::GetTabAtDeltaFromSelected(int delta) const {
371 int index = (GetSelectedTabIndex() + delta) % child_count();
372 if (index < 0)
373 index += child_count();
374 return GetTabAtIndex(index);
375 }
376
377 MdTabStrip::MdTabStrip() {
372 BoxLayout* layout = 378 BoxLayout* layout =
373 new BoxLayout(BoxLayout::kHorizontal, 0, kHarmonyTabStripVerticalPad, 0); 379 new BoxLayout(BoxLayout::kHorizontal, 0, kHarmonyTabStripVerticalPad, 0);
374 layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); 380 layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
375 layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); 381 layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
376 layout->SetDefaultFlex(1); 382 layout->SetDefaultFlex(1);
377 SetLayoutManager(layout); 383 SetLayoutManager(layout);
378 } 384 }
379 385
380 MdTabStrip::~MdTabStrip() {} 386 MdTabStrip::~MdTabStrip() {}
381 387
382 gfx::Size MdTabStrip::GetPreferredSize() const { 388 // The tab strip "border" is drawn as part of the tabs.
383 return gfx::Size(width(), 389 void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) {}
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 390
398 TabbedPane::TabbedPane() 391 TabbedPane::TabbedPane()
399 : listener_(NULL), 392 : listener_(NULL),
400 tab_strip_(ui::MaterialDesignController::IsSecondaryUiMaterial() 393 tab_strip_(ui::MaterialDesignController::IsSecondaryUiMaterial()
401 ? new MdTabStrip(this) 394 ? new MdTabStrip
402 : new TabStrip(this)), 395 : new TabStrip),
403 contents_(new View()), 396 contents_(new View()) {
404 selected_tab_index_(-1) {
405 AddChildView(tab_strip_); 397 AddChildView(tab_strip_);
406 AddChildView(contents_); 398 AddChildView(contents_);
407 } 399 }
408 400
409 TabbedPane::~TabbedPane() {} 401 TabbedPane::~TabbedPane() {}
410 402
403 int TabbedPane::GetSelectedTabIndex() const {
404 return tab_strip_->GetSelectedTabIndex();
405 }
406
411 int TabbedPane::GetTabCount() { 407 int TabbedPane::GetTabCount() {
412 DCHECK_EQ(tab_strip_->child_count(), contents_->child_count()); 408 DCHECK_EQ(tab_strip_->child_count(), contents_->child_count());
413 return contents_->child_count(); 409 return contents_->child_count();
414 } 410 }
415 411
416 void TabbedPane::AddTab(const base::string16& title, View* contents) { 412 void TabbedPane::AddTab(const base::string16& title, View* contents) {
417 AddTabAtIndex(tab_strip_->child_count(), title, contents); 413 AddTabAtIndex(tab_strip_->child_count(), title, contents);
418 } 414 }
419 415
420 void TabbedPane::AddTabAtIndex(int index, 416 void TabbedPane::AddTabAtIndex(int index,
421 const base::string16& title, 417 const base::string16& title,
422 View* contents) { 418 View* contents) {
423 DCHECK(index >= 0 && index <= GetTabCount()); 419 DCHECK(index >= 0 && index <= GetTabCount());
424 contents->SetVisible(false); 420 contents->SetVisible(false);
425 421
426 tab_strip_->AddChildViewAt( 422 tab_strip_->AddChildViewAt(
427 ui::MaterialDesignController::IsSecondaryUiMaterial() 423 ui::MaterialDesignController::IsSecondaryUiMaterial()
428 ? new MdTab(this, title, contents) 424 ? new MdTab(this, title, contents)
429 : new Tab(this, title, contents), 425 : new Tab(this, title, contents),
430 index); 426 index);
431 contents_->AddChildViewAt(contents, index); 427 contents_->AddChildViewAt(contents, index);
432 // TODO(ellyjones): if index < selected_tab_index(), selected_tab_index() gets 428 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); 429 SelectTabAt(index);
437 430
438 PreferredSizeChanged(); 431 PreferredSizeChanged();
439 } 432 }
440 433
441 void TabbedPane::SelectTabAt(int index) { 434 void TabbedPane::SelectTab(Tab* new_selected_tab) {
442 DCHECK(index >= 0 && index < GetTabCount()); 435 Tab* old_selected_tab = tab_strip_->GetSelectedTab();
443 if (index == selected_tab_index()) 436 if (old_selected_tab == new_selected_tab)
444 return; 437 return;
445 438
446 Tab* old_selected_tab = GetSelectedTab();
447 Tab* new_selected_tab = GetTabAt(index);
448 new_selected_tab->SetSelected(true); 439 new_selected_tab->SetSelected(true);
449 selected_tab_index_ = index;
450 if (old_selected_tab) { 440 if (old_selected_tab) {
451 if (old_selected_tab->HasFocus()) 441 if (old_selected_tab->HasFocus())
452 new_selected_tab->RequestFocus(); 442 new_selected_tab->RequestFocus();
453 old_selected_tab->SetSelected(false); 443 old_selected_tab->SetSelected(false);
454 } 444 }
455 tab_strip_->SchedulePaint(); 445 tab_strip_->SchedulePaint();
456 446
457 FocusManager* focus_manager = new_selected_tab->contents()->GetFocusManager(); 447 FocusManager* focus_manager = new_selected_tab->contents()->GetFocusManager();
458 if (focus_manager) { 448 if (focus_manager) {
459 const View* focused_view = focus_manager->GetFocusedView(); 449 const View* focused_view = focus_manager->GetFocusedView();
460 if (focused_view && contents_->Contains(focused_view) && 450 if (focused_view && contents_->Contains(focused_view) &&
461 !new_selected_tab->contents()->Contains(focused_view)) 451 !new_selected_tab->contents()->Contains(focused_view))
462 focus_manager->SetFocusedView(new_selected_tab->contents()); 452 focus_manager->SetFocusedView(new_selected_tab->contents());
463 } 453 }
464 454
465 if (listener()) 455 if (listener())
466 listener()->TabSelectedAt(index); 456 listener()->TabSelectedAt(tab_strip_->GetIndexOf(new_selected_tab));
467 } 457 }
468 458
469 void TabbedPane::SelectTab(Tab* tab) { 459 void TabbedPane::SelectTabAt(int index) {
470 const int index = tab_strip_->GetIndexOf(tab); 460 Tab* tab = tab_strip_->GetTabAtIndex(index);
471 if (index >= 0) 461 if (tab)
472 SelectTabAt(index); 462 SelectTab(tab);
473 } 463 }
474 464
475 gfx::Size TabbedPane::GetPreferredSize() const { 465 gfx::Size TabbedPane::GetPreferredSize() const {
476 gfx::Size size; 466 gfx::Size size;
477 for (int i = 0; i < contents_->child_count(); ++i) 467 for (int i = 0; i < contents_->child_count(); ++i)
478 size.SetToMax(contents_->child_at(i)->GetPreferredSize()); 468 size.SetToMax(contents_->child_at(i)->GetPreferredSize());
479 size.Enlarge(0, tab_strip_->GetPreferredSize().height()); 469 size.Enlarge(0, tab_strip_->GetPreferredSize().height());
480 return size; 470 return size;
481 } 471 }
482 472
483 Tab* TabbedPane::GetTabAt(int index) {
484 return static_cast<Tab*>(tab_strip_->child_at(index));
485 }
486
487 Tab* TabbedPane::GetSelectedTab() { 473 Tab* TabbedPane::GetSelectedTab() {
488 return selected_tab_index() >= 0 ? GetTabAt(selected_tab_index()) : nullptr; 474 return tab_strip_->GetSelectedTab();
489 } 475 }
490 476
491 bool TabbedPane::MoveSelectionBy(int delta) { 477 bool TabbedPane::MoveSelectionBy(int delta) {
492 const int tab_count = GetTabCount(); 478 if (contents_->child_count() <= 1)
493 if (tab_count <= 1)
494 return false; 479 return false;
495 int next_selected_index = (selected_tab_index() + delta) % tab_count; 480 SelectTab(tab_strip_->GetTabAtDeltaFromSelected(delta));
496 if (next_selected_index < 0)
497 next_selected_index += tab_count;
498 SelectTabAt(next_selected_index);
499 return true; 481 return true;
500 } 482 }
501 483
502 void TabbedPane::Layout() { 484 void TabbedPane::Layout() {
503 const gfx::Size size = tab_strip_->GetPreferredSize(); 485 const gfx::Size size = tab_strip_->GetPreferredSize();
504 tab_strip_->SetBounds(0, 0, width(), size.height()); 486 tab_strip_->SetBounds(0, 0, width(), size.height());
505 contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(), 487 contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(),
506 std::max(0, height() - size.height())); 488 std::max(0, height() - size.height()));
507 for (int i = 0; i < contents_->child_count(); ++i) 489 for (int i = 0; i < contents_->child_count(); ++i)
508 contents_->child_at(i)->SetSize(contents_->size()); 490 contents_->child_at(i)->SetSize(contents_->size());
(...skipping 21 matching lines...) Expand all
530 512
531 View* TabbedPane::GetSelectedTabContentView() { 513 View* TabbedPane::GetSelectedTabContentView() {
532 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr; 514 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr;
533 } 515 }
534 516
535 void TabbedPane::GetAccessibleState(ui::AXViewState* state) { 517 void TabbedPane::GetAccessibleState(ui::AXViewState* state) {
536 state->role = ui::AX_ROLE_TAB_LIST; 518 state->role = ui::AX_ROLE_TAB_LIST;
537 } 519 }
538 520
539 } // namespace views 521 } // 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