1 /*
2     Copyright © 2020, Inochi2D Project
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors: Luna Nielsen
6 */
7 module creator.panels;
8 import creator.core;
9 import creator.core.settings;
10 import creator.widgets;
11 import bindbc.imgui;
12 import std.string;
13 import i18n;
14 
15 public import creator.panels.logger;
16 
17 /**
18     A Widget
19 */
20 abstract class Panel {
21 private:
22     string name_;
23     string displayName_;
24     bool defaultVisibility;
25     const(char)* windowID;
26     const(char)* displayNamePtr;
27 
28     bool drewContents;
29     bool wasVisible;
30 
31 protected:
32     ImVec2 panelSpace;
33     abstract void onUpdate();
34     ImGuiWindowFlags flags;
35 
36     void onBeginUpdate() {
37 
38         // Try to begin panel
39         flags |= ImGuiWindowFlags.NoCollapse;
40         drewContents = incBegin(windowID, &visible, flags);
41 
42         // Handle panel visibility settings save for closing tabs
43         // and skipping content draw
44         if (wasVisible != visible) incSettingsSet(name~".visible", visible);
45         if (!drewContents) return;
46 
47         // Setup debug state and such.
48         debug incDebugImGuiState("Panel::onBeginUpdate", 1);
49         igGetContentRegionAvail(&panelSpace);
50     }
51     
52     void onEndUpdate() {
53         debug if (drewContents) incDebugImGuiState("Panel::onEndUpdate", -1);
54         incEnd();
55 
56         wasVisible = visible;
57     }
58 
59     void onInit() { }
60 
61 public:
62 
63     /**
64         Whether the panel is visible
65     */
66     bool visible;
67 
68     /**
69         Whether the panel is always visible
70     */
71     bool alwaysVisible = false;
72 
73     /**
74         Constructs a panel
75     */
76     this(string name, string displayName, bool defaultVisibility) {
77         this.name_ = name;
78         this.displayName_ = displayName;
79         this.visible = defaultVisibility;
80         this.defaultVisibility = defaultVisibility;
81     }
82 
83     /**
84         Initializes the Panel
85     */
86     final void init_() {
87         onInit();
88 
89         // Workaround for the fact that panels are initialized in shared static this
90         this.displayName_ = _(this.displayName_);
91         if (incSettingsCanGet(this.name_~".visible")) {
92             visible = incSettingsGet!bool(this.name_~".visible");
93             wasVisible = visible;
94         }
95 
96         windowID = "%s###%s".format(displayName_, name_).toStringz;
97         displayNamePtr = displayName_.toStringz;
98     }
99 
100     final string name() {
101         return name_;
102     }
103 
104     final string displayName() {
105         return displayName_;
106     }
107 
108     final const(char)* displayNameC() {
109         return displayNamePtr;
110     }
111 
112     /**
113         Draws the panel
114     */
115     final void update() {
116         this.onBeginUpdate();
117             if (drewContents) this.onUpdate();
118         this.onEndUpdate();
119     }
120 
121     final bool getDefaultVisibility() {
122         return defaultVisibility;
123     }
124 }
125 
126 /**
127     Auto generate panel adder
128 */
129 template incPanel(T) {
130     static this() {
131         incAddPanel(new T);
132     }
133 }
134 
135 /**
136     Adds panel to panel list
137 */
138 void incAddPanel(Panel panel) {
139     incPanels ~= panel;
140 }
141 
142 /**
143     Draws panels
144 */
145 void incUpdatePanels() {
146     foreach(panel; incPanels) {
147         if (!panel.visible && !panel.alwaysVisible) continue;
148 
149         panel.update();
150     }
151 }
152 
153 /**
154     Draws panels
155 */
156 void incInitPanels() {
157     foreach(panel; incPanels) {
158         panel.init_();
159     }
160 }
161 
162 /**
163     Panel list
164 */
165 Panel[] incPanels;