1 /** 2 * Module for core application handling. 3 * 4 * Authors: 5 * Jacob Jensen 6 * License: 7 * https://github.com/PoisonEngine/poison-ui/blob/master/LICENSE 8 */ 9 module poison.core.application; 10 11 import std.concurrency : thisTid; 12 import core.thread : Thread, dur; 13 14 import poison.ui : Window; 15 import poison.core.threading : _uiTid, receiveMessages; 16 import poison.core.eventobserver; 17 import poison.core.eventargs; 18 19 /// A wrapper around the core application. 20 class Application { 21 private: 22 /// The running application. 23 static Application _app; 24 25 /// The name of the application. 26 string _name; 27 28 /// Collection of windows. 29 Window[string] _windows; 30 31 /// Windows that can be removed. 32 string[] _removableWindows; 33 34 /// Boolean determining whether the application is cycling or not. 35 bool _cycling; 36 37 /// Boolean determining whether the application is open or not. 38 bool _open; 39 40 public: 41 /** 42 * Creates a new application. 43 * Params: 44 * name = The name of the application. 45 */ 46 this(string name) { 47 _name = name; 48 _uiTid = thisTid; 49 } 50 51 @property { 52 /// Gets the name of the application. 53 string name() { return _name; } 54 } 55 56 /// Updates all styles for each window. 57 void updateStyles() { 58 if (_windows) { 59 foreach (window; _windows) { 60 foreach (component; window._windowComponents) { 61 component.updateStyles(); 62 } 63 } 64 } 65 } 66 67 /** 68 * Adds a window to the application. 69 * Params: 70 * window = The window to add. 71 */ 72 void add(Window window) { 73 assert(window !is null); 74 assert(_windows.get(window.name, null) is null); 75 76 _windows[window.name] = window; 77 78 foreach (component; window._windowComponents) { 79 component.updateStyles(); 80 } 81 } 82 83 /** 84 * Removes a window from the application. 85 * Params: 86 * window = The window to remove. 87 */ 88 void remove(Window window) { 89 assert(window !is null); 90 91 remove(window.name); 92 } 93 94 /** 95 * Removes a window from the application. 96 * Params: 97 * name = The name of the window to remove. 98 */ 99 void remove(string name) { 100 assert(_windows.get(name, null) !is null); 101 102 if (_cycling) { 103 _removableWindows ~= name; 104 } 105 else { 106 auto windowToRemove = _windows.get(name, null); 107 108 if (!windowToRemove) { 109 return; 110 } 111 112 if (windowToRemove.isOpen) { 113 windowToRemove.close(); 114 } 115 116 _windows.remove(name); 117 } 118 } 119 120 private: 121 /// Processes the application. 122 void process() { 123 assert(_app !is null); 124 125 _open = true; 126 127 while (_open) { 128 _removableWindows = []; 129 _cycling = true; 130 131 receiveMessages(); 132 133 processWindows(); 134 135 _cycling = false; 136 137 foreach (removableWindow; _removableWindows) { 138 remove(removableWindow); 139 } 140 } 141 } 142 143 /// Processes all windows. 144 void processWindows() { 145 _open = false; 146 147 foreach (window; _windows) { 148 if (window.isOpen) { 149 _open = true; 150 151 window.process(); 152 } 153 } 154 } 155 156 public: 157 static: 158 /** 159 * Initializes a application and then processes it. 160 * Params: 161 * application = The application to initialize and process. 162 */ 163 void initialize(Application application) { 164 assert(_app is null); 165 166 _app = application; 167 168 _app.updateStyles(); 169 EventObserver.fireEventGlobal("applicationStart", EventArgs.empty); 170 _app.process(); 171 EventObserver.fireEventGlobal("applicationEnd", EventArgs.empty); 172 } 173 174 @property { 175 /// Gets the app. 176 Application app() { return _app; } 177 } 178 }