1 module Dgame.Window.MessageBox;
2 
3 private {
4 	import derelict.sdl2.sdl;
5 	
6 	import Dgame.Internal.Log;
7 	import Dgame.Graphics.Color;
8 }
9 
10 private {
11 	SDL_MessageBoxColorScheme _asSDLColorScheme(in MessageBox.Color[] mcols) {
12 		SDL_MessageBoxColorScheme color_scheme;
13 
14 		foreach (ref const MessageBox.Color mcol; mcols) {
15 			SDL_MessageBoxColor sdl_mcol = void;
16 			sdl_mcol.r = mcol.color.red;
17 			sdl_mcol.g = mcol.color.green;
18 			sdl_mcol.b = mcol.color.blue;
19 			
20 			color_scheme.colors[mcol.flag] = sdl_mcol;
21 		}
22 		
23 		return color_scheme;
24 	}
25 	
26 	SDL_MessageBoxButtonData[] _asSDLButton(in MessageBox.Button[] mbuttons) {
27 		SDL_MessageBoxButtonData[] buttons;
28 		buttons.reserve(mbuttons.length);
29 		
30 		foreach (ref const MessageBox.Button mbtn; mbuttons) {
31 			SDL_MessageBoxButtonData button_data = void;
32 			button_data.flags = mbtn.defKey;
33 			button_data.buttonid = mbtn.buttonId;
34 			button_data.text = mbtn.text.ptr;
35 			
36 			buttons ~= button_data;
37 		}
38 		
39 		return buttons;
40 	}
41 }
42 
43 /**
44  * A MessageBox is a short window which present a title and a message.
45  * It is really helpfull to present Exceptions or Errors.
46  * 
47  * Author: rschuett
48  */
49 struct MessageBox {
50 	static struct Color {
51 		.Color color = .Color.White;
52 		int flag;
53 		
54 		enum {
55 			Background = SDL_MESSAGEBOX_COLOR_BACKGROUND,
56 			Text = SDL_MESSAGEBOX_COLOR_TEXT,
57 			ButtonBorder = SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
58 			ButtonBackground = SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
59 			ButtonSelected = SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED
60 		}
61 	}
62 	
63 	static struct Button {
64 		enum DefaultKey {
65 			Return = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, /**< Marks the default button when return is hit */
66 			Escape = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, /**< Marks the default button when escape is hit */
67 		}
68 		
69 		DefaultKey defKey; /** The Default key */
70 		int buttonId = -1; /** User defined button id (value returned via SDL_ShowMessageBox) */
71 		char[16] text = void;  /** The UTF-8 button text */
72 	}
73 	
74 	/**
75 	 * The MessageBox states
76 	 */
77 	enum {
78 		Error = SDL_MESSAGEBOX_ERROR, /// An Error is thrown
79 		Warning = SDL_MESSAGEBOX_WARNING, /// A warning is thrown
80 		Information = SDL_MESSAGEBOX_INFORMATION, /// An information is thrown
81 		
82 		Default = Error /// Default is: Error
83 	}
84 	
85 	string title; /// The Title of the MessageBox
86 	string msg;   /// The Message of the MessageBox
87 	int flag;	  /// The MessageBox Flags. See: MessageBox states enum
88 
89 	/**
90 	 * The Window id where the Error/Warning/Information comes from.
91 	 * Can be get by
92 	 * ----
93 	 * Window wnd = new Window(...);
94 	 * // A lot of code
95 	 * MessageBox(MessageBox.Error, "An Error", "You get an error!", wnd.id);
96 	 * ----
97 	 * Default is -1, which means that the MessageBox is not affiliated to any Window.
98 	 */
99 	int winId = -1;
100 	
101 	Color[] box_colors;
102 	Button[] box_buttons;
103 	
104 	/**
105 	 * CTor
106 	 */
107 	this(int flag, string title, string msg, int wndId = -1) {
108 		this.flag = flag;
109 		this.title = title;
110 		this.msg = msg;
111 		this.winId = wndId;
112 	}
113 	
114 	/**
115 	 * Show the MessageBox.
116 	 * 
117 	 * Example:
118 	 * ----
119 	 * MessageBox(MessageBox.Error, "An Error", "You get an error!").show();
120 	 * ----
121 	 * Or
122 	 * ----
123 	 * MessageBox msgbox = MessageBox(MessageBox.Error, "An Error", "You get an error!");
124 	 * // Some code...
125 	 * msgbox.show();
126 	 * ----
127 	 */
128 	void show() const {
129 		int flag = this.flag;
130 		if (flag < Error || flag > Information)
131 			flag = Default;
132 		
133 		SDL_Window* wnd = null;
134 		if (this.winId != -1)
135 			wnd = SDL_GetWindowFromID(this.winId);
136 		if (wnd is null)
137 			wnd = SDL_GL_GetCurrentWindow();
138 		
139 		int result = -1;
140 		if (this.box_buttons.length == 0 && this.box_colors.length == 0)
141 			result = SDL_ShowSimpleMessageBox(flag, this.title.ptr, this.msg.ptr, wnd);
142 		else {
143 			SDL_MessageBoxData mbd = void;
144 			
145 			mbd.flags = flag;
146 			mbd.window = wnd;
147 			mbd.title = this.title.ptr;
148 			mbd.message = this.msg.ptr;
149 			mbd.numbuttons = cast(int) this.box_buttons.length;
150 			
151 			if (this.box_buttons.length != 0)
152 				mbd.buttons = _asSDLButton(this.box_buttons).ptr;
153 			
154 			if (this.box_colors.length != 0) {
155 				SDL_MessageBoxColorScheme box_color_scheme = _asSDLColorScheme(this.box_colors);
156 				mbd.colorScheme = &box_color_scheme;
157 			}
158 			
159 			result = SDL_ShowMessageBox(&mbd, null);
160 		}
161 		
162 		if (result != 0)
163 			Log.info("MessageBox could not be displayed.");
164 	}
165 }