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