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.1.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 /++ 65 This should be called once at the start of a program. It generates the proper 66 main function for your environment (win32/posix/dmain) and boot straps the 67 main loop for the GUI. This will call your UIAppMain function when ready. 68 +/ 69 mixin template RUN_MAIN() { 70 // On Windows use the normal dlangui main 71 version (Windows) { 72 import dlangui; 73 mixin APP_ENTRY_POINT; 74 // On Linux use a custom main that checks if SDL is installed 75 } else { 76 int main(string[] args) { 77 // Figure out if the SDL2 libraries can be loaded 78 version (Have_derelict_sdl2) { 79 import derelict.sdl2.sdl : DerelictSDL2, SharedLibVersion, SharedLibLoadException; 80 import message_box : is_sdl2_loadable; 81 try { 82 DerelictSDL2.load(SharedLibVersion(2, 0, 2)); 83 is_sdl2_loadable = true; 84 stdout.writefln("SDL was found ..."); 85 } catch (SharedLibLoadException) { 86 stdout.writefln("SDL was NOT found ..."); 87 } 88 } 89 90 // If SDL2 can be loaded, start the SDL2 main 91 if (is_sdl2_loadable) { 92 import dlangui.platforms.sdl.sdlapp : sdlmain; 93 return sdlmain(args); 94 // If not, use the normal main provided by the user 95 } else { 96 return UIAppMain(args); 97 } 98 } 99 } 100 } 101 102 103 /++ 104 If true will print output of external program to console. 105 Params: 106 is_logging = If true will print to output 107 +/ 108 public void setUseLog(bool is_logging) { 109 use_log = is_logging; 110 } 111 112 /++ 113 Returns if external program logging is on or off. 114 +/ 115 public bool getUseLog() { 116 return use_log; 117 } 118 119 /++ 120 The type of icon to show in the message box. Some message boxes will not show 121 the icon. 122 123 ---- 124 enum IconType { 125 None, 126 Information, 127 Error, 128 Warning, 129 } 130 ---- 131 +/ 132 133 enum IconType { 134 None, 135 Information, 136 Error, 137 Warning, 138 } 139 140 abstract class MessageBoxBase { 141 this(string title, string message, IconType icon_type) { 142 _title = title; 143 _message = message; 144 _icon_type = icon_type; 145 } 146 147 void onError(void delegate(Throwable err) cb) { 148 _on_error_cb = cb; 149 } 150 151 void fireOnError(Throwable err) { 152 auto old_cb = _on_error_cb; 153 _on_error_cb = null; 154 155 if (old_cb) old_cb(err); 156 } 157 158 void show(); 159 160 string _title; 161 string _message; 162 IconType _icon_type; 163 void delegate(Throwable err) _on_error_cb; 164 } 165 166 /++ 167 The MessageBox class 168 +/ 169 class MessageBox { 170 import message_box_dlangui : MessageBoxDlangUI; 171 import message_box_sdl : MessageBoxSDL; 172 import message_box_win32 : MessageBoxWin32; 173 import message_box_zenity : MessageBoxZenity; 174 import message_box_kdialog : MessageBoxKdialog; 175 import message_box_gxmessage : MessageBoxGxmessage; 176 177 /++ 178 Sets up the message box with the desired title, message, and icon. Does not 179 show it until the show method is called. 180 Params: 181 title = The string to show in the message box title 182 message = The string to show in the message box body 183 icon = The type of icon to show in the message box 184 Throws: 185 If it fails to find any programs or libraries to make a message box with. 186 +/ 187 this(string title, string message, IconType icon_type) { 188 if (MessageBoxDlangUI.isSupported()) { 189 _dialog = new MessageBoxDlangUI(title, message, icon_type); 190 } else if (MessageBoxSDL.isSupported()) { 191 _dialog = new MessageBoxSDL(title, message, icon_type); 192 } else if (MessageBoxWin32.isSupported()) { 193 _dialog = new MessageBoxWin32(title, message, icon_type); 194 } else if (MessageBoxZenity.isSupported()) { 195 _dialog = new MessageBoxZenity(title, message, icon_type); 196 } else if (MessageBoxKdialog.isSupported()) { 197 _dialog = new MessageBoxKdialog(title, message, icon_type); 198 } else if (MessageBoxGxmessage.isSupported()) { 199 _dialog = new MessageBoxGxmessage(title, message, icon_type); 200 } else { 201 throw new Exception("Failed to find a way to make a message box."); 202 } 203 } 204 205 /++ 206 This method is called if there is an error when showing the message box. 207 Params: 208 cb = The call back to fire when there is an error. 209 +/ 210 void onError(void delegate(Throwable err) cb) { 211 _dialog._on_error_cb = cb; 212 } 213 214 /++ 215 Shows the message box. Will block until it is closed. 216 +/ 217 void show() { 218 _dialog.show(); 219 } 220 221 MessageBoxBase _dialog; 222 }