1 /*
2 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7 #include "Wt/WApplication.h"
8 #include "Wt/WContainerWidget.h"
9 #include "Wt/WIcon.h"
10 #include "Wt/WImage.h"
11 #include "Wt/WMessageBox.h"
12 #include "Wt/WPushButton.h"
13 #include "Wt/WText.h"
14
15 namespace Wt {
16
17 StandardButton WMessageBox::order_[] = {
18 StandardButton::Ok,
19 StandardButton::Yes,
20 StandardButton::YesAll,
21 StandardButton::Retry,
22 StandardButton::No,
23 StandardButton::NoAll,
24 StandardButton::Abort,
25 StandardButton::Ignore,
26 StandardButton::Cancel
27 };
28
29 const char *WMessageBox::buttonText_[]
30 = { "Wt.WMessageBox.Ok", "Wt.WMessageBox.Yes", "Wt.WMessageBox.YesToAll",
31 "Wt.WMessageBox.Retry", "Wt.WMessageBox.No", "Wt.WMessageBox.NoToAll",
32 "Wt.WMessageBox.Abort", "Wt.WMessageBox.Ignore", "Wt.WMessageBox.Cancel"
33 };
34
WMessageBox()35 WMessageBox::WMessageBox()
36 : icon_(Icon::None),
37 result_(StandardButton::None),
38 defaultButton_(nullptr),
39 escapeButton_(nullptr)
40 {
41 create();
42 }
43
WMessageBox(const WString & caption,const WString & text,Icon icon,WFlags<StandardButton> buttons)44 WMessageBox::WMessageBox(const WString& caption, const WString& text,
45 Icon icon, WFlags<StandardButton> buttons)
46 : WDialog(caption),
47 icon_(Icon::None),
48 defaultButton_(nullptr),
49 escapeButton_(nullptr)
50 {
51 create();
52
53 setText(text);
54 setIcon(icon);
55 setStandardButtons(buttons);
56 }
57
create()58 void WMessageBox::create()
59 {
60 std::unique_ptr<WIcon> icon(iconW_ = new WIcon());
61 contents()->addWidget(std::move(icon));
62
63 std::unique_ptr<WText> text(text_ = new WText());
64 contents()->addWidget(std::move(text));
65
66 contents()->addStyleClass("Wt-msgbox-body");
67
68 rejectWhenEscapePressed();
69
70 finished().connect(this, &WMessageBox::onFinished);
71 }
72
addButton(StandardButton result)73 WPushButton *WMessageBox::addButton(StandardButton result)
74 {
75 return addButton(standardButtonText(result), result);
76 }
77
addButton(const WString & text,StandardButton result)78 WPushButton *WMessageBox::addButton(const WString& text, StandardButton result)
79 {
80 WPushButton *b = new WPushButton(text);
81 addButton(std::unique_ptr<WPushButton>(b), result);
82 return b;
83 }
84
addButton(std::unique_ptr<WPushButton> button,const StandardButton result)85 void WMessageBox::addButton(std::unique_ptr<WPushButton> button,
86 const StandardButton result)
87 {
88 buttons_.push_back(Button());
89 buttons_.back().button = button.get();
90 buttons_.back().result = result;
91
92 button->clicked().connect
93 (this, std::bind(&WMessageBox::onButtonClick, this, result));
94
95 if (button->isDefault())
96 setDefaultButton(button.get());
97
98 footer()->addWidget(std::move(button));
99 }
100
setDefaultButton(WPushButton * button)101 void WMessageBox::setDefaultButton(WPushButton *button)
102 {
103 if (defaultButton_)
104 defaultButton_->setDefault(false);
105 defaultButton_ = button;
106 if (defaultButton_)
107 defaultButton_->setDefault(true);
108 }
109
setDefaultButton(StandardButton button)110 void WMessageBox::setDefaultButton(StandardButton button)
111 {
112 WPushButton *b = this->button(button);
113 if (b)
114 setDefaultButton(b);
115 }
116
setEscapeButton(WPushButton * button)117 void WMessageBox::setEscapeButton(WPushButton *button)
118 {
119 escapeButton_ = button;
120 }
121
setEscapeButton(StandardButton button)122 void WMessageBox::setEscapeButton(StandardButton button)
123 {
124 WPushButton *b = this->button(button);
125 if (b)
126 setEscapeButton(b);
127 }
128
setText(const WString & text)129 void WMessageBox::setText(const WString& text)
130 {
131 text_->setText(text);
132 }
133
text()134 const WString& WMessageBox::text() const
135 {
136 return text_->text();
137 }
138
setIcon(Icon icon)139 void WMessageBox::setIcon(Icon icon)
140 {
141 icon_ = icon;
142
143 iconW_->toggleStyleClass("Wt-msgbox-icon", icon_ != Icon::None);
144 text_->toggleStyleClass("Wt-msgbox-text", icon_ != Icon::None);
145 iconW_->setSize(icon_ != Icon::None ? 2.5 : 1);
146
147 switch (icon_) {
148 case Icon::None:
149 iconW_->setName(std::string());
150 break;
151 case Icon::Information:
152 iconW_->setName("info");
153 break;
154 case Icon::Warning:
155 iconW_->setName("warning");
156 break;
157 case Icon::Critical:
158 iconW_->setName("exclamation");
159 break;
160 case Icon::Question:
161 iconW_->setName("question");
162 }
163 }
164
setStandardButtons(WFlags<StandardButton> buttons)165 void WMessageBox::setStandardButtons(WFlags<StandardButton> buttons)
166 {
167 buttons_.clear();
168 footer()->clear();
169
170 defaultButton_ = escapeButton_ = nullptr;
171
172 for (int i = 0; i < 9; ++i)
173 if (buttons.test(order_[i]))
174 addButton(order_[i]);
175 }
176
standardButtons()177 WFlags<StandardButton> WMessageBox::standardButtons() const
178 {
179 WFlags<StandardButton> result;
180
181 for (unsigned i = 0; i < buttons_.size(); ++i)
182 result |= buttons_[i].result;
183
184 return result;
185 }
186
buttons()187 std::vector<WPushButton *> WMessageBox::buttons() const
188 {
189 std::vector<WPushButton *> result;
190
191 for (unsigned i = 0; i < buttons_.size(); ++i)
192 result.push_back(buttons_[i].button);
193
194 return result;
195 }
196
button(StandardButton b)197 WPushButton *WMessageBox::button(StandardButton b)
198 {
199 for (unsigned i = 0; i < buttons_.size(); ++i)
200 if (buttons_[i].result == b)
201 return buttons_[i].button;
202
203 return nullptr;
204 }
205
onButtonClick(StandardButton b)206 void WMessageBox::onButtonClick(StandardButton b)
207 {
208 result_ = b;
209 buttonClicked_.emit(b);
210 }
211
onFinished()212 void WMessageBox::onFinished()
213 {
214 if (result() == DialogCode::Rejected) {
215 if (escapeButton_) {
216 for (unsigned i = 0; i < buttons_.size(); ++i) {
217 if (buttons_[i].button == escapeButton_) {
218 onButtonClick(buttons_[i].result);
219 return;
220 }
221 }
222 } else {
223 if (buttons_.size() == 1) {
224 onButtonClick(buttons_[0].result);
225 return;
226 } else {
227 WPushButton *b = button(StandardButton::Cancel);
228 if (b) {
229 onButtonClick(StandardButton::Cancel);
230 return;
231 }
232 b = button(StandardButton::No);
233 if (b) {
234 onButtonClick(StandardButton::No);
235 return;
236 }
237
238 onButtonClick(StandardButton::None);
239 }
240 }
241 }
242 }
243
setHidden(bool hidden,const WAnimation & animation)244 void WMessageBox::setHidden(bool hidden, const WAnimation& animation)
245 {
246 if (!hidden) {
247 if (!defaultButton_) {
248 for (unsigned i = 0; i < buttons_.size(); ++i) {
249 if (buttons_[i].result == StandardButton::Ok ||
250 buttons_[i].result == StandardButton::Yes) {
251 buttons_[i].button->setDefault(true);
252 break;
253 }
254 }
255 }
256 }
257
258 WDialog::setHidden(hidden, animation);
259 }
260
show(const WString & caption,const WString & text,WFlags<StandardButton> buttons,const WAnimation & animation)261 StandardButton WMessageBox::show(const WString& caption,
262 const WString& text,
263 WFlags<StandardButton> buttons,
264 const WAnimation& animation)
265 {
266 WMessageBox box(caption, text, Icon::Information, buttons);
267 box.buttonClicked().connect(&box, &WMessageBox::accept);
268 box.exec(animation);
269 return box.buttonResult();
270 }
271
standardButtonText(StandardButton button)272 WString WMessageBox::standardButtonText(StandardButton button)
273 {
274 for (unsigned i = 0; i < 9; ++i)
275 if (order_[i] == button)
276 return tr(buttonText_[i]);
277
278 return WString::Empty;
279 }
280
281 }
282