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

Side by Side 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 ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/focus/focus_manager.h"
6
7 #include "base/string_number_conversions.h"
8 #include "base/utf_string_conversions.h"
9 #include "ui/base/models/combobox_model.h"
10 #include "ui/views/focus/focus_manager_test.h"
11 #include "ui/views/widget/root_view.h"
12 #include "ui/views/widget/widget.h"
13 #include "views/controls/button/checkbox.h"
14 #include "views/controls/button/radio_button.h"
15 #include "views/controls/button/text_button.h"
16 #include "views/controls/combobox/combobox.h"
17 #include "views/controls/label.h"
18 #include "views/controls/link.h"
19 #include "views/controls/native/native_view_host.h"
20 #include "views/controls/scroll_view.h"
21 #include "views/controls/textfield/textfield.h"
22
23 #if !defined(USE_AURA)
24 #include "views/controls/tabbed_pane/tabbed_pane.h"
25 #endif
26
27 namespace views {
28
29 namespace {
30
31 int count = 1;
32
33 const int kTopCheckBoxID = count++; // 1
34 const int kLeftContainerID = count++;
35 const int kAppleLabelID = count++;
36 const int kAppleTextfieldID = count++;
37 const int kOrangeLabelID = count++; // 5
38 const int kOrangeTextfieldID = count++;
39 const int kBananaLabelID = count++;
40 const int kBananaTextfieldID = count++;
41 const int kKiwiLabelID = count++;
42 const int kKiwiTextfieldID = count++; // 10
43 const int kFruitButtonID = count++;
44 const int kFruitCheckBoxID = count++;
45 const int kComboboxID = count++;
46
47 const int kRightContainerID = count++;
48 const int kAsparagusButtonID = count++; // 15
49 const int kBroccoliButtonID = count++;
50 const int kCauliflowerButtonID = count++;
51
52 const int kInnerContainerID = count++;
53 const int kScrollViewID = count++;
54 const int kRosettaLinkID = count++; // 20
55 const int kStupeurEtTremblementLinkID = count++;
56 const int kDinerGameLinkID = count++;
57 const int kRidiculeLinkID = count++;
58 const int kClosetLinkID = count++;
59 const int kVisitingLinkID = count++; // 25
60 const int kAmelieLinkID = count++;
61 const int kJoyeuxNoelLinkID = count++;
62 const int kCampingLinkID = count++;
63 const int kBriceDeNiceLinkID = count++;
64 const int kTaxiLinkID = count++; // 30
65 const int kAsterixLinkID = count++;
66
67 const int kOKButtonID = count++;
68 const int kCancelButtonID = count++;
69 const int kHelpButtonID = count++;
70
71 #if !defined(USE_AURA)
72 const int kStyleContainerID = count++; // 35
73 const int kBoldCheckBoxID = count++;
74 const int kItalicCheckBoxID = count++;
75 const int kUnderlinedCheckBoxID = count++;
76 const int kStyleHelpLinkID = count++;
77 const int kStyleTextEditID = count++; // 40
78 #endif
79
80 const int kSearchContainerID = count++;
81 const int kSearchTextfieldID = count++;
82 const int kSearchButtonID = count++;
83 const int kHelpLinkID = count++;
84
85 const int kThumbnailContainerID = count++; // 45
86 const int kThumbnailStarID = count++;
87 const int kThumbnailSuperStarID = count++;
88
89 class DummyComboboxModel : public ui::ComboboxModel {
90 public:
91 virtual int GetItemCount() { return 10; }
92
93 virtual string16 GetItemAt(int index) {
94 return ASCIIToUTF16("Item ") + base::IntToString16(index);
95 }
96 };
97
98 // A View that can act as a pane.
99 class PaneView : public View, public FocusTraversable {
100 public:
101 PaneView() : focus_search_(NULL) {}
102
103 // If this method is called, this view will use GetPaneFocusTraversable to
104 // have this provided FocusSearch used instead of the default one, allowing
105 // you to trap focus within the pane.
106 void EnablePaneFocus(FocusSearch* focus_search) {
107 focus_search_ = focus_search;
108 }
109
110 // Overridden from views::View:
111 virtual FocusTraversable* GetPaneFocusTraversable() {
112 if (focus_search_)
113 return this;
114 else
115 return NULL;
116 }
117
118 // Overridden from views::FocusTraversable:
119 virtual views::FocusSearch* GetFocusSearch() {
120 return focus_search_;
121 }
122 virtual FocusTraversable* GetFocusTraversableParent() {
123 return NULL;
124 }
125 virtual View* GetFocusTraversableParentView() {
126 return NULL;
127 }
128
129 private:
130 FocusSearch* focus_search_;
131 };
132
133 // BorderView is a view containing a native window with its own view hierarchy.
134 // It is interesting to test focus traversal from a view hierarchy to an inner
135 // view hierarchy.
136 class BorderView : public NativeViewHost {
137 public:
138 explicit BorderView(View* child) : child_(child), widget_(NULL) {
139 DCHECK(child);
140 set_focusable(false);
141 }
142
143 virtual ~BorderView() {}
144
145 virtual internal::RootView* GetContentsRootView() {
146 return static_cast<internal::RootView*>(widget_->GetRootView());
147 }
148
149 virtual FocusTraversable* GetFocusTraversable() {
150 return static_cast<internal::RootView*>(widget_->GetRootView());
151 }
152
153 virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) {
154 NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
155
156 if (child == this && is_add) {
157 if (!widget_) {
158 widget_ = new Widget;
159 Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
160 #if defined(OS_WIN)
161 params.parent = parent->GetWidget()->GetNativeView();
162 #elif defined(TOOLKIT_USES_GTK)
163 params.parent = native_view();
164 #else
165 NOTREACHED();
166 #endif
167 widget_->Init(params);
168 widget_->SetFocusTraversableParentView(this);
169 widget_->SetContentsView(child_);
170 }
171
172 // We have been added to a view hierarchy, attach the native view.
173 Attach(widget_->GetNativeView());
174 // Also update the FocusTraversable parent so the focus traversal works.
175 static_cast<internal::RootView*>(widget_->GetRootView())->
176 SetFocusTraversableParent(GetWidget()->GetFocusTraversable());
177 }
178 }
179
180 private:
181 View* child_;
182 Widget* widget_;
183
184 DISALLOW_COPY_AND_ASSIGN(BorderView);
185 };
186
187 } // namespace
188
189 class FocusTraversalTest : public FocusManagerTest {
190 public:
191 ~FocusTraversalTest();
192
193 virtual void InitContentView() OVERRIDE;
194
195 protected:
196 FocusTraversalTest();
197
198 View* FindViewByID(int id) {
199 View* view = GetContentsView()->GetViewByID(id);
200 if (view)
201 return view;
202 #if !defined(USE_AURA)
203 if (style_tab_)
204 view = style_tab_->GetSelectedTab()->GetViewByID(id);
205 #endif
206 if (view)
207 return view;
208 view = search_border_view_->GetContentsRootView()->GetViewByID(id);
209 if (view)
210 return view;
211 return NULL;
212 }
213
214 protected:
215 #if !defined(USE_AURA)
216 TabbedPane* style_tab_;
217 #endif
218 BorderView* search_border_view_;
219 DummyComboboxModel combobox_model_;
220 PaneView* left_container_;
221 PaneView* right_container_;
222
223 DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest);
224 };
225
226 FocusTraversalTest::FocusTraversalTest()
227 :
228 #if !defined(USE_AURA)
229 style_tab_(NULL),
230 #endif
231 search_border_view_(NULL) {
232 }
233
234 FocusTraversalTest::~FocusTraversalTest() {
235 }
236
237 void FocusTraversalTest::InitContentView() {
238 // Create a complicated view hierarchy with lots of control types for
239 // use by all of the focus traversal tests.
240 //
241 // Class name, ID, and asterisk next to focusable views:
242 //
243 // View
244 // Checkbox * kTopCheckBoxID
245 // PaneView kLeftContainerID
246 // Label kAppleLabelID
247 // Textfield * kAppleTextfieldID
248 // Label kOrangeLabelID
249 // Textfield * kOrangeTextfieldID
250 // Label kBananaLabelID
251 // Textfield * kBananaTextfieldID
252 // Label kKiwiLabelID
253 // Textfield * kKiwiTextfieldID
254 // NativeButton * kFruitButtonID
255 // Checkbox * kFruitCheckBoxID
256 // Combobox * kComboboxID
257 // PaneView kRightContainerID
258 // RadioButton * kAsparagusButtonID
259 // RadioButton * kBroccoliButtonID
260 // RadioButton * kCauliflowerButtonID
261 // View kInnerContainerID
262 // ScrollView kScrollViewID
263 // View
264 // Link * kRosettaLinkID
265 // Link * kStupeurEtTremblementLinkID
266 // Link * kDinerGameLinkID
267 // Link * kRidiculeLinkID
268 // Link * kClosetLinkID
269 // Link * kVisitingLinkID
270 // Link * kAmelieLinkID
271 // Link * kJoyeuxNoelLinkID
272 // Link * kCampingLinkID
273 // Link * kBriceDeNiceLinkID
274 // Link * kTaxiLinkID
275 // Link * kAsterixLinkID
276 // NativeButton * kOKButtonID
277 // NativeButton * kCancelButtonID
278 // NativeButton * kHelpButtonID
279 // #if !defined(USE_AURA)
280 // TabbedPane * kStyleContainerID
281 // View
282 // Checkbox * kBoldCheckBoxID
283 // Checkbox * kItalicCheckBoxID
284 // Checkbox * kUnderlinedCheckBoxID
285 // Link * kStyleHelpLinkID
286 // Textfield * kStyleTextEditID
287 // Other
288 // #endif
289 // BorderView kSearchContainerID
290 // View
291 // Textfield * kSearchTextfieldID
292 // NativeButton * kSearchButtonID
293 // Link * kHelpLinkID
294 // View * kThumbnailContainerID
295 // NativeButton * kThumbnailStarID
296 // NativeButton * kThumbnailSuperStarID
297
298 GetContentsView()->set_background(
299 Background::CreateSolidBackground(SK_ColorWHITE));
300
301 Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox"));
302 GetContentsView()->AddChildView(cb);
303 // In this fast paced world, who really has time for non hard-coded layout?
304 cb->SetBounds(10, 10, 200, 20);
305 cb->set_id(kTopCheckBoxID);
306
307 left_container_ = new PaneView();
308 left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
309 left_container_->set_background(
310 Background::CreateSolidBackground(240, 240, 240));
311 left_container_->set_id(kLeftContainerID);
312 GetContentsView()->AddChildView(left_container_);
313 left_container_->SetBounds(10, 35, 250, 200);
314
315 int label_x = 5;
316 int label_width = 50;
317 int label_height = 15;
318 int text_field_width = 150;
319 int y = 10;
320 int gap_between_labels = 10;
321
322 Label* label = new Label(ASCIIToUTF16("Apple:"));
323 label->set_id(kAppleLabelID);
324 left_container_->AddChildView(label);
325 label->SetBounds(label_x, y, label_width, label_height);
326
327 Textfield* text_field = new Textfield();
328 text_field->set_id(kAppleTextfieldID);
329 left_container_->AddChildView(text_field);
330 text_field->SetBounds(label_x + label_width + 5, y,
331 text_field_width, label_height);
332
333 y += label_height + gap_between_labels;
334
335 label = new Label(ASCIIToUTF16("Orange:"));
336 label->set_id(kOrangeLabelID);
337 left_container_->AddChildView(label);
338 label->SetBounds(label_x, y, label_width, label_height);
339
340 text_field = new Textfield();
341 text_field->set_id(kOrangeTextfieldID);
342 left_container_->AddChildView(text_field);
343 text_field->SetBounds(label_x + label_width + 5, y,
344 text_field_width, label_height);
345
346 y += label_height + gap_between_labels;
347
348 label = new Label(ASCIIToUTF16("Banana:"));
349 label->set_id(kBananaLabelID);
350 left_container_->AddChildView(label);
351 label->SetBounds(label_x, y, label_width, label_height);
352
353 text_field = new Textfield();
354 text_field->set_id(kBananaTextfieldID);
355 left_container_->AddChildView(text_field);
356 text_field->SetBounds(label_x + label_width + 5, y,
357 text_field_width, label_height);
358
359 y += label_height + gap_between_labels;
360
361 label = new Label(ASCIIToUTF16("Kiwi:"));
362 label->set_id(kKiwiLabelID);
363 left_container_->AddChildView(label);
364 label->SetBounds(label_x, y, label_width, label_height);
365
366 text_field = new Textfield();
367 text_field->set_id(kKiwiTextfieldID);
368 left_container_->AddChildView(text_field);
369 text_field->SetBounds(label_x + label_width + 5, y,
370 text_field_width, label_height);
371
372 y += label_height + gap_between_labels;
373
374 NativeTextButton* button = new NativeTextButton(NULL,
375 ASCIIToUTF16("Click me"));
376 button->SetBounds(label_x, y + 10, 80, 30);
377 button->set_id(kFruitButtonID);
378 left_container_->AddChildView(button);
379 y += 40;
380
381 cb = new Checkbox(ASCIIToUTF16("This is another check box"));
382 cb->SetBounds(label_x + label_width + 5, y, 180, 20);
383 cb->set_id(kFruitCheckBoxID);
384 left_container_->AddChildView(cb);
385 y += 20;
386
387 Combobox* combobox = new Combobox(&combobox_model_);
388 combobox->SetBounds(label_x + label_width + 5, y, 150, 30);
389 combobox->set_id(kComboboxID);
390 left_container_->AddChildView(combobox);
391
392 right_container_ = new PaneView();
393 right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
394 right_container_->set_background(
395 Background::CreateSolidBackground(240, 240, 240));
396 right_container_->set_id(kRightContainerID);
397 GetContentsView()->AddChildView(right_container_);
398 right_container_->SetBounds(270, 35, 300, 200);
399
400 y = 10;
401 int radio_button_height = 18;
402 int gap_between_radio_buttons = 10;
403 RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1);
404 radio_button->set_id(kAsparagusButtonID);
405 right_container_->AddChildView(radio_button);
406 radio_button->SetBounds(5, y, 70, radio_button_height);
407 radio_button->SetGroup(1);
408 y += radio_button_height + gap_between_radio_buttons;
409 radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1);
410 radio_button->set_id(kBroccoliButtonID);
411 right_container_->AddChildView(radio_button);
412 radio_button->SetBounds(5, y, 70, radio_button_height);
413 radio_button->SetGroup(1);
414 RadioButton* radio_button_to_check = radio_button;
415 y += radio_button_height + gap_between_radio_buttons;
416 radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1);
417 radio_button->set_id(kCauliflowerButtonID);
418 right_container_->AddChildView(radio_button);
419 radio_button->SetBounds(5, y, 70, radio_button_height);
420 radio_button->SetGroup(1);
421 y += radio_button_height + gap_between_radio_buttons;
422
423 View* inner_container = new View();
424 inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
425 inner_container->set_background(
426 Background::CreateSolidBackground(230, 230, 230));
427 inner_container->set_id(kInnerContainerID);
428 right_container_->AddChildView(inner_container);
429 inner_container->SetBounds(100, 10, 150, 180);
430
431 ScrollView* scroll_view = new ScrollView();
432 scroll_view->set_id(kScrollViewID);
433 inner_container->AddChildView(scroll_view);
434 scroll_view->SetBounds(1, 1, 148, 178);
435
436 View* scroll_content = new View();
437 scroll_content->SetBounds(0, 0, 200, 200);
438 scroll_content->set_background(
439 Background::CreateSolidBackground(200, 200, 200));
440 scroll_view->SetContents(scroll_content);
441
442 static const char* const kTitles[] = {
443 "Rosetta", "Stupeur et tremblement", "The diner game",
444 "Ridicule", "Le placard", "Les Visiteurs", "Amelie",
445 "Joyeux Noel", "Camping", "Brice de Nice",
446 "Taxi", "Asterix"
447 };
448
449 static const int kIDs[] = {
450 kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
451 kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, kAmelieLinkID,
452 kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
453 kTaxiLinkID, kAsterixLinkID
454 };
455
456 DCHECK(arraysize(kTitles) == arraysize(kIDs));
457
458 y = 5;
459 for (size_t i = 0; i < arraysize(kTitles); ++i) {
460 Link* link = new Link(ASCIIToUTF16(kTitles[i]));
461 link->SetHorizontalAlignment(Label::ALIGN_LEFT);
462 link->set_id(kIDs[i]);
463 scroll_content->AddChildView(link);
464 link->SetBounds(5, y, 300, 15);
465 y += 15;
466 }
467
468 y = 250;
469 int width = 60;
470 button = new NativeTextButton(NULL, ASCIIToUTF16("OK"));
471 button->set_id(kOKButtonID);
472 button->SetIsDefault(true);
473
474 GetContentsView()->AddChildView(button);
475 button->SetBounds(150, y, width, 30);
476
477 button = new NativeTextButton(NULL, ASCIIToUTF16("Cancel"));
478 button->set_id(kCancelButtonID);
479 GetContentsView()->AddChildView(button);
480 button->SetBounds(220, y, width, 30);
481
482 button = new NativeTextButton(NULL, ASCIIToUTF16("Help"));
483 button->set_id(kHelpButtonID);
484 GetContentsView()->AddChildView(button);
485 button->SetBounds(290, y, width, 30);
486
487 y += 40;
488
489 View* contents = NULL;
490 Link* link = NULL;
491
492 #if !defined(USE_AURA)
493 // Left bottom box with style checkboxes.
494 contents = new View();
495 contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
496 cb = new Checkbox(ASCIIToUTF16("Bold"));
497 contents->AddChildView(cb);
498 cb->SetBounds(10, 10, 50, 20);
499 cb->set_id(kBoldCheckBoxID);
500
501 cb = new Checkbox(ASCIIToUTF16("Italic"));
502 contents->AddChildView(cb);
503 cb->SetBounds(70, 10, 50, 20);
504 cb->set_id(kItalicCheckBoxID);
505
506 cb = new Checkbox(ASCIIToUTF16("Underlined"));
507 contents->AddChildView(cb);
508 cb->SetBounds(130, 10, 70, 20);
509 cb->set_id(kUnderlinedCheckBoxID);
510
511 link = new Link(ASCIIToUTF16("Help"));
512 contents->AddChildView(link);
513 link->SetBounds(10, 35, 70, 10);
514 link->set_id(kStyleHelpLinkID);
515
516 text_field = new Textfield();
517 contents->AddChildView(text_field);
518 text_field->SetBounds(10, 50, 100, 20);
519 text_field->set_id(kStyleTextEditID);
520
521 style_tab_ = new TabbedPane();
522 style_tab_->set_id(kStyleContainerID);
523 GetContentsView()->AddChildView(style_tab_);
524 style_tab_->SetBounds(10, y, 210, 100);
525 style_tab_->AddTab(ASCIIToUTF16("Style"), contents);
526 style_tab_->AddTab(ASCIIToUTF16("Other"), new View());
527 #endif
528
529 // Right bottom box with search.
530 contents = new View();
531 contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
532 text_field = new Textfield();
533 contents->AddChildView(text_field);
534 text_field->SetBounds(10, 10, 100, 20);
535 text_field->set_id(kSearchTextfieldID);
536
537 button = new NativeTextButton(NULL, ASCIIToUTF16("Search"));
538 contents->AddChildView(button);
539 button->SetBounds(112, 5, 60, 30);
540 button->set_id(kSearchButtonID);
541
542 link = new Link(ASCIIToUTF16("Help"));
543 link->SetHorizontalAlignment(Label::ALIGN_LEFT);
544 link->set_id(kHelpLinkID);
545 contents->AddChildView(link);
546 link->SetBounds(175, 10, 30, 20);
547
548 search_border_view_ = new BorderView(contents);
549 search_border_view_->set_id(kSearchContainerID);
550
551 GetContentsView()->AddChildView(search_border_view_);
552 search_border_view_->SetBounds(300, y, 240, 50);
553
554 y += 60;
555
556 contents = new View();
557 contents->set_focusable(true);
558 contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE));
559 contents->set_id(kThumbnailContainerID);
560 button = new NativeTextButton(NULL, ASCIIToUTF16("Star"));
561 contents->AddChildView(button);
562 button->SetBounds(5, 5, 50, 30);
563 button->set_id(kThumbnailStarID);
564 button = new NativeTextButton(NULL, ASCIIToUTF16("SuperStar"));
565 contents->AddChildView(button);
566 button->SetBounds(60, 5, 100, 30);
567 button->set_id(kThumbnailSuperStarID);
568
569 GetContentsView()->AddChildView(contents);
570 contents->SetBounds(250, y, 200, 50);
571 // We can only call RadioButton::SetChecked() on the radio-button is part of
572 // the view hierarchy.
573 radio_button_to_check->SetChecked(true);
574 }
575
576 TEST_F(FocusTraversalTest, NormalTraversal) {
577 const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
578 kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
579 kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID,
580 kRosettaLinkID, kStupeurEtTremblementLinkID,
581 kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID,
582 kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
583 kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID,
584 #if !defined(USE_AURA)
585 kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
586 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
587 #endif
588 kSearchTextfieldID, kSearchButtonID, kHelpLinkID,
589 kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID };
590
591 // Uncomment the following line if you want to test manually the UI of this
592 // test.
593 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
594
595 // Let's traverse the whole focus hierarchy (several times, to make sure it
596 // loops OK).
597 GetFocusManager()->ClearFocus();
598 for (int i = 0; i < 3; ++i) {
599 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
600 GetFocusManager()->AdvanceFocus(false);
601 View* focused_view = GetFocusManager()->GetFocusedView();
602 EXPECT_TRUE(focused_view != NULL);
603 if (focused_view)
604 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
605 }
606 }
607
608 // Let's traverse in reverse order.
609 GetFocusManager()->ClearFocus();
610 for (int i = 0; i < 3; ++i) {
611 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
612 GetFocusManager()->AdvanceFocus(true);
613 View* focused_view = GetFocusManager()->GetFocusedView();
614 EXPECT_TRUE(focused_view != NULL);
615 if (focused_view)
616 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
617 }
618 }
619 }
620
621 TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
622 const int kDisabledIDs[] = {
623 kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID,
624 kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID,
625 kTaxiLinkID, kAsterixLinkID, kHelpButtonID,
626 #if !defined(USE_AURA)
627 kBoldCheckBoxID,
628 #endif
629 kSearchTextfieldID, kHelpLinkID };
630
631 const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
632 kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID,
633 kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
634 kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID,
635 kOKButtonID, kCancelButtonID,
636 #if !defined(USE_AURA)
637 kStyleContainerID, kItalicCheckBoxID, kUnderlinedCheckBoxID,
638 kStyleHelpLinkID, kStyleTextEditID,
639 #endif
640 kSearchButtonID, kThumbnailContainerID, kThumbnailStarID,
641 kThumbnailSuperStarID };
642
643 // Let's disable some views.
644 for (size_t i = 0; i < arraysize(kDisabledIDs); i++) {
645 View* v = FindViewByID(kDisabledIDs[i]);
646 ASSERT_TRUE(v != NULL);
647 v->SetEnabled(false);
648 }
649
650 // Uncomment the following line if you want to test manually the UI of this
651 // test.
652 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
653
654 View* focused_view;
655 // Let's do one traversal (several times, to make sure it loops ok).
656 GetFocusManager()->ClearFocus();
657 for (int i = 0; i < 3; ++i) {
658 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
659 GetFocusManager()->AdvanceFocus(false);
660 focused_view = GetFocusManager()->GetFocusedView();
661 EXPECT_TRUE(focused_view != NULL);
662 if (focused_view)
663 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
664 }
665 }
666
667 // Same thing in reverse.
668 GetFocusManager()->ClearFocus();
669 for (int i = 0; i < 3; ++i) {
670 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
671 GetFocusManager()->AdvanceFocus(true);
672 focused_view = GetFocusManager()->GetFocusedView();
673 EXPECT_TRUE(focused_view != NULL);
674 if (focused_view)
675 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
676 }
677 }
678 }
679
680 TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) {
681 const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID,
682 kThumbnailContainerID };
683
684 const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID,
685 kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID,
686 kComboboxID, kBroccoliButtonID, kRosettaLinkID,
687 kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID,
688 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
689 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID,
690 kCancelButtonID, kHelpButtonID,
691 #if !defined(USE_AURA)
692 kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
693 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
694 #endif
695 kSearchTextfieldID, kSearchButtonID, kHelpLinkID };
696
697
698 // Let's make some views invisible.
699 for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) {
700 View* v = FindViewByID(kInvisibleIDs[i]);
701 ASSERT_TRUE(v != NULL);
702 v->SetVisible(false);
703 }
704
705 // Uncomment the following line if you want to test manually the UI of this
706 // test.
707 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
708
709 View* focused_view;
710 // Let's do one traversal (several times, to make sure it loops ok).
711 GetFocusManager()->ClearFocus();
712 for (int i = 0; i < 3; ++i) {
713 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
714 GetFocusManager()->AdvanceFocus(false);
715 focused_view = GetFocusManager()->GetFocusedView();
716 EXPECT_TRUE(focused_view != NULL);
717 if (focused_view)
718 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
719 }
720 }
721
722 // Same thing in reverse.
723 GetFocusManager()->ClearFocus();
724 for (int i = 0; i < 3; ++i) {
725 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
726 GetFocusManager()->AdvanceFocus(true);
727 focused_view = GetFocusManager()->GetFocusedView();
728 EXPECT_TRUE(focused_view != NULL);
729 if (focused_view)
730 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
731 }
732 }
733 }
734
735 TEST_F(FocusTraversalTest, PaneTraversal) {
736 // Tests trapping the traversal within a pane - useful for full
737 // keyboard accessibility for toolbars.
738
739 // First test the left container.
740 const int kLeftTraversalIDs[] = {
741 kAppleTextfieldID,
742 kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
743 kFruitButtonID, kFruitCheckBoxID, kComboboxID };
744
745 FocusSearch focus_search_left(left_container_, true, false);
746 left_container_->EnablePaneFocus(&focus_search_left);
747 FindViewByID(kComboboxID)->RequestFocus();
748
749 // Traverse the focus hierarchy within the pane several times.
750 for (int i = 0; i < 3; ++i) {
751 for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) {
752 GetFocusManager()->AdvanceFocus(false);
753 View* focused_view = GetFocusManager()->GetFocusedView();
754 EXPECT_TRUE(focused_view != NULL);
755 if (focused_view)
756 EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
757 }
758 }
759
760 // Traverse in reverse order.
761 FindViewByID(kAppleTextfieldID)->RequestFocus();
762 for (int i = 0; i < 3; ++i) {
763 for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) {
764 GetFocusManager()->AdvanceFocus(true);
765 View* focused_view = GetFocusManager()->GetFocusedView();
766 EXPECT_TRUE(focused_view != NULL);
767 if (focused_view)
768 EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
769 }
770 }
771
772 // Now test the right container, but this time with accessibility mode.
773 // Make some links not focusable, but mark one of them as
774 // "accessibility focusable", so it should show up in the traversal.
775 const int kRightTraversalIDs[] = {
776 kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID,
777 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
778 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID };
779
780 FocusSearch focus_search_right(right_container_, true, true);
781 right_container_->EnablePaneFocus(&focus_search_right);
782 FindViewByID(kRosettaLinkID)->set_focusable(false);
783 FindViewByID(kStupeurEtTremblementLinkID)->set_focusable(false);
784 FindViewByID(kDinerGameLinkID)->set_accessibility_focusable(true);
785 FindViewByID(kDinerGameLinkID)->set_focusable(false);
786 FindViewByID(kAsterixLinkID)->RequestFocus();
787
788 // Traverse the focus hierarchy within the pane several times.
789 for (int i = 0; i < 3; ++i) {
790 for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) {
791 GetFocusManager()->AdvanceFocus(false);
792 View* focused_view = GetFocusManager()->GetFocusedView();
793 EXPECT_TRUE(focused_view != NULL);
794 if (focused_view)
795 EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
796 }
797 }
798
799 // Traverse in reverse order.
800 FindViewByID(kBroccoliButtonID)->RequestFocus();
801 for (int i = 0; i < 3; ++i) {
802 for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) {
803 GetFocusManager()->AdvanceFocus(true);
804 View* focused_view = GetFocusManager()->GetFocusedView();
805 EXPECT_TRUE(focused_view != NULL);
806 if (focused_view)
807 EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
808 }
809 }
810 }
811
812 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698