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