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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/examples/dialog_example.cc
diff --git a/ui/views/examples/dialog_example.cc b/ui/views/examples/dialog_example.cc
new file mode 100644
index 0000000000000000000000000000000000000000..637c6dafabb1957002431d3e709998ed9e4c4af4
--- /dev/null
+++ b/ui/views/examples/dialog_example.cc
@@ -0,0 +1,329 @@
+// Copyright 2017 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/examples/dialog_example.h"
+
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/views/bubble/bubble_dialog_delegate.h"
+#include "ui/views/controls/button/checkbox.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/views_delegate.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/window/dialog_client_view.h"
+
+using base::ASCIIToUTF16;
+
+namespace views {
+namespace examples {
+namespace {
+
+constexpr int kFieldsColumnId = 0;
+constexpr int kButtonsColumnId = 1;
+constexpr int kFakeModeless = ui::MODAL_TYPE_SYSTEM + 1;
+
+} // namespace
+
+template <class DialogType>
+class DialogExample::Delegate : public virtual DialogType {
+ public:
+ explicit Delegate(DialogExample* parent) : parent_(parent) {}
+
+ void InitDelegate() {
+ LayoutManager* fill_layout = new FillLayout();
+ this->SetLayoutManager(fill_layout);
+ Label* body = new Label(parent_->body_->text());
+ body->SetMultiLine(true);
+ body->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ body->set_background(Background::CreateSolidBackground(0, 255, 255));
+ this->AddChildView(body);
+
+ // Give the example code a way to change the body text.
+ parent_->last_body_label_ = body;
+ }
+
+ protected:
+ // WidgetDelegate:
+ ui::ModalType GetModalType() const override {
+ return parent_->GetModalType();
+ }
+
+ base::string16 GetWindowTitle() const override {
+ return parent_->title_->text();
+ }
+
+ // DialogDelegate:
+ View* CreateExtraView() {
+ if (!parent_->has_extra_button_->checked())
+ return nullptr;
+ return MdTextButton::CreateSecondaryUiButton(
+ nullptr, parent_->extra_button_label_->text());
+ }
+
+ bool Cancel() override { return parent_->AllowDialogClose(false); }
+ bool Accept() override { return parent_->AllowDialogClose(true); }
+ int GetDialogButtons() const override { return parent_->GetDialogButtons(); }
+ base::string16 GetDialogButtonLabel(ui::DialogButton button) const override {
+ if (button == ui::DIALOG_BUTTON_OK)
+ return parent_->ok_button_label_->text();
+ if (button == ui::DIALOG_BUTTON_CANCEL)
+ return parent_->cancel_button_label_->text();
+ return base::string16();
+ }
+
+ private:
+ DialogExample* parent_;
+
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+};
+
+class DialogExample::Bubble : public Delegate<BubbleDialogDelegateView> {
+ public:
+ Bubble(DialogExample* parent, View* anchor)
+ : BubbleDialogDelegateView(anchor, BubbleBorder::TOP_LEFT),
+ Delegate(parent) {
+ set_close_on_deactivate(!parent->persistent_bubble_->checked());
+ }
+
+ // BubbleDialogDelegateView:
+ void Init() override { InitDelegate(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Bubble);
+};
+
+class DialogExample::Dialog : public Delegate<DialogDelegateView> {
+ public:
+ explicit Dialog(DialogExample* parent) : Delegate(parent) {}
+
+ // WidgetDelegate:
+ bool CanResize() const override {
+ // Mac supports resizing of modal dialogs (parent or window-modal). On other
+ // platforms this will be weird unless the modal type is "none", but helps
+ // test layout.
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Dialog);
+};
+
+DialogExample::DialogExample()
+ : ExampleBase("Dialog"),
+ mode_model_({
+ base::ASCIIToUTF16("Modeless"), base::ASCIIToUTF16("Window Modal"),
+ base::ASCIIToUTF16("Child Modal"), base::ASCIIToUTF16("System Modal"),
+ base::ASCIIToUTF16("Fake Modeless (non-bubbles)"),
+ }) {}
+
+DialogExample::~DialogExample() {}
+
+void DialogExample::CreateExampleView(View* container) {
+ // GridLayout |resize_percent| constants.
+ const float kFixed = 0.f;
+ const float kStretchy = 1.f;
+
+ const int horizontal_spacing =
+ ViewsDelegate::GetInstance()->GetDialogRelatedButtonHorizontalSpacing();
+ GridLayout* layout = GridLayout::CreatePanel(container);
+ container->SetLayoutManager(layout);
+ ColumnSet* column_set = layout->AddColumnSet(kFieldsColumnId);
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, kFixed,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(kFixed, horizontal_spacing);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kStretchy,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(kFixed, horizontal_spacing);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kFixed,
+ GridLayout::USE_PREF, 0, 0);
+ StartTextfieldRow(layout, &title_, "Dialog Title", "Title");
+ StartTextfieldRow(layout, &body_, "Dialog Body Text", "Body Text");
+
+ StartTextfieldRow(layout, &ok_button_label_, "OK Button Label", "Done");
+ AddCheckbox(layout, &has_ok_button_);
+
+ StartTextfieldRow(layout, &cancel_button_label_, "Cancel Button Label",
+ "Cancel");
+ AddCheckbox(layout, &has_cancel_button_);
+
+ StartTextfieldRow(layout, &extra_button_label_, "Extra Button Label", "Edit");
+ AddCheckbox(layout, &has_extra_button_);
+
+ StartRowWithLabel(layout, "Modal Type");
+ mode_ = new Combobox(&mode_model_);
+ mode_->set_listener(this);
+ mode_->SetSelectedIndex(ui::MODAL_TYPE_CHILD);
+ layout->AddView(mode_);
+
+ StartRowWithLabel(layout, "Bubble");
+ AddCheckbox(layout, &bubble_);
+ AddCheckbox(layout, &persistent_bubble_);
+ persistent_bubble_->SetText(base::ASCIIToUTF16("Persistent"));
+
+ column_set = layout->AddColumnSet(kButtonsColumnId);
+ column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, kStretchy,
+ GridLayout::USE_PREF, 0, 0);
+ layout->StartRowWithPadding(kFixed, kButtonsColumnId, kFixed,
+ kUnrelatedControlVerticalSpacing);
+ show_ =
+ MdTextButton::CreateSecondaryUiButton(this, base::ASCIIToUTF16("Show"));
+ layout->AddView(show_);
+
+ // Grow the dialog a bit when this example is first selected, so it all fits.
+ gfx::Size dialog_size = container->GetWidget()->GetRestoredBounds().size();
+ dialog_size.set_height(dialog_size.height() + 80);
+ container->GetWidget()->SetSize(dialog_size);
+}
+
+void DialogExample::StartRowWithLabel(GridLayout* layout, const char* label) {
+ const float kFixedVerticalResize = 0.f;
+ layout->StartRowWithPadding(
+ kFixedVerticalResize, kFieldsColumnId, kFixedVerticalResize,
+ ViewsDelegate::GetInstance()->GetDialogRelatedControlVerticalSpacing());
+ layout->AddView(new Label(base::ASCIIToUTF16(label)));
+}
+
+void DialogExample::StartTextfieldRow(GridLayout* layout,
+ Textfield** member,
+ const char* label,
+ const char* value) {
+ StartRowWithLabel(layout, label);
+ Textfield* textfield = new Textfield();
+ layout->AddView(textfield);
+ textfield->set_controller(this);
+ textfield->SetText(base::ASCIIToUTF16(value));
+ *member = textfield;
+}
+
+void DialogExample::AddCheckbox(GridLayout* layout, Checkbox** member) {
+ Checkbox* checkbox = new Checkbox(base::string16());
+ checkbox->set_listener(this);
+ checkbox->SetChecked(true);
+ layout->AddView(checkbox);
+ *member = checkbox;
+}
+
+ui::ModalType DialogExample::GetModalType() const {
+ // "Fake" modeless happens when a DialogDelegate specifies window-modal, but
+ // doesn't provide a parent window.
+ if (mode_->selected_index() == kFakeModeless)
+ return ui::MODAL_TYPE_WINDOW;
+
+ return static_cast<ui::ModalType>(mode_->selected_index());
+}
+
+int DialogExample::GetDialogButtons() const {
+ int buttons = 0;
+ if (has_ok_button_->checked())
+ buttons |= ui::DIALOG_BUTTON_OK;
+ if (has_cancel_button_->checked())
+ buttons |= ui::DIALOG_BUTTON_CANCEL;
+ return buttons;
+}
+
+bool DialogExample::AllowDialogClose(bool accept) {
+ PrintStatus("Dialog closed with %s.", accept ? "Accept" : "Cancel");
+ last_dialog_ = nullptr;
+ last_body_label_ = nullptr;
+ return true;
+}
+
+void DialogExample::ResizeDialog() {
+ DCHECK(last_dialog_);
+ Widget* widget = last_dialog_->GetWidget();
+ gfx::Rect preferred_bounds(widget->GetRestoredBounds());
+ preferred_bounds.set_size(widget->non_client_view()->GetPreferredSize());
+
+ // Q: Do we need NonClientFrameView::GetWindowBoundsForClientBounds() here?
+ // A: When DialogCientView properly feeds back sizes, we do not.
+ widget->SetBoundsConstrained(preferred_bounds);
+}
+
+void DialogExample::ButtonPressed(Button* sender, const ui::Event& event) {
+ if (sender == show_) {
+ if (bubble_->checked()) {
+ Bubble* bubble = new Bubble(this, sender);
+ last_dialog_ = bubble;
+ BubbleDialogDelegateView::CreateBubble(bubble);
+ } else {
+ Dialog* dialog = new Dialog(this);
+ last_dialog_ = dialog;
+ dialog->InitDelegate();
+
+ // constrained_window::CreateBrowserModalDialogViews() allows dialogs to
+ // be created as MODAL_TYPE_WINDOW without specifying a parent.
+ gfx::NativeView parent = nullptr;
+ if (mode_->selected_index() != kFakeModeless)
+ parent = container()->GetWidget()->GetNativeView();
+
+ DialogDelegate::CreateDialogWidget(
+ dialog, container()->GetWidget()->GetNativeWindow(), parent);
+ }
+ last_dialog_->GetWidget()->Show();
+ return;
+ }
+
+ if (sender == bubble_) {
+ if (bubble_->checked() && GetModalType() != ui::MODAL_TYPE_CHILD) {
+ mode_->SetSelectedIndex(ui::MODAL_TYPE_CHILD);
+ PrintStatus("You nearly always want Child Modal for bubbles.");
+ }
+ persistent_bubble_->SetEnabled(bubble_->checked());
+ OnPerformAction(mode_); // Validate the modal type.
+
+ if (!bubble_->checked() && GetModalType() == ui::MODAL_TYPE_CHILD) {
+ // Do something reasonable when simply unchecking bubble and re-enable.
+ mode_->SetSelectedIndex(ui::MODAL_TYPE_WINDOW);
+ OnPerformAction(mode_);
+ }
+ return;
+ }
+
+ // Other buttons are all checkboxes. Update the dialog if there is one.
+ if (last_dialog_) {
+ last_dialog_->GetDialogClientView()->UpdateDialogButtons();
+ ResizeDialog();
+ }
+}
+
+void DialogExample::ContentsChanged(Textfield* sender,
+ const base::string16& new_contents) {
+ if (!last_dialog_)
+ return;
+
+ if (sender == extra_button_label_)
+ PrintStatus("DialogClientView can never refresh the extra view.");
+
+ if (sender == title_) {
+ last_dialog_->GetWidget()->UpdateWindowTitle();
+ } else if (sender == body_) {
+ last_body_label_->SetText(new_contents);
+ } else {
+ last_dialog_->GetDialogClientView()->UpdateDialogButtons();
+ }
+
+ ResizeDialog();
+}
+
+void DialogExample::OnPerformAction(Combobox* combobox) {
+ bool enable = bubble_->checked() || GetModalType() != ui::MODAL_TYPE_CHILD;
+#if defined(OS_MACOSX)
+ enable = enable && GetModalType() != ui::MODAL_TYPE_SYSTEM;
+#endif
+ show_->SetEnabled(enable);
+ if (!enable && GetModalType() == ui::MODAL_TYPE_CHILD)
+ PrintStatus("MODAL_TYPE_CHILD can't be used with non-bubbles.");
+ if (!enable && GetModalType() == ui::MODAL_TYPE_SYSTEM)
+ PrintStatus("MODAL_TYPE_SYSTEM isn't supported on Mac.");
+}
+
+} // namespace examples
+} // namespace views
« 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