1 /*
2    Copyright (C) 2008 - 2018 by Mark de Wever <koraq@xs4all.nl>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
17 #include "gui/dialogs/message.hpp"
18 
19 #include "gettext.hpp"
20 #include "gui/auxiliary/find_widget.hpp"
21 #include "gui/widgets/button.hpp"
22 #include "gui/widgets/image.hpp"
23 #include "gui/widgets/label.hpp"
24 #include "gui/widgets/settings.hpp"
25 #include "gui/widgets/window.hpp"
26 #include "log.hpp"
27 
28 namespace gui2
29 {
30 namespace dialogs
31 {
32 
33 REGISTER_DIALOG(message)
34 
35 /**
36  * Helper to implement private functions without modifying the header.
37  *
38  * The class is a helper to avoid recompilation and only has static
39  * functions.
40  */
41 struct message_implementation
42 {
43 	/**
44 	 * Initialiazes a button.
45 	 *
46 	 * @param window              The window that contains the button.
47 	 * @param button_status       The button status to modify.
48 	 * @param id                  The id of the button.
49 	 */
init_buttongui2::dialogs::message_implementation50 	static void init_button(window& window,
51 							message::button_status& button_status,
52 							const std::string& id)
53 	{
54 		button_status.ptr = find_widget<button>(&window, id, false, true);
55 		button_status.ptr->set_visible(button_status.visible);
56 
57 		if(!button_status.caption.empty()) {
58 			button_status.ptr->set_label(button_status.caption);
59 		}
60 
61 		if(button_status.retval != retval::NONE) {
62 			button_status.ptr->set_retval(button_status.retval);
63 		}
64 	}
65 };
66 
pre_show(window & window)67 void message::pre_show(window& window)
68 {
69 	set_restore(true);
70 
71 	// ***** Validate the required buttons ***** ***** ***** *****
72 	message_implementation::init_button(window, buttons_[left_1], "left_side");
73 	message_implementation::init_button(window, buttons_[cancel], "cancel");
74 	message_implementation::init_button(window, buttons_[ok], "ok");
75 	message_implementation::init_button(
76 			window, buttons_[right_1], "right_side");
77 
78 	// ***** ***** ***** ***** Set up the widgets ***** ***** ***** *****
79 	styled_widget& title_widget = find_widget<label>(&window, "title", false);
80 	if(!title_.empty()) {
81 		title_widget.set_label(title_);
82 		title_widget.set_use_markup(title_use_markup_);
83 	} else {
84 		title_widget.set_visible(widget::visibility::invisible);
85 	}
86 
87 	styled_widget& img_widget = find_widget<image>(&window, "image", false);
88 	if(!image_.empty()) {
89 		img_widget.set_label(image_);
90 	} else {
91 		img_widget.set_visible(widget::visibility::invisible);
92 	}
93 
94 	styled_widget& label = find_widget<styled_widget>(&window, "label", false);
95 	label.set_label(message_);
96 	label.set_use_markup(message_use_markup_);
97 
98 	// The label might not always be a scroll_label but the capturing
99 	// shouldn't hurt.
100 	window.keyboard_capture(&label);
101 
102 	// Override the user value, to make sure it's set properly.
103 	window.set_click_dismiss(auto_close_);
104 }
105 
post_show(window &)106 void message::post_show(window& /*window*/)
107 {
108 	for(auto & button_status : buttons_)
109 	{
110 		button_status.ptr = nullptr;
111 	}
112 }
113 
set_button_caption(const button_id button,const std::string & caption)114 void message::set_button_caption(const button_id button,
115 								  const std::string& caption)
116 {
117 	buttons_[button].caption = caption;
118 	if(buttons_[button].ptr) {
119 		buttons_[button].ptr->set_label(caption);
120 	}
121 }
122 
set_button_visible(const button_id button,const widget::visibility visible)123 void message::set_button_visible(const button_id button,
124 								  const widget::visibility visible)
125 {
126 	buttons_[button].visible = visible;
127 	if(buttons_[button].ptr) {
128 		buttons_[button].ptr->set_visible(visible);
129 	}
130 }
131 
set_button_retval(const button_id button,const int retval)132 void message::set_button_retval(const button_id button, const int retval)
133 {
134 	buttons_[button].retval = retval;
135 	if(buttons_[button].ptr) {
136 		buttons_[button].ptr->set_retval(retval);
137 	}
138 }
139 
button_status()140 message::button_status::button_status()
141 	: ptr(nullptr)
142 	, caption()
143 	, visible(widget::visibility::invisible)
144 	, retval(gui2::retval::NONE) // Needs explicit namespace qualifier to avoid name clashes.
145 {
146 }
147 
148 } // namespace dialogs
149 
150 using namespace dialogs;
151 
show_message(const std::string & title,const std::string & msg,const std::string & button_caption,const bool auto_close,const bool message_use_markup,const bool title_use_markup)152 void show_message(const std::string& title,
153 				  const std::string& msg,
154 				  const std::string& button_caption,
155 				  const bool auto_close,
156 				  const bool message_use_markup,
157 				  const bool title_use_markup)
158 {
159 	message dlg(title, msg, auto_close, message_use_markup, title_use_markup);
160 	dlg.set_button_caption(message::ok, button_caption);
161 	dlg.show();
162 }
163 
show_message(const std::string & title,const std::string & msg,const message::button_style button_style,bool message_use_markup,bool title_use_markup)164 int show_message(const std::string& title,
165 				 const std::string& msg,
166 				 const message::button_style button_style,
167 				 bool message_use_markup,
168 				 bool title_use_markup)
169 {
170 	message dlg(title,
171 				 msg,
172 				 button_style == message::auto_close,
173 				 message_use_markup,
174 				 title_use_markup);
175 
176 	switch(button_style) {
177 		case message::auto_close:
178 			break;
179 		case message::ok_button:
180 			dlg.set_button_visible(message::ok, widget::visibility::visible);
181 			dlg.set_button_caption(message::ok, _("OK"));
182 			break;
183 		case message::close_button:
184 			dlg.set_button_visible(message::ok, widget::visibility::visible);
185 			break;
186 		case message::ok_cancel_buttons:
187 			dlg.set_button_visible(message::ok, widget::visibility::visible);
188 			dlg.set_button_caption(message::ok, _("OK"));
189 			FALLTHROUGH;
190 		case message::cancel_button:
191 			dlg.set_button_visible(message::cancel, widget::visibility::visible);
192 			break;
193 		case message::yes_no_buttons:
194 			dlg.set_button_visible(message::ok, widget::visibility::visible);
195 			dlg.set_button_caption(message::ok, _("Yes"));
196 			dlg.set_button_visible(message::cancel,  widget::visibility::visible);
197 			dlg.set_button_caption(message::cancel, _("No"));
198 			break;
199 	}
200 
201 	dlg.show();
202 	return dlg.get_retval();
203 }
204 
show_error_message(const std::string & msg,bool message_use_markup)205 void show_error_message(const std::string& msg,
206 						bool message_use_markup)
207 {
208 	LOG_STREAM(err, lg::general()) << msg << '\n';
209 	(void) show_message(
210 				 _("Error"),
211 				 msg,
212 				 message::ok_button,
213 				 message_use_markup);
214 }
215 } // namespace gui2
216