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

Side by Side Diff: ui/views/examples/dialog_example.cc

Issue 2701373002: Add a DialogExample example to views_examples (Closed)
Patch Set: respond to comments Created 3 years, 10 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
« no previous file with comments | « ui/views/examples/dialog_example.h ('k') | ui/views/examples/examples_window.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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/examples/dialog_example.h"
6
7 #include "base/macros.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "ui/views/bubble/bubble_dialog_delegate.h"
10 #include "ui/views/controls/button/checkbox.h"
11 #include "ui/views/controls/button/label_button.h"
12 #include "ui/views/controls/button/md_text_button.h"
13 #include "ui/views/controls/combobox/combobox.h"
14 #include "ui/views/controls/label.h"
15 #include "ui/views/controls/textfield/textfield.h"
16 #include "ui/views/layout/fill_layout.h"
17 #include "ui/views/layout/grid_layout.h"
18 #include "ui/views/layout/layout_constants.h"
19 #include "ui/views/views_delegate.h"
20 #include "ui/views/widget/widget.h"
21 #include "ui/views/window/dialog_client_view.h"
22
23 using base::ASCIIToUTF16;
24
25 namespace views {
26 namespace examples {
27 namespace {
28
29 constexpr int kFieldsColumnId = 0;
30 constexpr int kButtonsColumnId = 1;
31 constexpr int kFakeModeless = ui::MODAL_TYPE_SYSTEM + 1;
32
33 } // namespace
34
35 template <class DialogType>
36 class DialogExample::Delegate : public virtual DialogType {
37 public:
38 explicit Delegate(DialogExample* parent) : parent_(parent) {}
39
40 void InitDelegate() {
41 LayoutManager* fill_layout = new FillLayout();
42 this->SetLayoutManager(fill_layout);
43 Label* body = new Label(parent_->body_->text());
44 body->SetMultiLine(true);
45 body->SetHorizontalAlignment(gfx::ALIGN_LEFT);
46 body->set_background(Background::CreateSolidBackground(0, 255, 255));
47 this->AddChildView(body);
48
49 // Give the example code a way to change the body text.
50 parent_->last_body_label_ = body;
51 }
52
53 protected:
54 // WidgetDelegate:
55 ui::ModalType GetModalType() const override {
56 return parent_->GetModalType();
57 }
58
59 base::string16 GetWindowTitle() const override {
60 return parent_->title_->text();
61 }
62
63 // DialogDelegate:
64 View* CreateExtraView() {
65 if (!parent_->has_extra_button_->checked())
66 return nullptr;
67 return MdTextButton::CreateSecondaryUiButton(
68 nullptr, parent_->extra_button_label_->text());
69 }
70
71 bool Cancel() override { return parent_->AllowDialogClose(false); }
72 bool Accept() override { return parent_->AllowDialogClose(true); }
73 int GetDialogButtons() const override { return parent_->GetDialogButtons(); }
74 base::string16 GetDialogButtonLabel(ui::DialogButton button) const override {
75 if (button == ui::DIALOG_BUTTON_OK)
76 return parent_->ok_button_label_->text();
77 if (button == ui::DIALOG_BUTTON_CANCEL)
78 return parent_->cancel_button_label_->text();
79 return base::string16();
80 }
81
82 private:
83 DialogExample* parent_;
84
85 DISALLOW_COPY_AND_ASSIGN(Delegate);
86 };
87
88 class DialogExample::Bubble : public Delegate<BubbleDialogDelegateView> {
89 public:
90 Bubble(DialogExample* parent, View* anchor)
91 : BubbleDialogDelegateView(anchor, BubbleBorder::TOP_LEFT),
92 Delegate(parent) {
93 set_close_on_deactivate(!parent->persistent_bubble_->checked());
94 }
95
96 // BubbleDialogDelegateView:
97 void Init() override { InitDelegate(); }
98
99 private:
100 DISALLOW_COPY_AND_ASSIGN(Bubble);
101 };
102
103 class DialogExample::Dialog : public Delegate<DialogDelegateView> {
104 public:
105 explicit Dialog(DialogExample* parent) : Delegate(parent) {}
106
107 // WidgetDelegate:
108 bool CanResize() const override {
109 // Mac supports resizing of modal dialogs (parent or window-modal). On other
110 // platforms this will be weird unless the modal type is "none", but helps
111 // test layout.
112 return true;
113 }
114
115 private:
116 DISALLOW_COPY_AND_ASSIGN(Dialog);
117 };
118
119 DialogExample::DialogExample()
120 : ExampleBase("Dialog"),
121 mode_model_({
122 base::ASCIIToUTF16("Modeless"), base::ASCIIToUTF16("Window Modal"),
123 base::ASCIIToUTF16("Child Modal"), base::ASCIIToUTF16("System Modal"),
124 base::ASCIIToUTF16("Fake Modeless (non-bubbles)"),
125 }) {}
126
127 DialogExample::~DialogExample() {}
128
129 void DialogExample::CreateExampleView(View* container) {
130 // GridLayout |resize_percent| constants.
131 const float kFixed = 0.f;
132 const float kStretchy = 1.f;
133
134 const int horizontal_spacing =
135 ViewsDelegate::GetInstance()->GetDialogRelatedButtonHorizontalSpacing();
136 GridLayout* layout = GridLayout::CreatePanel(container);
137 container->SetLayoutManager(layout);
138 ColumnSet* column_set = layout->AddColumnSet(kFieldsColumnId);
139 column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, kFixed,
140 GridLayout::USE_PREF, 0, 0);
141 column_set->AddPaddingColumn(kFixed, horizontal_spacing);
142 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kStretchy,
143 GridLayout::USE_PREF, 0, 0);
144 column_set->AddPaddingColumn(kFixed, horizontal_spacing);
145 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kFixed,
146 GridLayout::USE_PREF, 0, 0);
147 StartTextfieldRow(layout, &title_, "Dialog Title", "Title");
148 StartTextfieldRow(layout, &body_, "Dialog Body Text", "Body Text");
149
150 StartTextfieldRow(layout, &ok_button_label_, "OK Button Label", "Done");
151 AddCheckbox(layout, &has_ok_button_);
152
153 StartTextfieldRow(layout, &cancel_button_label_, "Cancel Button Label",
154 "Cancel");
155 AddCheckbox(layout, &has_cancel_button_);
156
157 StartTextfieldRow(layout, &extra_button_label_, "Extra Button Label", "Edit");
158 AddCheckbox(layout, &has_extra_button_);
159
160 StartRowWithLabel(layout, "Modal Type");
161 mode_ = new Combobox(&mode_model_);
162 mode_->set_listener(this);
163 mode_->SetSelectedIndex(ui::MODAL_TYPE_CHILD);
164 layout->AddView(mode_);
165
166 StartRowWithLabel(layout, "Bubble");
167 AddCheckbox(layout, &bubble_);
168 AddCheckbox(layout, &persistent_bubble_);
169 persistent_bubble_->SetText(base::ASCIIToUTF16("Persistent"));
170
171 column_set = layout->AddColumnSet(kButtonsColumnId);
172 column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, kStretchy,
173 GridLayout::USE_PREF, 0, 0);
174 layout->StartRowWithPadding(kFixed, kButtonsColumnId, kFixed,
175 kUnrelatedControlVerticalSpacing);
176 show_ =
177 MdTextButton::CreateSecondaryUiButton(this, base::ASCIIToUTF16("Show"));
178 layout->AddView(show_);
179
180 // Grow the dialog a bit when this example is first selected, so it all fits.
181 gfx::Size dialog_size = container->GetWidget()->GetRestoredBounds().size();
182 dialog_size.set_height(dialog_size.height() + 80);
183 container->GetWidget()->SetSize(dialog_size);
184 }
185
186 void DialogExample::StartRowWithLabel(GridLayout* layout, const char* label) {
187 const float kFixedVerticalResize = 0.f;
188 layout->StartRowWithPadding(
189 kFixedVerticalResize, kFieldsColumnId, kFixedVerticalResize,
190 ViewsDelegate::GetInstance()->GetDialogRelatedControlVerticalSpacing());
191 layout->AddView(new Label(base::ASCIIToUTF16(label)));
192 }
193
194 void DialogExample::StartTextfieldRow(GridLayout* layout,
195 Textfield** member,
196 const char* label,
197 const char* value) {
198 StartRowWithLabel(layout, label);
199 Textfield* textfield = new Textfield();
200 layout->AddView(textfield);
201 textfield->set_controller(this);
202 textfield->SetText(base::ASCIIToUTF16(value));
203 *member = textfield;
204 }
205
206 void DialogExample::AddCheckbox(GridLayout* layout, Checkbox** member) {
207 Checkbox* checkbox = new Checkbox(base::string16());
208 checkbox->set_listener(this);
209 checkbox->SetChecked(true);
210 layout->AddView(checkbox);
211 *member = checkbox;
212 }
213
214 ui::ModalType DialogExample::GetModalType() const {
215 // "Fake" modeless happens when a DialogDelegate specifies window-modal, but
216 // doesn't provide a parent window.
217 if (mode_->selected_index() == kFakeModeless)
218 return ui::MODAL_TYPE_WINDOW;
219
220 return static_cast<ui::ModalType>(mode_->selected_index());
221 }
222
223 int DialogExample::GetDialogButtons() const {
224 int buttons = 0;
225 if (has_ok_button_->checked())
226 buttons |= ui::DIALOG_BUTTON_OK;
227 if (has_cancel_button_->checked())
228 buttons |= ui::DIALOG_BUTTON_CANCEL;
229 return buttons;
230 }
231
232 bool DialogExample::AllowDialogClose(bool accept) {
233 PrintStatus("Dialog closed with %s.", accept ? "Accept" : "Cancel");
234 last_dialog_ = nullptr;
235 last_body_label_ = nullptr;
236 return true;
237 }
238
239 void DialogExample::ResizeDialog() {
240 DCHECK(last_dialog_);
241 Widget* widget = last_dialog_->GetWidget();
242 gfx::Rect preferred_bounds(widget->GetRestoredBounds());
243 preferred_bounds.set_size(widget->non_client_view()->GetPreferredSize());
244
245 // Q: Do we need NonClientFrameView::GetWindowBoundsForClientBounds() here?
246 // A: When DialogCientView properly feeds back sizes, we do not.
247 widget->SetBoundsConstrained(preferred_bounds);
248 }
249
250 void DialogExample::ButtonPressed(Button* sender, const ui::Event& event) {
251 if (sender == show_) {
252 if (bubble_->checked()) {
253 Bubble* bubble = new Bubble(this, sender);
254 last_dialog_ = bubble;
255 BubbleDialogDelegateView::CreateBubble(bubble);
256 } else {
257 Dialog* dialog = new Dialog(this);
258 last_dialog_ = dialog;
259 dialog->InitDelegate();
260
261 // constrained_window::CreateBrowserModalDialogViews() allows dialogs to
262 // be created as MODAL_TYPE_WINDOW without specifying a parent.
263 gfx::NativeView parent = nullptr;
264 if (mode_->selected_index() != kFakeModeless)
265 parent = container()->GetWidget()->GetNativeView();
266
267 DialogDelegate::CreateDialogWidget(
268 dialog, container()->GetWidget()->GetNativeWindow(), parent);
269 }
270 last_dialog_->GetWidget()->Show();
271 return;
272 }
273
274 if (sender == bubble_) {
275 if (bubble_->checked() && GetModalType() != ui::MODAL_TYPE_CHILD) {
276 mode_->SetSelectedIndex(ui::MODAL_TYPE_CHILD);
277 PrintStatus("You nearly always want Child Modal for bubbles.");
278 }
279 persistent_bubble_->SetEnabled(bubble_->checked());
280 OnPerformAction(mode_); // Validate the modal type.
281
282 if (!bubble_->checked() && GetModalType() == ui::MODAL_TYPE_CHILD) {
283 // Do something reasonable when simply unchecking bubble and re-enable.
284 mode_->SetSelectedIndex(ui::MODAL_TYPE_WINDOW);
285 OnPerformAction(mode_);
286 }
287 return;
288 }
289
290 // Other buttons are all checkboxes. Update the dialog if there is one.
291 if (last_dialog_) {
292 last_dialog_->GetDialogClientView()->UpdateDialogButtons();
293 ResizeDialog();
294 }
295 }
296
297 void DialogExample::ContentsChanged(Textfield* sender,
298 const base::string16& new_contents) {
299 if (!last_dialog_)
300 return;
301
302 if (sender == extra_button_label_)
303 PrintStatus("DialogClientView can never refresh the extra view.");
304
305 if (sender == title_) {
306 last_dialog_->GetWidget()->UpdateWindowTitle();
307 } else if (sender == body_) {
308 last_body_label_->SetText(new_contents);
309 } else {
310 last_dialog_->GetDialogClientView()->UpdateDialogButtons();
311 }
312
313 ResizeDialog();
314 }
315
316 void DialogExample::OnPerformAction(Combobox* combobox) {
317 bool enable = bubble_->checked() || GetModalType() != ui::MODAL_TYPE_CHILD;
318 #if defined(OS_MACOSX)
319 enable = enable && GetModalType() != ui::MODAL_TYPE_SYSTEM;
320 #endif
321 show_->SetEnabled(enable);
322 if (!enable && GetModalType() == ui::MODAL_TYPE_CHILD)
323 PrintStatus("MODAL_TYPE_CHILD can't be used with non-bubbles.");
324 if (!enable && GetModalType() == ui::MODAL_TYPE_SYSTEM)
325 PrintStatus("MODAL_TYPE_SYSTEM isn't supported on Mac.");
326 }
327
328 } // namespace examples
329 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/examples/dialog_example.h ('k') | ui/views/examples/examples_window.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698