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

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

Issue 2578303003: a11y: Add a11y information to views::Tab and manually ignore its a11y children. (Closed)
Patch Set: Review comments. Created 3 years, 11 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_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 // The View containing the text for each tab in the tab strip.
49 class TabLabel : public Label {
50 public:
51 explicit TabLabel(const base::string16& tab_title)
52 : Label(tab_title,
53 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta(
54 ui::kLabelFontSizeDelta,
55 gfx::Font::NORMAL,
56 kActiveWeight)) {}
57
58 // Label:
59 void GetAccessibleNodeData(ui::AXNodeData* data) override {
60 // views::Tab shouldn't expose any of its children in the a11y tree.
61 // Instead, it should provide the a11y information itself. Normally,
62 // non-keyboard-focusable children of keyboard-focusable parents are
63 // ignored, but Tabs only mark the currently selected tab as
64 // keyboard-focusable. This means all unselected Tabs expose their children
65 // to the a11y tree. To fix, manually ignore the children.
66 data->role = ui::AX_ROLE_IGNORED;
67 }
68 };
69
45 } // namespace 70 } // namespace
46 71
47 namespace views {
48
49 // static 72 // static
50 const char TabbedPane::kViewClassName[] = "TabbedPane"; 73 const char TabbedPane::kViewClassName[] = "TabbedPane";
51 74
52 // A subclass of Tab that implements the Harmony visual styling. 75 // A subclass of Tab that implements the Harmony visual styling.
53 class MdTab : public Tab { 76 class MdTab : public Tab {
54 public: 77 public:
55 MdTab(TabbedPane* tabbed_pane, const base::string16& title, View* contents); 78 MdTab(TabbedPane* tabbed_pane, const base::string16& title, View* contents);
56 ~MdTab() override; 79 ~MdTab() override;
57 80
58 // Overridden from Tab: 81 // Overridden from Tab:
59 void OnStateChanged() override; 82 void OnStateChanged() override;
60 83
61 // Overridden from View: 84 // Overridden from View:
62 gfx::Size GetPreferredSize() const override; 85 gfx::Size GetPreferredSize() const override;
63 void OnFocus() override; 86 void OnFocus() override;
64 void OnBlur() override; 87 void OnBlur() override;
65 88
66 private: 89 private:
67 DISALLOW_COPY_AND_ASSIGN(MdTab); 90 DISALLOW_COPY_AND_ASSIGN(MdTab);
68 }; 91 };
69 92
70 // The tab strip shown above the tab contents.
71 class TabStrip : public View {
72 public:
73 // Internal class name.
74 static const char kViewClassName[];
75
76 TabStrip();
77 ~TabStrip() override;
78
79 // Called by TabStrip when the selected tab changes. This function is only
80 // called if |from_tab| is not null, i.e., there was a previously selected
81 // tab.
82 virtual void OnSelectedTabChanged(Tab* from_tab, Tab* to_tab);
83
84 // Overridden from View:
85 const char* GetClassName() const override;
86 void OnPaintBorder(gfx::Canvas* canvas) override;
87
88 Tab* GetSelectedTab() const;
89 Tab* GetTabAtDeltaFromSelected(int delta) const;
90 Tab* GetTabAtIndex(int index) const;
91 int GetSelectedTabIndex() const;
92
93 private:
94 DISALLOW_COPY_AND_ASSIGN(TabStrip);
95 };
96
97 // A subclass of TabStrip that implements the Harmony visual styling. This 93 // A subclass of TabStrip that implements the Harmony visual styling. This
98 // class uses a BoxLayout to position tabs. 94 // class uses a BoxLayout to position tabs.
99 class MdTabStrip : public TabStrip, public gfx::AnimationDelegate { 95 class MdTabStrip : public TabStrip, public gfx::AnimationDelegate {
100 public: 96 public:
101 MdTabStrip(); 97 MdTabStrip();
102 ~MdTabStrip() override; 98 ~MdTabStrip() override;
103 99
104 // Overridden from TabStrip: 100 // Overridden from TabStrip:
105 void OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) override; 101 void OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) override;
106 102
(...skipping 18 matching lines...) Expand all
125 gfx::Range animating_to_; 121 gfx::Range animating_to_;
126 122
127 DISALLOW_COPY_AND_ASSIGN(MdTabStrip); 123 DISALLOW_COPY_AND_ASSIGN(MdTabStrip);
128 }; 124 };
129 125
130 // static 126 // static
131 const char Tab::kViewClassName[] = "Tab"; 127 const char Tab::kViewClassName[] = "Tab";
132 128
133 Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents) 129 Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
134 : tabbed_pane_(tabbed_pane), 130 : tabbed_pane_(tabbed_pane),
135 title_(new Label( 131 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), 132 tab_state_(TAB_ACTIVE),
142 contents_(contents) { 133 contents_(contents) {
143 // Calculate this now while the font list is guaranteed to be bold. 134 // Calculate this now while the font list is guaranteed to be bold.
144 preferred_title_size_ = title_->GetPreferredSize(); 135 preferred_title_size_ = title_->GetPreferredSize();
145 136
146 const int kTabVerticalPadding = 5; 137 const int kTabVerticalPadding = 5;
147 const int kTabHorizontalPadding = 10; 138 const int kTabHorizontalPadding = 10;
148 139
149 SetBorder(CreateEmptyBorder( 140 SetBorder(CreateEmptyBorder(
150 gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding))); 141 gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding)));
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 } 222 }
232 223
233 void Tab::SetState(TabState tab_state) { 224 void Tab::SetState(TabState tab_state) {
234 if (tab_state == tab_state_) 225 if (tab_state == tab_state_)
235 return; 226 return;
236 tab_state_ = tab_state; 227 tab_state_ = tab_state;
237 OnStateChanged(); 228 OnStateChanged();
238 SchedulePaint(); 229 SchedulePaint();
239 } 230 }
240 231
232 void Tab::GetAccessibleNodeData(ui::AXNodeData* data) {
233 data->role = ui::AX_ROLE_TAB;
234 data->SetName(title()->text());
235 data->AddStateFlag(ui::AX_STATE_SELECTABLE);
236 if (selected())
237 data->AddStateFlag(ui::AX_STATE_SELECTED);
238 }
239
240 bool Tab::HandleAccessibleAction(const ui::AXActionData& action_data) {
241 if (action_data.action != ui::AX_ACTION_SET_SELECTION || !enabled())
242 return false;
243 // It's not clear what should happen if a tab is 'deselected', so having the
tapted 2017/01/10 16:22:18 nit: blank line before, delete "having"
Patti Lor 2017/01/11 05:51:44 Done.
244 // AX_ACTION_SET_SELECTION action always selects the tab.
tapted 2017/01/10 16:22:19 nit: selects -> select
Patti Lor 2017/01/11 05:51:44 Done.
245 tabbed_pane_->SelectTab(this);
246 return true;
247 }
248
241 void Tab::OnFocus() { 249 void Tab::OnFocus() {
242 OnStateChanged(); 250 OnStateChanged();
243 // When the tab gains focus, send an accessibility event indicating that the 251 // 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 252 // 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 253 // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to
246 // send one in OnBlur(). 254 // send one in OnBlur().
247 if (contents()) 255 if (contents())
248 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); 256 contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
249 SchedulePaint(); 257 SchedulePaint();
250 } 258 }
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 627
620 View* TabbedPane::GetSelectedTabContentView() { 628 View* TabbedPane::GetSelectedTabContentView() {
621 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr; 629 return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr;
622 } 630 }
623 631
624 void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) { 632 void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) {
625 node_data->role = ui::AX_ROLE_TAB_LIST; 633 node_data->role = ui::AX_ROLE_TAB_LIST;
626 } 634 }
627 635
628 } // namespace views 636 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698