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 |