Chromium Code Reviews| 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 "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_action_data.h" | |
| 11 #include "ui/accessibility/ax_node_data.h" | 12 #include "ui/accessibility/ax_node_data.h" |
| 12 #include "ui/base/default_style.h" | 13 #include "ui/base/default_style.h" |
| 13 #include "ui/base/material_design/material_design_controller.h" | 14 #include "ui/base/material_design/material_design_controller.h" |
| 14 #include "ui/base/resource/resource_bundle.h" | 15 #include "ui/base/resource/resource_bundle.h" |
| 15 #include "ui/events/keycodes/keyboard_codes.h" | 16 #include "ui/events/keycodes/keyboard_codes.h" |
| 16 #include "ui/gfx/animation/animation_delegate.h" | 17 #include "ui/gfx/animation/animation_delegate.h" |
| 17 #include "ui/gfx/animation/linear_animation.h" | 18 #include "ui/gfx/animation/linear_animation.h" |
| 18 #include "ui/gfx/animation/tween.h" | 19 #include "ui/gfx/animation/tween.h" |
| 19 #include "ui/gfx/canvas.h" | 20 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/font_list.h" | 21 #include "ui/gfx/font_list.h" |
| 21 #include "ui/native_theme/native_theme.h" | 22 #include "ui/native_theme/native_theme.h" |
| 22 #include "ui/views/border.h" | 23 #include "ui/views/border.h" |
| 23 #include "ui/views/controls/label.h" | 24 #include "ui/views/controls/label.h" |
| 24 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h" | 25 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h" |
| 25 #include "ui/views/layout/box_layout.h" | 26 #include "ui/views/layout/box_layout.h" |
| 26 #include "ui/views/layout/fill_layout.h" | 27 #include "ui/views/layout/fill_layout.h" |
| 27 #include "ui/views/layout/layout_manager.h" | 28 #include "ui/views/layout/layout_manager.h" |
| 28 #include "ui/views/widget/widget.h" | 29 #include "ui/views/widget/widget.h" |
| 29 | 30 |
| 31 namespace views { | |
| 32 | |
| 30 namespace { | 33 namespace { |
| 31 | 34 |
| 32 // TODO(markusheintz|msw): Use NativeTheme colors. | 35 // TODO(markusheintz|msw): Use NativeTheme colors. |
| 33 const SkColor kTabTitleColor_Inactive = SkColorSetRGB(0x64, 0x64, 0x64); | 36 const SkColor kTabTitleColor_Inactive = SkColorSetRGB(0x64, 0x64, 0x64); |
| 34 const SkColor kTabTitleColor_Active = SK_ColorBLACK; | 37 const SkColor kTabTitleColor_Active = SK_ColorBLACK; |
| 35 const SkColor kTabTitleColor_Hovered = SK_ColorBLACK; | 38 const SkColor kTabTitleColor_Hovered = SK_ColorBLACK; |
| 36 const SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8); | 39 const SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8); |
| 37 const SkScalar kTabBorderThickness = 1.0f; | 40 const SkScalar kTabBorderThickness = 1.0f; |
| 38 | 41 |
| 39 const gfx::Font::Weight kHoverWeight = gfx::Font::Weight::NORMAL; | 42 const gfx::Font::Weight kHoverWeight = gfx::Font::Weight::NORMAL; |
| 40 const gfx::Font::Weight kActiveWeight = gfx::Font::Weight::BOLD; | 43 const gfx::Font::Weight kActiveWeight = gfx::Font::Weight::BOLD; |
| 41 const gfx::Font::Weight kInactiveWeight = gfx::Font::Weight::NORMAL; | 44 const gfx::Font::Weight kInactiveWeight = gfx::Font::Weight::NORMAL; |
| 42 | 45 |
| 43 const int kHarmonyTabStripTabHeight = 40; | 46 const int kHarmonyTabStripTabHeight = 40; |
| 44 | 47 |
| 48 // views::Tab shouldn't expose any of its children in the a11y tree. Instead, it | |
|
tapted
2017/01/03 00:29:27
nit: move comment into GetAccessibleNodeData. the
Patti Lor
2017/01/06 02:02:29
Done.
| |
| 49 // should provide the a11y information itself. Normally, non-keyboard-focusable | |
| 50 // children of keyboard-focusable parents are ignored, but Tabs only mark the | |
| 51 // currently selected tab as keyboard-focusable. This means all unselected Tabs | |
| 52 // expose their children to the a11y tree. To fix, manually ignore the children. | |
| 53 class TabLabel : public Label { | |
| 54 public: | |
| 55 TabLabel(const base::string16& tab_title) | |
|
tapted
2017/01/03 00:29:27
nit; explicit
Patti Lor
2017/01/06 02:02:29
Done.
| |
| 56 : Label(tab_title, | |
| 57 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( | |
| 58 ui::kLabelFontSizeDelta, | |
| 59 gfx::Font::NORMAL, | |
| 60 kActiveWeight)) {} | |
| 61 | |
| 62 void GetAccessibleNodeData(ui::AXNodeData* data) override { | |
|
tapted
2017/01/03 00:29:27
nit: // Label:
Patti Lor
2017/01/06 02:02:30
Done.
| |
| 63 data->role = ui::AX_ROLE_IGNORED; | |
| 64 } | |
| 65 }; | |
| 66 | |
| 45 } // namespace | 67 } // namespace |
| 46 | 68 |
| 47 namespace views { | |
| 48 | |
| 49 // static | 69 // static |
| 50 const char TabbedPane::kViewClassName[] = "TabbedPane"; | 70 const char TabbedPane::kViewClassName[] = "TabbedPane"; |
| 51 | 71 |
| 52 // A subclass of Tab that implements the Harmony visual styling. | 72 // A subclass of Tab that implements the Harmony visual styling. |
| 53 class MdTab : public Tab { | 73 class MdTab : public Tab { |
| 54 public: | 74 public: |
| 55 MdTab(TabbedPane* tabbed_pane, const base::string16& title, View* contents); | 75 MdTab(TabbedPane* tabbed_pane, const base::string16& title, View* contents); |
| 56 ~MdTab() override; | 76 ~MdTab() override; |
| 57 | 77 |
| 58 // Overridden from Tab: | 78 // Overridden from Tab: |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 125 gfx::Range animating_to_; | 145 gfx::Range animating_to_; |
| 126 | 146 |
| 127 DISALLOW_COPY_AND_ASSIGN(MdTabStrip); | 147 DISALLOW_COPY_AND_ASSIGN(MdTabStrip); |
| 128 }; | 148 }; |
| 129 | 149 |
| 130 // static | 150 // static |
| 131 const char Tab::kViewClassName[] = "Tab"; | 151 const char Tab::kViewClassName[] = "Tab"; |
| 132 | 152 |
| 133 Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents) | 153 Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents) |
| 134 : tabbed_pane_(tabbed_pane), | 154 : tabbed_pane_(tabbed_pane), |
| 135 title_(new Label( | 155 title_(new TabLabel(title)), |
| 136 title, | |
| 137 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( | |
| 138 ui::kLabelFontSizeDelta, | |
| 139 gfx::Font::NORMAL, | |
| 140 kActiveWeight))), | |
| 141 tab_state_(TAB_ACTIVE), | 156 tab_state_(TAB_ACTIVE), |
| 142 contents_(contents) { | 157 contents_(contents) { |
| 143 // Calculate this now while the font list is guaranteed to be bold. | 158 // Calculate this now while the font list is guaranteed to be bold. |
| 144 preferred_title_size_ = title_->GetPreferredSize(); | 159 preferred_title_size_ = title_->GetPreferredSize(); |
| 145 | 160 |
| 146 const int kTabVerticalPadding = 5; | 161 const int kTabVerticalPadding = 5; |
| 147 const int kTabHorizontalPadding = 10; | 162 const int kTabHorizontalPadding = 10; |
| 148 | 163 |
| 149 SetBorder(CreateEmptyBorder( | 164 SetBorder(CreateEmptyBorder( |
| 150 gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding))); | 165 gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding))); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 } | 246 } |
| 232 | 247 |
| 233 void Tab::SetState(TabState tab_state) { | 248 void Tab::SetState(TabState tab_state) { |
| 234 if (tab_state == tab_state_) | 249 if (tab_state == tab_state_) |
| 235 return; | 250 return; |
| 236 tab_state_ = tab_state; | 251 tab_state_ = tab_state; |
| 237 OnStateChanged(); | 252 OnStateChanged(); |
| 238 SchedulePaint(); | 253 SchedulePaint(); |
| 239 } | 254 } |
| 240 | 255 |
| 256 void Tab::GetAccessibleNodeData(ui::AXNodeData* data) { | |
| 257 data->role = ui::AX_ROLE_TAB; | |
| 258 data->SetName(title()->text()); | |
| 259 data->AddStateFlag(ui::AX_STATE_SELECTABLE); | |
| 260 if (selected()) | |
| 261 data->AddStateFlag(ui::AX_STATE_SELECTED); | |
| 262 } | |
| 263 | |
| 264 bool Tab::HandleAccessibleAction(const ui::AXActionData& action_data) { | |
| 265 if (action_data.action != ui::AX_ACTION_SET_SELECTION || !enabled()) | |
| 266 return false; | |
| 267 // It's not clear what should happen if a tab is 'deselected', so having the | |
| 268 // AX_ACTION_SET_SELECTION action always selects the tab. | |
| 269 if (!selected()) | |
|
tapted
2017/01/03 00:29:27
Can we just ignore requests to SET_SELECTION to 0/
Patti Lor
2017/01/06 02:02:30
Yep - so on Mac, I've done this by reporting selec
| |
| 270 tabbed_pane_->SelectTab(this); | |
| 271 return true; | |
| 272 } | |
| 273 | |
| 241 void Tab::OnFocus() { | 274 void Tab::OnFocus() { |
| 242 OnStateChanged(); | 275 OnStateChanged(); |
| 243 // When the tab gains focus, send an accessibility event indicating that the | 276 // When the tab gains focus, send an accessibility event indicating that the |
| 244 // contents are focused. When the tab loses focus, whichever new View ends up | 277 // contents are focused. When the tab loses focus, whichever new View ends up |
| 245 // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to | 278 // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to |
| 246 // send one in OnBlur(). | 279 // send one in OnBlur(). |
| 247 if (contents()) | 280 if (contents()) |
| 248 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); | 281 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); |
| 249 SchedulePaint(); | 282 SchedulePaint(); |
| 250 } | 283 } |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 | 652 |
| 620 View* TabbedPane::GetSelectedTabContentView() { | 653 View* TabbedPane::GetSelectedTabContentView() { |
| 621 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr; | 654 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr; |
| 622 } | 655 } |
| 623 | 656 |
| 624 void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) { | 657 void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) { |
| 625 node_data->role = ui::AX_ROLE_TAB_LIST; | 658 node_data->role = ui::AX_ROLE_TAB_LIST; |
| 626 } | 659 } |
| 627 | 660 |
| 628 } // namespace views | 661 } // namespace views |
| OLD | NEW |