1 /**
2     Gui Modal
3 
4     Copyright: (c) Enalye 2017
5     License: Zlib
6     Authors: Enalye
7 */
8 
9 module atelier.ui.gui_modal;
10 import atelier.core, atelier.render, atelier.common;
11 import atelier.ui.gui_element, atelier.ui.layout, atelier.ui.label,
12     atelier.ui.button, atelier.ui.gui_manager;
13 
14 private {
15     GuiElement[][] _backups;
16     GuiElement[] _modalElements;
17     GuiElement _modalElement;
18     bool _isModal = false;
19 }
20 
21 /// Set a gui as a modal gui.
22 /// ___
23 /// It will have exclusive access to events and be rendered above all other guis.
24 void pushModal(GuiElement modalGui) {
25     if (_isModal) {
26         _modalElements ~= _modalElement;
27     }
28     _isModal = true;
29     _backups ~= getRoots();
30     removeRoots();
31     _modalElement = modalGui;
32     appendRoot(_modalElement);
33 }
34 
35 /// Does a modal gui is currently being run ?
36 bool isModal() {
37     return _isModal;
38 }
39 
40 /// Get and stop the current modal.
41 T popModal(T)() {
42     T convModal = getModal!T();
43     stopModal();
44     return convModal;
45 }
46 
47 /// Get the modal currently running.
48 private T getModal(T)() {
49     if (_modalElement is null)
50         throw new Exception("Modal: No window instanciated");
51     T convModal = cast(T) _modalElement;
52     if (convModal is null)
53         throw new Exception("Modal: Type error");
54     return convModal;
55 }
56 
57 /// Immediately stops the currently running modal gui.
58 void stopModal() {
59     removeRoots();
60     if (_modalElement is null)
61         throw new Exception("Modal: No window instanciated");
62     setRoots(_backups[$ - 1]);
63     _backups.length--;
64     if (_modalElements.length) {
65         _modalElement = _modalElements[$ - 1];
66         _modalElements.length--;
67     }
68     else {
69         _isModal = false;
70     }
71 }
72 
73 /// Close everything
74 package(atelier) void stopAllModals() {
75     while (_isModal) {
76         stopModal();
77     }
78 }
79 
80 /// Update and render the gui that aren't modals while the modal gui is active.
81 package(atelier) void processModalBack() {
82     foreach (backup; _backups) {
83         foreach (GuiElement gui; backup) {
84             updateRoots(gui, null);
85             drawRoots(gui);
86         }
87     }
88 }