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 }