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

Unified Diff: ui/views/focus/focus_traversal_unittest.cc

Issue 8642002: Enable FocusManager tests for Aura. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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
Index: ui/views/focus/focus_traversal_unittest.cc
===================================================================
--- ui/views/focus/focus_traversal_unittest.cc (revision 0)
+++ ui/views/focus/focus_traversal_unittest.cc (revision 0)
@@ -0,0 +1,812 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/focus/focus_manager.h"
+
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/views/focus/focus_manager_test.h"
+#include "ui/views/widget/root_view.h"
+#include "ui/views/widget/widget.h"
+#include "views/controls/button/checkbox.h"
+#include "views/controls/button/radio_button.h"
+#include "views/controls/button/text_button.h"
+#include "views/controls/combobox/combobox.h"
+#include "views/controls/label.h"
+#include "views/controls/link.h"
+#include "views/controls/native/native_view_host.h"
+#include "views/controls/scroll_view.h"
+#include "views/controls/textfield/textfield.h"
+
+#if !defined(USE_AURA)
+#include "views/controls/tabbed_pane/tabbed_pane.h"
+#endif
+
+namespace views {
+
+namespace {
+
+int count = 1;
+
+const int kTopCheckBoxID = count++; // 1
+const int kLeftContainerID = count++;
+const int kAppleLabelID = count++;
+const int kAppleTextfieldID = count++;
+const int kOrangeLabelID = count++; // 5
+const int kOrangeTextfieldID = count++;
+const int kBananaLabelID = count++;
+const int kBananaTextfieldID = count++;
+const int kKiwiLabelID = count++;
+const int kKiwiTextfieldID = count++; // 10
+const int kFruitButtonID = count++;
+const int kFruitCheckBoxID = count++;
+const int kComboboxID = count++;
+
+const int kRightContainerID = count++;
+const int kAsparagusButtonID = count++; // 15
+const int kBroccoliButtonID = count++;
+const int kCauliflowerButtonID = count++;
+
+const int kInnerContainerID = count++;
+const int kScrollViewID = count++;
+const int kRosettaLinkID = count++; // 20
+const int kStupeurEtTremblementLinkID = count++;
+const int kDinerGameLinkID = count++;
+const int kRidiculeLinkID = count++;
+const int kClosetLinkID = count++;
+const int kVisitingLinkID = count++; // 25
+const int kAmelieLinkID = count++;
+const int kJoyeuxNoelLinkID = count++;
+const int kCampingLinkID = count++;
+const int kBriceDeNiceLinkID = count++;
+const int kTaxiLinkID = count++; // 30
+const int kAsterixLinkID = count++;
+
+const int kOKButtonID = count++;
+const int kCancelButtonID = count++;
+const int kHelpButtonID = count++;
+
+#if !defined(USE_AURA)
+const int kStyleContainerID = count++; // 35
+const int kBoldCheckBoxID = count++;
+const int kItalicCheckBoxID = count++;
+const int kUnderlinedCheckBoxID = count++;
+const int kStyleHelpLinkID = count++;
+const int kStyleTextEditID = count++; // 40
+#endif
+
+const int kSearchContainerID = count++;
+const int kSearchTextfieldID = count++;
+const int kSearchButtonID = count++;
+const int kHelpLinkID = count++;
+
+const int kThumbnailContainerID = count++; // 45
+const int kThumbnailStarID = count++;
+const int kThumbnailSuperStarID = count++;
+
+class DummyComboboxModel : public ui::ComboboxModel {
+ public:
+ virtual int GetItemCount() { return 10; }
+
+ virtual string16 GetItemAt(int index) {
+ return ASCIIToUTF16("Item ") + base::IntToString16(index);
+ }
+};
+
+// A View that can act as a pane.
+class PaneView : public View, public FocusTraversable {
+ public:
+ PaneView() : focus_search_(NULL) {}
+
+ // If this method is called, this view will use GetPaneFocusTraversable to
+ // have this provided FocusSearch used instead of the default one, allowing
+ // you to trap focus within the pane.
+ void EnablePaneFocus(FocusSearch* focus_search) {
+ focus_search_ = focus_search;
+ }
+
+ // Overridden from views::View:
+ virtual FocusTraversable* GetPaneFocusTraversable() {
+ if (focus_search_)
+ return this;
+ else
+ return NULL;
+ }
+
+ // Overridden from views::FocusTraversable:
+ virtual views::FocusSearch* GetFocusSearch() {
+ return focus_search_;
+ }
+ virtual FocusTraversable* GetFocusTraversableParent() {
+ return NULL;
+ }
+ virtual View* GetFocusTraversableParentView() {
+ return NULL;
+ }
+
+ private:
+ FocusSearch* focus_search_;
+};
+
+// BorderView is a view containing a native window with its own view hierarchy.
+// It is interesting to test focus traversal from a view hierarchy to an inner
+// view hierarchy.
+class BorderView : public NativeViewHost {
+ public:
+ explicit BorderView(View* child) : child_(child), widget_(NULL) {
+ DCHECK(child);
+ set_focusable(false);
+ }
+
+ virtual ~BorderView() {}
+
+ virtual internal::RootView* GetContentsRootView() {
+ return static_cast<internal::RootView*>(widget_->GetRootView());
+ }
+
+ virtual FocusTraversable* GetFocusTraversable() {
+ return static_cast<internal::RootView*>(widget_->GetRootView());
+ }
+
+ virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) {
+ NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
+
+ if (child == this && is_add) {
+ if (!widget_) {
+ widget_ = new Widget;
+ Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
+#if defined(OS_WIN)
+ params.parent = parent->GetWidget()->GetNativeView();
+#elif defined(TOOLKIT_USES_GTK)
+ params.parent = native_view();
+#else
+ NOTREACHED();
+#endif
+ widget_->Init(params);
+ widget_->SetFocusTraversableParentView(this);
+ widget_->SetContentsView(child_);
+ }
+
+ // We have been added to a view hierarchy, attach the native view.
+ Attach(widget_->GetNativeView());
+ // Also update the FocusTraversable parent so the focus traversal works.
+ static_cast<internal::RootView*>(widget_->GetRootView())->
+ SetFocusTraversableParent(GetWidget()->GetFocusTraversable());
+ }
+ }
+
+ private:
+ View* child_;
+ Widget* widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(BorderView);
+};
+
+} // namespace
+
+class FocusTraversalTest : public FocusManagerTest {
+ public:
+ ~FocusTraversalTest();
+
+ virtual void InitContentView() OVERRIDE;
+
+ protected:
+ FocusTraversalTest();
+
+ View* FindViewByID(int id) {
+ View* view = GetContentsView()->GetViewByID(id);
+ if (view)
+ return view;
+#if !defined(USE_AURA)
+ if (style_tab_)
+ view = style_tab_->GetSelectedTab()->GetViewByID(id);
+#endif
+ if (view)
+ return view;
+ view = search_border_view_->GetContentsRootView()->GetViewByID(id);
+ if (view)
+ return view;
+ return NULL;
+ }
+
+ protected:
+#if !defined(USE_AURA)
+ TabbedPane* style_tab_;
+#endif
+ BorderView* search_border_view_;
+ DummyComboboxModel combobox_model_;
+ PaneView* left_container_;
+ PaneView* right_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest);
+};
+
+FocusTraversalTest::FocusTraversalTest()
+ :
+#if !defined(USE_AURA)
+ style_tab_(NULL),
+#endif
+ search_border_view_(NULL) {
+}
+
+FocusTraversalTest::~FocusTraversalTest() {
+}
+
+void FocusTraversalTest::InitContentView() {
+ // Create a complicated view hierarchy with lots of control types for
+ // use by all of the focus traversal tests.
+ //
+ // Class name, ID, and asterisk next to focusable views:
+ //
+ // View
+ // Checkbox * kTopCheckBoxID
+ // PaneView kLeftContainerID
+ // Label kAppleLabelID
+ // Textfield * kAppleTextfieldID
+ // Label kOrangeLabelID
+ // Textfield * kOrangeTextfieldID
+ // Label kBananaLabelID
+ // Textfield * kBananaTextfieldID
+ // Label kKiwiLabelID
+ // Textfield * kKiwiTextfieldID
+ // NativeButton * kFruitButtonID
+ // Checkbox * kFruitCheckBoxID
+ // Combobox * kComboboxID
+ // PaneView kRightContainerID
+ // RadioButton * kAsparagusButtonID
+ // RadioButton * kBroccoliButtonID
+ // RadioButton * kCauliflowerButtonID
+ // View kInnerContainerID
+ // ScrollView kScrollViewID
+ // View
+ // Link * kRosettaLinkID
+ // Link * kStupeurEtTremblementLinkID
+ // Link * kDinerGameLinkID
+ // Link * kRidiculeLinkID
+ // Link * kClosetLinkID
+ // Link * kVisitingLinkID
+ // Link * kAmelieLinkID
+ // Link * kJoyeuxNoelLinkID
+ // Link * kCampingLinkID
+ // Link * kBriceDeNiceLinkID
+ // Link * kTaxiLinkID
+ // Link * kAsterixLinkID
+ // NativeButton * kOKButtonID
+ // NativeButton * kCancelButtonID
+ // NativeButton * kHelpButtonID
+ // #if !defined(USE_AURA)
+ // TabbedPane * kStyleContainerID
+ // View
+ // Checkbox * kBoldCheckBoxID
+ // Checkbox * kItalicCheckBoxID
+ // Checkbox * kUnderlinedCheckBoxID
+ // Link * kStyleHelpLinkID
+ // Textfield * kStyleTextEditID
+ // Other
+ // #endif
+ // BorderView kSearchContainerID
+ // View
+ // Textfield * kSearchTextfieldID
+ // NativeButton * kSearchButtonID
+ // Link * kHelpLinkID
+ // View * kThumbnailContainerID
+ // NativeButton * kThumbnailStarID
+ // NativeButton * kThumbnailSuperStarID
+
+ GetContentsView()->set_background(
+ Background::CreateSolidBackground(SK_ColorWHITE));
+
+ Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox"));
+ GetContentsView()->AddChildView(cb);
+ // In this fast paced world, who really has time for non hard-coded layout?
+ cb->SetBounds(10, 10, 200, 20);
+ cb->set_id(kTopCheckBoxID);
+
+ left_container_ = new PaneView();
+ left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ left_container_->set_background(
+ Background::CreateSolidBackground(240, 240, 240));
+ left_container_->set_id(kLeftContainerID);
+ GetContentsView()->AddChildView(left_container_);
+ left_container_->SetBounds(10, 35, 250, 200);
+
+ int label_x = 5;
+ int label_width = 50;
+ int label_height = 15;
+ int text_field_width = 150;
+ int y = 10;
+ int gap_between_labels = 10;
+
+ Label* label = new Label(ASCIIToUTF16("Apple:"));
+ label->set_id(kAppleLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ Textfield* text_field = new Textfield();
+ text_field->set_id(kAppleTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ label = new Label(ASCIIToUTF16("Orange:"));
+ label->set_id(kOrangeLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ text_field = new Textfield();
+ text_field->set_id(kOrangeTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ label = new Label(ASCIIToUTF16("Banana:"));
+ label->set_id(kBananaLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ text_field = new Textfield();
+ text_field->set_id(kBananaTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ label = new Label(ASCIIToUTF16("Kiwi:"));
+ label->set_id(kKiwiLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ text_field = new Textfield();
+ text_field->set_id(kKiwiTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ NativeTextButton* button = new NativeTextButton(NULL,
+ ASCIIToUTF16("Click me"));
+ button->SetBounds(label_x, y + 10, 80, 30);
+ button->set_id(kFruitButtonID);
+ left_container_->AddChildView(button);
+ y += 40;
+
+ cb = new Checkbox(ASCIIToUTF16("This is another check box"));
+ cb->SetBounds(label_x + label_width + 5, y, 180, 20);
+ cb->set_id(kFruitCheckBoxID);
+ left_container_->AddChildView(cb);
+ y += 20;
+
+ Combobox* combobox = new Combobox(&combobox_model_);
+ combobox->SetBounds(label_x + label_width + 5, y, 150, 30);
+ combobox->set_id(kComboboxID);
+ left_container_->AddChildView(combobox);
+
+ right_container_ = new PaneView();
+ right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ right_container_->set_background(
+ Background::CreateSolidBackground(240, 240, 240));
+ right_container_->set_id(kRightContainerID);
+ GetContentsView()->AddChildView(right_container_);
+ right_container_->SetBounds(270, 35, 300, 200);
+
+ y = 10;
+ int radio_button_height = 18;
+ int gap_between_radio_buttons = 10;
+ RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1);
+ radio_button->set_id(kAsparagusButtonID);
+ right_container_->AddChildView(radio_button);
+ radio_button->SetBounds(5, y, 70, radio_button_height);
+ radio_button->SetGroup(1);
+ y += radio_button_height + gap_between_radio_buttons;
+ radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1);
+ radio_button->set_id(kBroccoliButtonID);
+ right_container_->AddChildView(radio_button);
+ radio_button->SetBounds(5, y, 70, radio_button_height);
+ radio_button->SetGroup(1);
+ RadioButton* radio_button_to_check = radio_button;
+ y += radio_button_height + gap_between_radio_buttons;
+ radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1);
+ radio_button->set_id(kCauliflowerButtonID);
+ right_container_->AddChildView(radio_button);
+ radio_button->SetBounds(5, y, 70, radio_button_height);
+ radio_button->SetGroup(1);
+ y += radio_button_height + gap_between_radio_buttons;
+
+ View* inner_container = new View();
+ inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ inner_container->set_background(
+ Background::CreateSolidBackground(230, 230, 230));
+ inner_container->set_id(kInnerContainerID);
+ right_container_->AddChildView(inner_container);
+ inner_container->SetBounds(100, 10, 150, 180);
+
+ ScrollView* scroll_view = new ScrollView();
+ scroll_view->set_id(kScrollViewID);
+ inner_container->AddChildView(scroll_view);
+ scroll_view->SetBounds(1, 1, 148, 178);
+
+ View* scroll_content = new View();
+ scroll_content->SetBounds(0, 0, 200, 200);
+ scroll_content->set_background(
+ Background::CreateSolidBackground(200, 200, 200));
+ scroll_view->SetContents(scroll_content);
+
+ static const char* const kTitles[] = {
+ "Rosetta", "Stupeur et tremblement", "The diner game",
+ "Ridicule", "Le placard", "Les Visiteurs", "Amelie",
+ "Joyeux Noel", "Camping", "Brice de Nice",
+ "Taxi", "Asterix"
+ };
+
+ static const int kIDs[] = {
+ kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
+ kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, kAmelieLinkID,
+ kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
+ kTaxiLinkID, kAsterixLinkID
+ };
+
+ DCHECK(arraysize(kTitles) == arraysize(kIDs));
+
+ y = 5;
+ for (size_t i = 0; i < arraysize(kTitles); ++i) {
+ Link* link = new Link(ASCIIToUTF16(kTitles[i]));
+ link->SetHorizontalAlignment(Label::ALIGN_LEFT);
+ link->set_id(kIDs[i]);
+ scroll_content->AddChildView(link);
+ link->SetBounds(5, y, 300, 15);
+ y += 15;
+ }
+
+ y = 250;
+ int width = 60;
+ button = new NativeTextButton(NULL, ASCIIToUTF16("OK"));
+ button->set_id(kOKButtonID);
+ button->SetIsDefault(true);
+
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(150, y, width, 30);
+
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Cancel"));
+ button->set_id(kCancelButtonID);
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(220, y, width, 30);
+
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Help"));
+ button->set_id(kHelpButtonID);
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(290, y, width, 30);
+
+ y += 40;
+
+ View* contents = NULL;
+ Link* link = NULL;
+
+#if !defined(USE_AURA)
+ // Left bottom box with style checkboxes.
+ contents = new View();
+ contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
+ cb = new Checkbox(ASCIIToUTF16("Bold"));
+ contents->AddChildView(cb);
+ cb->SetBounds(10, 10, 50, 20);
+ cb->set_id(kBoldCheckBoxID);
+
+ cb = new Checkbox(ASCIIToUTF16("Italic"));
+ contents->AddChildView(cb);
+ cb->SetBounds(70, 10, 50, 20);
+ cb->set_id(kItalicCheckBoxID);
+
+ cb = new Checkbox(ASCIIToUTF16("Underlined"));
+ contents->AddChildView(cb);
+ cb->SetBounds(130, 10, 70, 20);
+ cb->set_id(kUnderlinedCheckBoxID);
+
+ link = new Link(ASCIIToUTF16("Help"));
+ contents->AddChildView(link);
+ link->SetBounds(10, 35, 70, 10);
+ link->set_id(kStyleHelpLinkID);
+
+ text_field = new Textfield();
+ contents->AddChildView(text_field);
+ text_field->SetBounds(10, 50, 100, 20);
+ text_field->set_id(kStyleTextEditID);
+
+ style_tab_ = new TabbedPane();
+ style_tab_->set_id(kStyleContainerID);
+ GetContentsView()->AddChildView(style_tab_);
+ style_tab_->SetBounds(10, y, 210, 100);
+ style_tab_->AddTab(ASCIIToUTF16("Style"), contents);
+ style_tab_->AddTab(ASCIIToUTF16("Other"), new View());
+#endif
+
+ // Right bottom box with search.
+ contents = new View();
+ contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
+ text_field = new Textfield();
+ contents->AddChildView(text_field);
+ text_field->SetBounds(10, 10, 100, 20);
+ text_field->set_id(kSearchTextfieldID);
+
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Search"));
+ contents->AddChildView(button);
+ button->SetBounds(112, 5, 60, 30);
+ button->set_id(kSearchButtonID);
+
+ link = new Link(ASCIIToUTF16("Help"));
+ link->SetHorizontalAlignment(Label::ALIGN_LEFT);
+ link->set_id(kHelpLinkID);
+ contents->AddChildView(link);
+ link->SetBounds(175, 10, 30, 20);
+
+ search_border_view_ = new BorderView(contents);
+ search_border_view_->set_id(kSearchContainerID);
+
+ GetContentsView()->AddChildView(search_border_view_);
+ search_border_view_->SetBounds(300, y, 240, 50);
+
+ y += 60;
+
+ contents = new View();
+ contents->set_focusable(true);
+ contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE));
+ contents->set_id(kThumbnailContainerID);
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Star"));
+ contents->AddChildView(button);
+ button->SetBounds(5, 5, 50, 30);
+ button->set_id(kThumbnailStarID);
+ button = new NativeTextButton(NULL, ASCIIToUTF16("SuperStar"));
+ contents->AddChildView(button);
+ button->SetBounds(60, 5, 100, 30);
+ button->set_id(kThumbnailSuperStarID);
+
+ GetContentsView()->AddChildView(contents);
+ contents->SetBounds(250, y, 200, 50);
+ // We can only call RadioButton::SetChecked() on the radio-button is part of
+ // the view hierarchy.
+ radio_button_to_check->SetChecked(true);
+}
+
+TEST_F(FocusTraversalTest, NormalTraversal) {
+ const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
+ kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
+ kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID,
+ kRosettaLinkID, kStupeurEtTremblementLinkID,
+ kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID,
+ kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
+ kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID,
+#if !defined(USE_AURA)
+ kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
+ kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
+#endif
+ kSearchTextfieldID, kSearchButtonID, kHelpLinkID,
+ kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID };
+
+ // Uncomment the following line if you want to test manually the UI of this
+ // test.
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ // Let's traverse the whole focus hierarchy (several times, to make sure it
+ // loops OK).
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Let's traverse in reverse order.
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
+ const int kDisabledIDs[] = {
+ kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID,
+ kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID,
+ kTaxiLinkID, kAsterixLinkID, kHelpButtonID,
+#if !defined(USE_AURA)
+ kBoldCheckBoxID,
+#endif
+ kSearchTextfieldID, kHelpLinkID };
+
+ const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
+ kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID,
+ kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
+ kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID,
+ kOKButtonID, kCancelButtonID,
+#if !defined(USE_AURA)
+ kStyleContainerID, kItalicCheckBoxID, kUnderlinedCheckBoxID,
+ kStyleHelpLinkID, kStyleTextEditID,
+#endif
+ kSearchButtonID, kThumbnailContainerID, kThumbnailStarID,
+ kThumbnailSuperStarID };
+
+ // Let's disable some views.
+ for (size_t i = 0; i < arraysize(kDisabledIDs); i++) {
+ View* v = FindViewByID(kDisabledIDs[i]);
+ ASSERT_TRUE(v != NULL);
+ v->SetEnabled(false);
+ }
+
+ // Uncomment the following line if you want to test manually the UI of this
+ // test.
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ View* focused_view;
+ // Let's do one traversal (several times, to make sure it loops ok).
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Same thing in reverse.
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) {
+ const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID,
+ kThumbnailContainerID };
+
+ const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID,
+ kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID,
+ kComboboxID, kBroccoliButtonID, kRosettaLinkID,
+ kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID,
+ kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
+ kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID,
+ kCancelButtonID, kHelpButtonID,
+#if !defined(USE_AURA)
+ kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
+ kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
+#endif
+ kSearchTextfieldID, kSearchButtonID, kHelpLinkID };
+
+
+ // Let's make some views invisible.
+ for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) {
+ View* v = FindViewByID(kInvisibleIDs[i]);
+ ASSERT_TRUE(v != NULL);
+ v->SetVisible(false);
+ }
+
+ // Uncomment the following line if you want to test manually the UI of this
+ // test.
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ View* focused_view;
+ // Let's do one traversal (several times, to make sure it loops ok).
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Same thing in reverse.
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+TEST_F(FocusTraversalTest, PaneTraversal) {
+ // Tests trapping the traversal within a pane - useful for full
+ // keyboard accessibility for toolbars.
+
+ // First test the left container.
+ const int kLeftTraversalIDs[] = {
+ kAppleTextfieldID,
+ kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
+ kFruitButtonID, kFruitCheckBoxID, kComboboxID };
+
+ FocusSearch focus_search_left(left_container_, true, false);
+ left_container_->EnablePaneFocus(&focus_search_left);
+ FindViewByID(kComboboxID)->RequestFocus();
+
+ // Traverse the focus hierarchy within the pane several times.
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Traverse in reverse order.
+ FindViewByID(kAppleTextfieldID)->RequestFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Now test the right container, but this time with accessibility mode.
+ // Make some links not focusable, but mark one of them as
+ // "accessibility focusable", so it should show up in the traversal.
+ const int kRightTraversalIDs[] = {
+ kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID,
+ kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
+ kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID };
+
+ FocusSearch focus_search_right(right_container_, true, true);
+ right_container_->EnablePaneFocus(&focus_search_right);
+ FindViewByID(kRosettaLinkID)->set_focusable(false);
+ FindViewByID(kStupeurEtTremblementLinkID)->set_focusable(false);
+ FindViewByID(kDinerGameLinkID)->set_accessibility_focusable(true);
+ FindViewByID(kDinerGameLinkID)->set_focusable(false);
+ FindViewByID(kAsterixLinkID)->RequestFocus();
+
+ // Traverse the focus hierarchy within the pane several times.
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Traverse in reverse order.
+ FindViewByID(kBroccoliButtonID)->RequestFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+} // namespace views
Property changes on: ui\views\focus\focus_traversal_unittest.cc
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698