1 // Copyright 2020 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 #ifndef UI_VIEWS_BUBBLE_BUBBLE_DIALOG_MODEL_HOST_H_ 6 #define UI_VIEWS_BUBBLE_BUBBLE_DIALOG_MODEL_HOST_H_ 7 8 #include <memory> 9 #include <vector> 10 11 #include "base/callback.h" 12 #include "ui/base/models/dialog_model.h" 13 #include "ui/views/bubble/bubble_dialog_delegate_view.h" 14 #include "ui/views/controls/button/button.h" 15 16 namespace views { 17 18 class Label; 19 class StyledLabel; 20 21 // BubbleDialogModelHost is a views implementation of ui::DialogModelHost which 22 // hosts a ui::DialogModel as a BubbleDialogDelegateView. This exposes such as 23 // SetAnchorView(), SetArrow() and SetHighlightedButton(). For methods that are 24 // reflected in ui::DialogModelHost (such as ::Close()), prefer using the 25 // ui::DialogModelHost to avoid platform-specific code (GetWidget()->Close()) 26 // where unnecessary. For those methods, note that this can be retrieved as a 27 // ui::DialogModelHost through DialogModel::host(). This helps minimize 28 // platform-specific code from platform-agnostic model-delegate code. 29 class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView, 30 public ui::DialogModelHost { 31 public: 32 METADATA_HEADER(BubbleDialogModelHost); 33 // Constructs a BubbleDialogModelHost, which for most purposes is to used as a 34 // BubbleDialogDelegateView. The BubbleDialogDelegateView is nominally handed 35 // to BubbleDialogDelegateView::CreateBubble() which returns a Widget that has 36 // taken ownership of the bubble. Widget::Show() finally shows the bubble. 37 BubbleDialogModelHost(std::unique_ptr<ui::DialogModel> model, 38 View* anchor_view, 39 BubbleBorder::Arrow arrow); 40 ~BubbleDialogModelHost() override; 41 42 static std::unique_ptr<BubbleDialogModelHost> CreateModal( 43 std::unique_ptr<ui::DialogModel> model, 44 ui::ModalType modal_type); 45 46 // BubbleDialogDelegateView: 47 // TODO(pbos): Populate initparams with initial view instead of overriding 48 // GetInitiallyFocusedView(). 49 View* GetInitiallyFocusedView() override; 50 void OnDialogInitialized() override; 51 52 // ui::DialogModelHost: 53 void Close() override; 54 void SelectAllText(int unique_id) override; 55 void OnFieldAdded(ui::DialogModelField* field) override; 56 57 private: 58 // TODO(pbos): Consider externalizing this functionality into a different 59 // format that could feasibly be adopted by LayoutManagers. This is used for 60 // BoxLayouts (but could be others) to agree on columns' preferred width as a 61 // replacement for using GridLayout. 62 class LayoutConsensusView; 63 class LayoutConsensusGroup { 64 public: 65 LayoutConsensusGroup(); 66 ~LayoutConsensusGroup(); 67 68 void AddView(LayoutConsensusView* view); 69 void RemoveView(LayoutConsensusView* view); 70 71 void InvalidateChildren(); 72 73 // Get the union of all preferred sizes within the group. 74 gfx::Size GetMaxPreferredSize() const; 75 76 // Get the union of all minimum sizes within the group. 77 gfx::Size GetMaxMinimumSize() const; 78 79 private: 80 base::flat_set<View*> children_; 81 }; 82 83 struct DialogModelHostField { 84 ui::DialogModelField* dialog_model_field; 85 86 // View representing the entire field. 87 View* field_view; 88 89 // Child view to |field_view|, if any, that's used for focus. For instance, 90 // a textfield row would be a container that contains both a 91 // views::Textfield and a descriptive label. In this case |focusable_view| 92 // would refer to the views::Textfield which is also what would gain focus. 93 View* focusable_view; 94 }; 95 96 void OnWindowClosing(); 97 98 void AddInitialFields(); 99 void AddOrUpdateBodyText(ui::DialogModelBodyText* model_field); 100 void AddOrUpdateCheckbox(ui::DialogModelCheckbox* model_field); 101 void AddOrUpdateCombobox(ui::DialogModelCombobox* model_field); 102 void AddOrUpdateTextfield(ui::DialogModelTextfield* model_field); 103 104 void UpdateSpacingAndMargins(); 105 106 void AddViewForLabelAndField(ui::DialogModelField* model_field, 107 const base::string16& label_text, 108 std::unique_ptr<views::View> field, 109 const gfx::FontList& field_font); 110 111 static bool DialogModelLabelRequiresStyledLabel( 112 const ui::DialogModelLabel& dialog_label); 113 std::unique_ptr<View> CreateViewForLabel( 114 const ui::DialogModelLabel& dialog_label); 115 std::unique_ptr<StyledLabel> CreateStyledLabelForDialogModelLabel( 116 const ui::DialogModelLabel& dialog_label); 117 std::unique_ptr<Label> CreateLabelForDialogModelLabel( 118 const ui::DialogModelLabel& dialog_label); 119 120 void AddDialogModelHostField(std::unique_ptr<View> view, 121 const DialogModelHostField& field_view_info); 122 void AddDialogModelHostFieldForExistingView( 123 const DialogModelHostField& field_view_info); 124 125 DialogModelHostField FindDialogModelHostField( 126 ui::DialogModelField* model_field); 127 DialogModelHostField FindDialogModelHostField(View* view); 128 129 static View* GetTargetView(const DialogModelHostField& field_view_info); 130 131 bool IsModalDialog() const; 132 133 std::unique_ptr<ui::DialogModel> model_; 134 std::vector<DialogModelHostField> fields_; 135 std::vector<PropertyChangedSubscription> property_changed_subscriptions_; 136 137 LayoutConsensusGroup textfield_first_column_group_; 138 LayoutConsensusGroup textfield_second_column_group_; 139 }; 140 141 } // namespace views 142 143 #endif // UI_VIEWS_BUBBLE_BUBBLE_DIALOG_MODEL_HOST_H_ 144