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

Side by Side Diff: ui/views/window/dialog_client_view.cc

Issue 2807653002: Ensure default dialog button focus remains after a dialog update. (Closed)
Patch Set: Using a view deletion observer to track focus. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/window/dialog_client_view.h" 5 #include "ui/views/window/dialog_client_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "build/build_config.h" 9 #include "build/build_config.h"
10 #include "ui/base/material_design/material_design_controller.h" 10 #include "ui/base/material_design/material_design_controller.h"
11 #include "ui/events/keycodes/keyboard_codes.h" 11 #include "ui/events/keycodes/keyboard_codes.h"
12 #include "ui/views/background.h" 12 #include "ui/views/background.h"
13 #include "ui/views/border.h" 13 #include "ui/views/border.h"
14 #include "ui/views/controls/button/blue_button.h" 14 #include "ui/views/controls/button/blue_button.h"
15 #include "ui/views/controls/button/custom_button.h" 15 #include "ui/views/controls/button/custom_button.h"
16 #include "ui/views/controls/button/label_button.h" 16 #include "ui/views/controls/button/label_button.h"
17 #include "ui/views/controls/button/md_text_button.h" 17 #include "ui/views/controls/button/md_text_button.h"
18 #include "ui/views/layout/grid_layout.h" 18 #include "ui/views/layout/grid_layout.h"
19 #include "ui/views/style/platform_style.h" 19 #include "ui/views/style/platform_style.h"
20 #include "ui/views/view_observer.h"
20 #include "ui/views/views_delegate.h" 21 #include "ui/views/views_delegate.h"
21 #include "ui/views/widget/widget.h" 22 #include "ui/views/widget/widget.h"
22 #include "ui/views/window/dialog_delegate.h" 23 #include "ui/views/window/dialog_delegate.h"
23 24
25 namespace {
sky 2017/05/17 19:08:30 Move this code to around line 80ish, inside the vi
ackermanb 2017/05/17 22:03:49 Done.
26
27 class ViewDeletionObserver : public views::ViewObserver {
sky 2017/05/17 19:08:30 Add comment.
ackermanb 2017/05/17 22:03:50 Done.
28 public:
29 ViewDeletionObserver(views::View* observed_view)
sky 2017/05/17 19:08:30 explicit
ackermanb 2017/05/17 22:03:50 Done.
30 : observed_view_(observed_view) {
31 if (observed_view_)
32 observed_view_->AddObserver(this);
33 }
34
35 ~ViewDeletionObserver() override {
36 if (observed_view_)
37 observed_view_->RemoveObserver(this);
38 }
39
40 void OnViewIsDeleting(views::View* observed_view) override {
sky 2017/05/17 19:08:30 Prefix with: // ViewObserver:
ackermanb 2017/05/17 22:03:50 Done.
41 DCHECK_EQ(observed_view, observed_view_);
42 observed_view_ = nullptr;
sky 2017/05/17 19:08:30 Remove observer here.
ackermanb 2017/05/17 22:03:49 Done.
43 }
44
45 views::View* focused_view() { return observed_view_; }
46
47 private:
48 views::View* observed_view_ = nullptr;
Devlin 2017/05/17 18:13:49 DISALLOW_COPY_AND_ASSIGN()
ackermanb 2017/05/17 22:03:50 Done.
49 };
50
51 } // namespace
52
24 namespace views { 53 namespace views {
25 54
26 namespace { 55 namespace {
27 56
28 // The group used by the buttons. This name is chosen voluntarily big not to 57 // The group used by the buttons. This name is chosen voluntarily big not to
29 // conflict with other groups that could be in the dialog content. 58 // conflict with other groups that could be in the dialog content.
30 const int kButtonGroup = 6666; 59 const int kButtonGroup = 6666;
31 60
32 #if defined(OS_WIN) || defined(OS_CHROMEOS) 61 #if defined(OS_WIN) || defined(OS_CHROMEOS)
33 const bool kIsOkButtonOnLeftSide = true; 62 const bool kIsOkButtonOnLeftSide = true;
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 View* third = ok_button_; 341 View* third = ok_button_;
313 if (kIsOkButtonOnLeftSide) 342 if (kIsOkButtonOnLeftSide)
314 std::swap(second, third); 343 std::swap(second, third);
315 return {{first, second, third}}; 344 return {{first, second, third}};
316 } 345 }
317 346
318 void DialogClientView::SetupLayout() { 347 void DialogClientView::SetupLayout() {
319 base::AutoReset<bool> auto_reset(&adding_or_removing_views_, true); 348 base::AutoReset<bool> auto_reset(&adding_or_removing_views_, true);
320 GridLayout* layout = new GridLayout(button_row_container_); 349 GridLayout* layout = new GridLayout(button_row_container_);
321 layout->set_minimum_size(minimum_size_); 350 layout->set_minimum_size(minimum_size_);
351 ViewDeletionObserver deletion_observer(GetFocusManager()->GetFocusedView());
Devlin 2017/05/17 18:13:49 nit: Since we use the FocusManager twice in this f
ackermanb 2017/05/17 22:03:50 Done.
322 352
323 // Clobber any existing LayoutManager since it has weak references to child 353 // Clobber any existing LayoutManager since it has weak references to child
324 // Views which may be removed by SetupViews(). 354 // Views which may be removed by SetupViews().
325 button_row_container_->SetLayoutManager(layout); 355 button_row_container_->SetLayoutManager(layout);
326 SetupViews(); 356 SetupViews();
327 const std::array<View*, kNumButtons> views = GetButtonRowViews(); 357 const std::array<View*, kNumButtons> views = GetButtonRowViews();
328 358
329 // Visibility changes on |extra_view_| must be observed to re-Layout. However, 359 // Visibility changes on |extra_view_| must be observed to re-Layout. However,
330 // when hidden it's not included in the button row (it can't influence layout) 360 // when hidden it's not included in the button row (it can't influence layout)
331 // and it can't be added to |button_row_container_| (GridLayout complains). 361 // and it can't be added to |button_row_container_| (GridLayout complains).
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 } 422 }
393 423
394 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { 424 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
395 // Only link the extra view column if it is a button. 425 // Only link the extra view column if it is a button.
396 if (views[0] && !CustomButton::AsCustomButton(views[0])) 426 if (views[0] && !CustomButton::AsCustomButton(views[0]))
397 column_set->LinkColumnSizes(link[1], link[2], -1); 427 column_set->LinkColumnSizes(link[1], link[2], -1);
398 else 428 else
399 column_set->LinkColumnSizes(link[0], link[1], link[2], -1); 429 column_set->LinkColumnSizes(link[0], link[1], link[2], -1);
400 } 430 }
401 layout->AddPaddingRow(kFixed, insets.bottom()); 431 layout->AddPaddingRow(kFixed, insets.bottom());
432
433 // The default focus is lost when child views are added back into the dialog.
434 // This restores focus if the button is still available.
435 View* focused_view = deletion_observer.focused_view();
sky 2017/05/17 19:08:30 Name this previously_focused_view.
ackermanb 2017/05/17 22:03:50 Done.
436 if (!GetFocusManager()->GetFocusedView() && focused_view)
Devlin 2017/05/17 18:13:49 drive-by nit: I'd invert these, since checking foc
sky 2017/05/17 19:08:30 Also, add a conditional of Contains(focused_view);
ackermanb 2017/05/17 22:03:49 Done.
ackermanb 2017/05/17 22:03:50 Done.
437 focused_view->RequestFocus();
402 } 438 }
403 439
404 void DialogClientView::SetupViews() { 440 void DialogClientView::SetupViews() {
405 button_row_container_->RemoveAllChildViews(false /* delete children */); 441 button_row_container_->RemoveAllChildViews(false /* delete children */);
406 // If SetupLayout() "stored" a hidden |extra_view_| in |this|, ensure it can 442 // If SetupLayout() "stored" a hidden |extra_view_| in |this|, ensure it can
407 // be re-added to the layout when becoming visible. 443 // be re-added to the layout when becoming visible.
408 if (extra_view_) 444 if (extra_view_)
409 RemoveChildView(extra_view_); 445 RemoveChildView(extra_view_);
410 446
411 UpdateDialogButton(&ok_button_, ui::DIALOG_BUTTON_OK); 447 UpdateDialogButton(&ok_button_, ui::DIALOG_BUTTON_OK);
412 UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL); 448 UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL);
413 449
414 if (extra_view_) 450 if (extra_view_)
415 return; 451 return;
416 452
417 extra_view_ = GetDialogDelegate()->CreateExtraView(); 453 extra_view_ = GetDialogDelegate()->CreateExtraView();
418 if (extra_view_) 454 if (extra_view_)
419 extra_view_->SetGroup(kButtonGroup); 455 extra_view_->SetGroup(kButtonGroup);
420 } 456 }
421 457
422 } // namespace views 458 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698