1 /**
2  * Dialog module.
3  *
4  * License:
5  *     MIT. See LICENSE for full details.
6  */
7 module tkd.window.dialog.messagedialog;
8 
9 /**
10  * Imports.
11  */
12 import std.regex;
13 import tkd.window.dialog.dialog;
14 import tkd.window.window;
15 
16 /**
17  * Pops up a dialog box with a user defined message and buttons.
18  *
19  * Example:
20  * ---
21  * auto dialog = new MessageDialog("Save file?")
22  * 	.setIcon(MessageDialogIcon.question)
23  * 	.setMessage("Do you want to save this file?")
24  * 	.setType(MessageDialogType.okcancel)
25  * 	.show();
26  *
27  * string buttonClicked = dialog.getResult();
28  * ---
29  *
30  * Result:
31  *     The symbolic name of the button pressed.
32  *
33  * See_Also:
34  *     $(LINK2 ./dialog.html, tkd.dialog.dialog) $(BR)
35  */
36 class MessageDialog : Dialog
37 {
38 	/**
39 	 * The symbolic name of the default button for this message window ('ok', 
40 	 * 'cancel', and so on).
41 	 */
42 	private string _defaultButton;
43 
44 	/**
45 	 * Specifies an auxiliary message to the main message.
46 	 */
47 	private string _detailMessage;
48 
49 	/**
50 	 * Specifies an icon to display.
51 	 */
52 	private string _icon = MessageDialogIcon.info;
53 
54 	/**
55 	 * Specifies the message to display in this message box.
56 	 */
57 	private string _message;
58 
59 	/**
60 	 * Arranges for a predefined set of buttons to be displayed.
61 	 */
62 	private string _type = MessageDialogType.ok;
63 
64 	/**
65 	 * Construct the dialog.
66 	 *
67 	 * Params:
68 	 *     parent = The parent window of the dialog.
69 	 *     title = The title of the dialog.
70 	 */
71 	this(Window parent, string title = "Information")
72 	{
73 		super(parent, title);
74 	}
75 
76 	/**
77 	 * Construct the dialog.
78 	 *
79 	 * Params:
80 	 *     title = The title of the dialog.
81 	 */
82 	this(string title = "Information")
83 	{
84 		this(null, title);
85 	}
86 
87 	/**
88 	 * Set the default button.
89 	 *
90 	 * Params:
91 	 *     button = The default button to use.
92 	 *
93 	 * Returns:
94 	 *     This dialog to aid method chaining.
95 	 *
96 	 * See_Also:
97 	 *     $(LINK2 ./messagedialog.html#MessageDialogButton, tkd.dialog.messagedialog.MessageDialogButton) $(BR)
98 	 */
99 	public auto setDefaultButton(this T)(string button)
100 	{
101 		this._defaultButton = button;
102 
103 		return cast(T) this;
104 	}
105 
106 	/**
107 	 * Set the detail message. The message detail will be presented beneath the 
108 	 * main message and, where supported by the OS, in a less emphasized font 
109 	 * than the main message.
110 	 *
111 	 * Params:
112 	 *     message = The detail message.
113 	 *
114 	 * Returns:
115 	 *     This dialog to aid method chaining.
116 	 */
117 	public auto setDetailMessage(this T)(string message)
118 	{
119 		this._detailMessage = message;
120 
121 		return cast(T) this;
122 	}
123 
124 	/**
125 	 * Set the preset dialog icon. It must be one of the following: error, 
126 	 * info, question or warning.
127 	 *
128 	 * Params:
129 	 *     icon = The preset dialog icon.
130 	 *
131 	 * Returns:
132 	 *     This dialog to aid method chaining.
133 	 *
134 	 * See_Also:
135 	 *     $(LINK2 ./messagedialog.html#MessageDialogIcon, tkd.dialog.messagedialog.MessageDialogIcon) $(BR)
136 	 */
137 	public auto setIcon(this T)(string icon)
138 	{
139 		this._icon = icon;
140 
141 		return cast(T) this;
142 	}
143 
144 	/**
145 	 * Set the main message to display in the message dialog.
146 	 *
147 	 * Params:
148 	 *     message = The message.
149 	 *
150 	 * Returns:
151 	 *     This dialog to aid method chaining.
152 	 */
153 	public auto setMessage(this T)(string message)
154 	{
155 		this._message = message;
156 
157 		return cast(T) this;
158 	}
159 
160 	/**
161 	 * Set the message dialog type. Arranges for a predefined set of buttons to 
162 	 * be displayed.
163 	 *
164 	 * Params:
165 	 *     type = The type of the message dialog.
166 	 *
167 	 * Returns:
168 	 *     This dialog to aid method chaining.
169 	 *
170 	 * See_Also:
171 	 *     $(LINK2 ./messagedialog.html#MessageDialogType, tkd.dialog.messagedialog.MessageDialogType) $(BR)
172 	 */
173 	public auto setType(this T)(string type)
174 	{
175 		this._type = type;
176 
177 		return cast(T) this;
178 	}
179 
180 	/**
181 	 * Check the default button and if not set, set it.
182 	 */
183 	private void checkDefaultButton()
184 	{
185 		if (!this._defaultButton)
186 		{
187 			switch(this._type)
188 			{
189 				case MessageDialogType.abortretryignore:
190 					this._defaultButton = MessageDialogButton.abort;
191 					break;
192 
193 				case MessageDialogType.retrycancel:
194 					this._defaultButton = MessageDialogButton.retry;
195 					break;
196 
197 				case MessageDialogType.yesno:
198 				case MessageDialogType.yesnocancel:
199 					this._defaultButton = MessageDialogButton.yes;
200 					break;
201 
202 				default:
203 					this._defaultButton = MessageDialogButton.ok;
204 					break;
205 			}
206 		}
207 	}
208 
209 	/**
210 	 * Show the dialog.
211 	 *
212 	 * Returns:
213 	 *     This dialog to aid method chaining.
214 	 */
215 	public auto show(this T)()
216 	{
217 		this.checkDefaultButton();
218 
219 		if (this._parent)
220 		{
221 			this._tk.eval("tk_messageBox -parent %s -title {%s} -default {%s} -detail {%s} -icon {%s} -message {%s} -type {%s}", this._parent.id, this._title, this._defaultButton, this._detailMessage, this._icon, this._message, this._type);
222 		}
223 		else
224 		{
225 			this._tk.eval("tk_messageBox -title {%s} -default {%s} -detail {%s} -icon {%s} -message {%s} -type {%s}", this._title, this._defaultButton, this._detailMessage, this._icon, this._message, this._type);
226 		}
227 
228 		this._results = [this._tk.getResult!(string)];
229 
230 		return cast(T) this;
231 	}
232 }
233 
234 /**
235  * Symbolic names for message dialog buttons.
236  */
237 enum MessageDialogButton : string
238 {
239 	abort  = "abort",  /// The 'abort' button.
240 	cancel = "cancel", /// The 'cancel' button.
241 	ignore = "ignore", /// The 'ignore' button.
242 	no     = "no",     /// The 'no' button.
243 	ok     = "ok",     /// The 'ok' button.
244 	retry  = "retry",  /// The 'retry' button.
245 	yes    = "yes",    /// The 'yes' button.
246 }
247 
248 /**
249  * Preset icons used for the message dialog.
250  */
251 enum MessageDialogIcon : string
252 {
253 	error    = "error",    /// An error icon.
254 	info     = "info",     /// An information icon
255 	question = "question", /// A question icon.
256 	warning  = "warning",  /// A warning icon.
257 }
258 
259 /**
260  * Arranges for a predefined set of buttons to be displayed. The following 
261  * values are possible for predefinedType:
262  */
263 enum MessageDialogType : string
264 {
265 	abortretryignore = "abortretryignore", /// Displays three buttons whose symbolic names are abort, retry and ignore.
266 	ok               = "ok",               /// Displays one button whose symbolic name is ok.
267 	okcancel         = "okcancel",         /// Displays two buttons whose symbolic names are ok and cancel.
268 	retrycancel      = "retrycancel",      /// Displays two buttons whose symbolic names are retry and cancel.
269 	yesno            = "yesno",            /// Displays two buttons whose symbolic names are yes and no.
270 	yesnocancel      = "yesnocancel",      /// Displays three buttons whose symbolic names are yes, no and cancel.
271 }