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 #include "ui/base/models/dialog_model.h"
6 
7 #include "base/callback_helpers.h"
8 #include "base/ranges/algorithm.h"
9 
10 namespace ui {
11 
Builder(std::unique_ptr<DialogModelDelegate> delegate)12 DialogModel::Builder::Builder(std::unique_ptr<DialogModelDelegate> delegate)
13     : model_(std::make_unique<DialogModel>(util::PassKey<Builder>(),
14                                            std::move(delegate))) {}
15 
Builder()16 DialogModel::Builder::Builder() : Builder(nullptr) {}
17 
~Builder()18 DialogModel::Builder::~Builder() {
19   DCHECK(!model_) << "Model should've been built.";
20 }
21 
Build()22 std::unique_ptr<DialogModel> DialogModel::Builder::Build() {
23   DCHECK(model_);
24   return std::move(model_);
25 }
26 
AddOkButton(base::OnceClosure callback,base::string16 label,const DialogModelButton::Params & params)27 DialogModel::Builder& DialogModel::Builder::AddOkButton(
28     base::OnceClosure callback,
29     base::string16 label,
30     const DialogModelButton::Params& params) {
31   DCHECK(!model_->accept_callback_);
32   model_->accept_callback_ = std::move(callback);
33   // NOTREACHED() is used below to make sure this callback isn't used.
34   // DialogModelHost should be using OnDialogAccepted() instead.
35   model_->ok_button_.emplace(
36       model_->GetPassKey(), model_.get(),
37       base::BindRepeating([](const Event&) { NOTREACHED(); }), std::move(label),
38       params);
39 
40   return *this;
41 }
42 
AddCancelButton(base::OnceClosure callback,base::string16 label,const DialogModelButton::Params & params)43 DialogModel::Builder& DialogModel::Builder::AddCancelButton(
44     base::OnceClosure callback,
45     base::string16 label,
46     const DialogModelButton::Params& params) {
47   DCHECK(!model_->cancel_callback_);
48   model_->cancel_callback_ = std::move(callback);
49   // NOTREACHED() is used below to make sure this callback isn't used.
50   // DialogModelHost should be using OnDialogCanceled() instead.
51   model_->cancel_button_.emplace(
52       model_->GetPassKey(), model_.get(),
53       base::BindRepeating([](const Event&) { NOTREACHED(); }), std::move(label),
54       params);
55 
56   return *this;
57 }
58 
AddDialogExtraButton(base::RepeatingCallback<void (const Event &)> callback,base::string16 label,const DialogModelButton::Params & params)59 DialogModel::Builder& DialogModel::Builder::AddDialogExtraButton(
60     base::RepeatingCallback<void(const Event&)> callback,
61     base::string16 label,
62     const DialogModelButton::Params& params) {
63   model_->extra_button_.emplace(model_->GetPassKey(), model_.get(),
64                                 std::move(callback), std::move(label), params);
65   return *this;
66 }
67 
SetInitiallyFocusedField(int unique_id)68 DialogModel::Builder& DialogModel::Builder::SetInitiallyFocusedField(
69     int unique_id) {
70   // This must be called with unique_id >= 0 (-1 is "no ID").
71   DCHECK_GE(unique_id, 0);
72   // This can only be called once.
73   DCHECK(!model_->initially_focused_field_);
74   model_->initially_focused_field_ = unique_id;
75   return *this;
76 }
77 
DialogModel(util::PassKey<Builder>,std::unique_ptr<DialogModelDelegate> delegate)78 DialogModel::DialogModel(util::PassKey<Builder>,
79                          std::unique_ptr<DialogModelDelegate> delegate)
80     : delegate_(std::move(delegate)) {
81   if (delegate_)
82     delegate_->set_dialog_model(this);
83 }
84 
85 DialogModel::~DialogModel() = default;
86 
AddBodyText(const DialogModelLabel & label)87 void DialogModel::AddBodyText(const DialogModelLabel& label) {
88   AddField(std::make_unique<DialogModelBodyText>(GetPassKey(), this, label));
89 }
90 
AddCheckbox(int unique_id,const DialogModelLabel & label)91 void DialogModel::AddCheckbox(int unique_id, const DialogModelLabel& label) {
92   AddField(std::make_unique<DialogModelCheckbox>(GetPassKey(), this, unique_id,
93                                                  label));
94 }
95 
AddCombobox(base::string16 label,std::unique_ptr<ui::ComboboxModel> combobox_model,const DialogModelCombobox::Params & params)96 void DialogModel::AddCombobox(base::string16 label,
97                               std::unique_ptr<ui::ComboboxModel> combobox_model,
98                               const DialogModelCombobox::Params& params) {
99   AddField(std::make_unique<DialogModelCombobox>(
100       GetPassKey(), this, std::move(label), std::move(combobox_model), params));
101 }
102 
AddTextfield(base::string16 label,base::string16 text,const DialogModelTextfield::Params & params)103 void DialogModel::AddTextfield(base::string16 label,
104                                base::string16 text,
105                                const DialogModelTextfield::Params& params) {
106   AddField(std::make_unique<DialogModelTextfield>(
107       GetPassKey(), this, std::move(label), std::move(text), params));
108 }
109 
HasField(int unique_id) const110 bool DialogModel::HasField(int unique_id) const {
111   return base::ranges::any_of(fields_, [unique_id](auto& field) {
112     return field->unique_id_ == unique_id;
113   });
114 }
115 
GetFieldByUniqueId(int unique_id)116 DialogModelField* DialogModel::GetFieldByUniqueId(int unique_id) {
117   for (auto& field : fields_) {
118     if (field->unique_id_ == unique_id)
119       return field.get();
120   }
121   NOTREACHED();
122   return nullptr;
123 }
124 
GetCheckboxByUniqueId(int unique_id)125 DialogModelCheckbox* DialogModel::GetCheckboxByUniqueId(int unique_id) {
126   return GetFieldByUniqueId(unique_id)->AsCheckbox();
127 }
128 
GetComboboxByUniqueId(int unique_id)129 DialogModelCombobox* DialogModel::GetComboboxByUniqueId(int unique_id) {
130   return GetFieldByUniqueId(unique_id)->AsCombobox();
131 }
132 
GetTextfieldByUniqueId(int unique_id)133 DialogModelTextfield* DialogModel::GetTextfieldByUniqueId(int unique_id) {
134   return GetFieldByUniqueId(unique_id)->AsTextfield();
135 }
136 
OnDialogAccepted(util::PassKey<DialogModelHost>)137 void DialogModel::OnDialogAccepted(util::PassKey<DialogModelHost>) {
138   if (accept_callback_)
139     std::move(accept_callback_).Run();
140 }
141 
OnDialogCancelled(util::PassKey<DialogModelHost>)142 void DialogModel::OnDialogCancelled(util::PassKey<DialogModelHost>) {
143   if (cancel_callback_)
144     std::move(cancel_callback_).Run();
145 }
146 
OnDialogClosed(util::PassKey<DialogModelHost>)147 void DialogModel::OnDialogClosed(util::PassKey<DialogModelHost>) {
148   if (close_callback_)
149     std::move(close_callback_).Run();
150 }
151 
OnWindowClosing(util::PassKey<DialogModelHost>)152 void DialogModel::OnWindowClosing(util::PassKey<DialogModelHost>) {
153   if (window_closing_callback_)
154     std::move(window_closing_callback_).Run();
155 }
156 
AddField(std::unique_ptr<DialogModelField> field)157 void DialogModel::AddField(std::unique_ptr<DialogModelField> field) {
158   fields_.push_back(std::move(field));
159   if (host_)
160     host_->OnFieldAdded(fields_.back().get());
161 }
162 
163 }  // namespace ui