| 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
|
|
|
|
|