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

Unified Diff: ui/views/controls/tabbed_pane/tabbed_pane.cc

Issue 2368283002: views: add focus to TabbedPane (Closed)
Patch Set: rename some stuff, move Tab class 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/tabbed_pane/tabbed_pane.cc
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 07fe5a69545640c34d3bab5c1b58bf003a80811b..1e9de95666dcbb2bd70393cceeebd89263f55b71 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -46,54 +46,6 @@ namespace views {
// static
const char TabbedPane::kViewClassName[] = "TabbedPane";
-// The tab view shown in the tab strip.
-class Tab : public View {
- public:
- // Internal class name.
- static const char kViewClassName[];
-
- Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents);
- ~Tab() override;
-
- View* contents() const { return contents_; }
-
- bool selected() const { return contents_->visible(); }
- void SetSelected(bool selected);
-
- // Overridden from View:
- bool OnMousePressed(const ui::MouseEvent& event) override;
- void OnMouseEntered(const ui::MouseEvent& event) override;
- void OnMouseExited(const ui::MouseEvent& event) override;
- void OnGestureEvent(ui::GestureEvent* event) override;
- gfx::Size GetPreferredSize() const override;
- void Layout() override;
- const char* GetClassName() const override;
-
- protected:
- Label* title() { return title_; }
-
- // Called whenever |tab_state_| changes.
- virtual void OnStateChanged();
-
- private:
- enum TabState {
- TAB_INACTIVE,
- TAB_ACTIVE,
- TAB_HOVERED,
- };
-
- void SetState(TabState tab_state);
-
- TabbedPane* tabbed_pane_;
- Label* title_;
- gfx::Size preferred_title_size_;
- TabState tab_state_;
- // The content view associated with this tab.
- View* contents_;
-
- DISALLOW_COPY_AND_ASSIGN(Tab);
-};
-
// A subclass of Tab that implements the Harmony visual styling.
class MdTab : public Tab {
public:
@@ -103,6 +55,9 @@ class MdTab : public Tab {
// Overridden from Tab:
void OnStateChanged() override;
+ // Overridden from View:
+ void OnPaintBorder(gfx::Canvas* canvas) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(MdTab);
};
@@ -169,6 +124,12 @@ Tab::~Tab() {}
void Tab::SetSelected(bool selected) {
contents_->SetVisible(selected);
SetState(selected ? TAB_ACTIVE : TAB_INACTIVE);
+#if defined(OS_MACOSX)
+ SetFocusBehavior(selected ? FocusBehavior::ACCESSIBLE_ONLY
+ : FocusBehavior::NEVER);
+#else
+ SetFocusBehavior(selected ? FocusBehavior::ALWAYS : FocusBehavior::NEVER);
+#endif
}
void Tab::OnStateChanged() {
@@ -252,6 +213,33 @@ void Tab::SetState(TabState tab_state) {
SchedulePaint();
}
+bool Tab::ContainerHasFocus() {
+ return tabbed_pane_->HasFocus();
+}
+
+void Tab::OnFocus() {
+ OnStateChanged();
+ // When the tab gains focus, send an accessibility event indicating that the
+ // contents are focused. When the tab loses focus, whichever new View ends up
+ // with focus will send an AX_EVENT_FOCUS of its own, so there's no need to
+ // send one in OnBlur().
+ if (contents())
+ contents()->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
+ SchedulePaint();
+}
+
+void Tab::OnBlur() {
+ OnStateChanged();
+ SchedulePaint();
+}
+
+bool Tab::OnKeyPressed(const ui::KeyEvent& event) {
+ ui::KeyboardCode key = event.key_code();
+ if (key != ui::VKEY_LEFT && key != ui::VKEY_RIGHT)
+ return false;
+ return tabbed_pane_->MoveSelectionBy(key == ui::VKEY_RIGHT ? 1 : -1);
+}
+
MdTab::MdTab(TabbedPane* tabbed_pane,
const base::string16& title,
View* contents)
@@ -263,12 +251,6 @@ MdTab::~MdTab() {}
void MdTab::OnStateChanged() {
ui::NativeTheme* theme = GetNativeTheme();
- SkColor border_color = theme->GetSystemColor(
- selected() ? ui::NativeTheme::kColorId_FocusedBorderColor
- : ui::NativeTheme::kColorId_UnfocusedBorderColor);
- int border_thickness = selected() ? 2 : 1;
- SetBorder(
- Border::CreateSolidSidedBorder(0, 0, border_thickness, 0, border_color));
SkColor font_color = selected()
? theme->GetSystemColor(ui::NativeTheme::kColorId_ProminentButtonColor)
@@ -286,6 +268,40 @@ void MdTab::OnStateChanged() {
gfx::Font::NORMAL, font_weight));
}
+void MdTab::OnPaintBorder(gfx::Canvas* canvas) {
+ const int kBorderStrokeWidth = 2;
+ if (!HasFocus()) {
+ SkColor color = GetNativeTheme()->GetSystemColor(
+ selected() ? ui::NativeTheme::kColorId_FocusedBorderColor
+ : ui::NativeTheme::kColorId_UnfocusedBorderColor);
+ int thickness = selected() ? kBorderStrokeWidth : kBorderStrokeWidth / 2;
+ canvas->FillRect(gfx::Rect(0, height() - thickness, width(), thickness),
+ color);
+ return;
+ }
+
+ // TODO(ellyjones): should this 0x66 be part of NativeTheme somehow?
+ SkColor base_color = GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor);
+ SkColor light_color = SkColorSetA(base_color, 0x66);
+
+ SkPaint paint;
+ paint.setColor(light_color);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(kBorderStrokeWidth);
+
+ gfx::RectF bounds = gfx::RectF(GetLocalBounds());
+ bounds.Inset(gfx::Insets(kBorderStrokeWidth / 2.f));
+
+ // Draw the lighter-colored stroke first, then draw the heavier stroke over
+ // the bottom of it. This is fine because the heavier stroke has 1.0 alpha, so
+ // the lighter stroke won't show through.
+ canvas->DrawRect(bounds, paint);
+ canvas->FillRect(
+ gfx::Rect(0, height() - kBorderStrokeWidth, width(), kBorderStrokeWidth),
+ base_color);
+}
+
// static
const char TabStrip::kViewClassName[] = "TabStrip";
@@ -386,12 +402,6 @@ TabbedPane::TabbedPane()
: new TabStrip(this)),
contents_(new View()),
selected_tab_index_(-1) {
-#if defined(OS_MACOSX)
- SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
-#else
- SetFocusBehavior(FocusBehavior::ALWAYS);
-#endif
-
AddChildView(tab_strip_);
AddChildView(contents_);
}
@@ -403,11 +413,6 @@ int TabbedPane::GetTabCount() {
return contents_->child_count();
}
-View* TabbedPane::GetSelectedTab() {
- return selected_tab_index() < 0 ?
- NULL : GetTabAt(selected_tab_index())->contents();
-}
-
void TabbedPane::AddTab(const base::string16& title, View* contents) {
AddTabAtIndex(tab_strip_->child_count(), title, contents);
}
@@ -424,6 +429,9 @@ void TabbedPane::AddTabAtIndex(int index,
: new Tab(this, title, contents),
index);
contents_->AddChildViewAt(contents, index);
+ // TODO(ellyjones): if index < selected_tab_index(), selected_tab_index() gets
+ // out of sync with which tab believes it is selected. This class should
+ // directly ask Tabs whether they are selected.
if (selected_tab_index() < 0)
SelectTabAt(index);
@@ -435,20 +443,23 @@ void TabbedPane::SelectTabAt(int index) {
if (index == selected_tab_index())
return;
- if (selected_tab_index() >= 0)
- GetTabAt(selected_tab_index())->SetSelected(false);
-
+ Tab* old_selected_tab = GetSelectedTab();
+ Tab* new_selected_tab = GetTabAt(index);
+ new_selected_tab->SetSelected(true);
selected_tab_index_ = index;
- Tab* tab = GetTabAt(index);
- tab->SetSelected(true);
+ if (old_selected_tab) {
+ if (old_selected_tab->HasFocus())
+ new_selected_tab->RequestFocus();
+ old_selected_tab->SetSelected(false);
+ }
tab_strip_->SchedulePaint();
- FocusManager* focus_manager = tab->contents()->GetFocusManager();
+ FocusManager* focus_manager = new_selected_tab->contents()->GetFocusManager();
if (focus_manager) {
const View* focused_view = focus_manager->GetFocusedView();
if (focused_view && contents_->Contains(focused_view) &&
- !tab->contents()->Contains(focused_view))
- focus_manager->SetFocusedView(tab->contents());
+ !new_selected_tab->contents()->Contains(focused_view))
+ focus_manager->SetFocusedView(new_selected_tab->contents());
}
if (listener())
@@ -473,6 +484,21 @@ Tab* TabbedPane::GetTabAt(int index) {
return static_cast<Tab*>(tab_strip_->child_at(index));
}
+Tab* TabbedPane::GetSelectedTab() {
+ return selected_tab_index() >= 0 ? GetTabAt(selected_tab_index()) : nullptr;
+}
+
+bool TabbedPane::MoveSelectionBy(int delta) {
+ const int tab_count = GetTabCount();
+ if (tab_count <= 1)
+ return false;
+ int next_selected_index = (selected_tab_index() + delta) % tab_count;
+ if (next_selected_index < 0)
+ next_selected_index += tab_count;
+ SelectTabAt(next_selected_index);
+ return true;
+}
+
void TabbedPane::Layout() {
const gfx::Size size = tab_strip_->GetPreferredSize();
tab_strip_->SetBounds(0, 0, width(), size.height());
@@ -495,30 +521,15 @@ void TabbedPane::ViewHierarchyChanged(
bool TabbedPane::AcceleratorPressed(const ui::Accelerator& accelerator) {
// Handle Ctrl+Tab and Ctrl+Shift+Tab navigation of pages.
DCHECK(accelerator.key_code() == ui::VKEY_TAB && accelerator.IsCtrlDown());
- const int tab_count = GetTabCount();
- if (tab_count <= 1)
- return false;
- const int increment = accelerator.IsShiftDown() ? -1 : 1;
- int next_tab_index = (selected_tab_index() + increment) % tab_count;
- // Wrap around.
- if (next_tab_index < 0)
- next_tab_index += tab_count;
- SelectTabAt(next_tab_index);
- return true;
+ return MoveSelectionBy(accelerator.IsShiftDown() ? -1 : 1);
}
const char* TabbedPane::GetClassName() const {
return kViewClassName;
}
-void TabbedPane::OnFocus() {
- View::OnFocus();
-
- View* selected_tab = GetSelectedTab();
- if (selected_tab) {
- selected_tab->NotifyAccessibilityEvent(
- ui::AX_EVENT_FOCUS, true);
- }
+View* TabbedPane::GetSelectedTabContentView() {
+ return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr;
}
void TabbedPane::GetAccessibleState(ui::AXViewState* state) {
« 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