1 // Copyright (c) 2017 Matthew Brennan Jones <matthew.brennan.jones@gmail.com> 2 // Boost Software License - Version 1.0 3 // A simple message box for the D programming language 4 // https://github.com/workhorsy/d-message-box 5 6 7 /++ 8 A simple message box for the D programming language 9 10 It should work without requiring any 3rd party GUI toolkits. But will work with what 11 it can find on your OS at runtime. 12 13 It tries to use the following: 14 15 * DlangUI (win32 on Windows or SDL2 on Linux) 16 17 * SDL_ShowSimpleMessageBox (Derelict SDL2) 18 19 * MessageBoxW (Windows) 20 21 * Zenity (Gtk/Gnome) 22 23 * Kdialog (KDE) 24 25 * gxmessage (X11) 26 27 Home page: 28 $(LINK https://github.com/workhorsy/d-message-box) 29 30 Version: 0.3.0 31 32 License: 33 Boost Software License - Version 1.0 34 35 Examples: 36 ---- 37 import std.stdio : stdout, stderr; 38 import message_box : MessageBox, IconType, RUN_MAIN; 39 40 mixin RUN_MAIN; 41 42 extern (C) int UIAppMain(string[] args) { 43 // Create the message box 44 auto dialog = new MessageBox("Party Time", "The roof is on fire!", IconType.Warning); 45 46 // Set the error handler 47 dialog.onError((Throwable err) { 48 stderr.writefln("Failed to show message box: %s", err); 49 }); 50 51 // Show the message box 52 dialog.show(); 53 54 return 0; 55 } 56 ---- 57 +/ 58 59 module message_box; 60 61 bool is_sdl2_loadable = false; 62 bool use_log = false; 63 64 static this() { 65 import std.stdio : stdout; 66 67 // Figure out if the SDL2 libraries can be loaded 68 version (Have_derelict_sdl2) { 69 import derelict.sdl2.sdl : DerelictSDL2, SharedLibVersion, SharedLibLoadException; 70 try { 71 DerelictSDL2.load(SharedLibVersion(2, 0, 2)); 72 is_sdl2_loadable = true; 73 stdout.writefln("SDL was found ..."); 74 } catch (SharedLibLoadException) { 75 stdout.writefln("SDL was NOT found ..."); 76 } 77 } 78 } 79 80 /++ 81 This should be called once at the start of a program. It generates the proper 82 main function for your environment (win32/posix/dmain) and boot straps the 83 main loop for the GUI. This will call your UIAppMain function when ready. 84 +/ 85 mixin template RUN_MAIN() { 86 version (unittest) { } else { 87 // On Windows use the normal dlangui main 88 version (Windows) { 89 import dlangui; 90 mixin APP_ENTRY_POINT; 91 // On Linux use a custom main that checks if SDL is installed 92 } else { 93 int main(string[] args) { 94 import message_box : is_sdl2_loadable; 95 // If SDL2 can be loaded, start the SDL2 main 96 if (is_sdl2_loadable) { 97 import dlangui.platforms.sdl.sdlapp : sdlmain; 98 return sdlmain(args); 99 // If not, use the normal main provided by the user 100 } else { 101 return UIAppMain(args); 102 } 103 } 104 } 105 } 106 } 107 108 109 /++ 110 If true will print output of external program to console. 111 Params: 112 is_logging = If true will print to output 113 +/ 114 public void setUseLog(bool is_logging) { 115 use_log = is_logging; 116 } 117 118 /++ 119 Returns if external program logging is on or off. 120 +/ 121 public bool getUseLog() { 122 return use_log; 123 } 124 125 /++ 126 The type of icon to show in the message box. Some message boxes will not show 127 the icon. 128 129 ---- 130 enum IconType { 131 None, 132 Information, 133 Error, 134 Warning, 135 } 136 ---- 137 +/ 138 139 enum IconType { 140 None, 141 Information, 142 Error, 143 Warning, 144 } 145 146 abstract class MessageBoxBase { 147 this(string title, string message, IconType icon_type) { 148 _title = title; 149 _message = message; 150 _icon_type = icon_type; 151 } 152 153 void onError(void delegate(Throwable err) cb) { 154 _on_error_cb = cb; 155 } 156 157 void fireOnError(Throwable err) { 158 auto old_cb = _on_error_cb; 159 _on_error_cb = null; 160 161 if (old_cb) old_cb(err); 162 } 163 164 void show(); 165 166 string _title; 167 string _message; 168 IconType _icon_type; 169 void delegate(Throwable err) _on_error_cb; 170 } 171 172 /++ 173 The MessageBox class 174 +/ 175 class MessageBox { 176 import message_box_dlangui : MessageBoxDlangUI; 177 import message_box_sdl : MessageBoxSDL; 178 import message_box_win32 : MessageBoxWin32; 179 import message_box_zenity : MessageBoxZenity; 180 import message_box_kdialog : MessageBoxKdialog; 181 import message_box_gxmessage : MessageBoxGxmessage; 182 183 /++ 184 Sets up the message box with the desired title, message, and icon. Does not 185 show it until the show method is called. 186 Params: 187 title = The string to show in the message box title 188 message = The string to show in the message box body 189 icon = The type of icon to show in the message box 190 Throws: 191 If it fails to find any programs or libraries to make a message box with. 192 +/ 193 this(string title, string message, IconType icon_type) { 194 if (MessageBoxDlangUI.isSupported()) { 195 _dialog = new MessageBoxDlangUI(title, message, icon_type); 196 } else if (MessageBoxSDL.isSupported()) { 197 _dialog = new MessageBoxSDL(title, message, icon_type); 198 } else if (MessageBoxWin32.isSupported()) { 199 _dialog = new MessageBoxWin32(title, message, icon_type); 200 } else if (MessageBoxZenity.isSupported()) { 201 _dialog = new MessageBoxZenity(title, message, icon_type); 202 } else if (MessageBoxKdialog.isSupported()) { 203 _dialog = new MessageBoxKdialog(title, message, icon_type); 204 } else if (MessageBoxGxmessage.isSupported()) { 205 _dialog = new MessageBoxGxmessage(title, message, icon_type); 206 } else { 207 throw new Exception("Failed to find a way to make a message box."); 208 } 209 } 210 211 /++ 212 This method is called if there is an error when showing the message box. 213 Params: 214 cb = The call back to fire when there is an error. 215 +/ 216 void onError(void delegate(Throwable err) cb) { 217 _dialog._on_error_cb = cb; 218 } 219 220 /++ 221 Shows the message box. Will block until it is closed. 222 +/ 223 void show() { 224 _dialog.show(); 225 } 226 227 MessageBoxBase _dialog; 228 }