]> git.mxchange.org Git - flightgear.git/blob - src/GUI/new_gui.cxx
Instead of reading $FG_ROOT/gui.xml, recursively read all files under
[flightgear.git] / src / GUI / new_gui.cxx
1 // new_gui.cxx: implementation of XML-configurable GUI support.
2
3 #include "new_gui.hxx"
4
5 #include <plib/pu.h>
6 #include <plib/ul.h>
7
8 #include <vector>
9 SG_USING_STD(vector);
10
11 #include <simgear/misc/exception.hxx>
12 #include <Main/fg_props.hxx>
13
14
15 /**
16  * Callback to update all property values.
17  */
18 static void
19 update_callback (puObject * object)
20 {
21     ((NewGUI *)object->getUserData())->updateProperties();
22 }
23
24
25 /**
26  * Callback to close the dialog.
27  */
28 static void
29 close_callback (puObject * object)
30 {
31     ((NewGUI *)object->getUserData())->closeActiveObject();
32 }
33
34
35 /**
36  * Callback to apply the property value for every field.
37  */
38 static void
39 apply_callback (puObject * object)
40 {
41     ((NewGUI *)object->getUserData())->applyProperties();
42     update_callback(object);
43 }
44
45
46 /**
47  * Callback to apply the property values and close the dialog.
48  */
49 static void
50 close_apply_callback (puObject * object)
51 {
52     apply_callback(object);
53     close_callback(object);
54 }
55
56
57
58 NewGUI::NewGUI ()
59     : _activeObject(0)
60 {
61 }
62
63 NewGUI::~NewGUI ()
64 {
65 }
66
67 void
68 NewGUI::init ()
69 {
70     char path[1024];
71     ulMakePath(path, getenv("FG_ROOT"), "gui");
72     std::cerr << "Reading from " << path << std::endl;
73     readDir(path);
74     std::cerr << "Done reading from " << path << std::endl;
75 }
76
77 void
78 NewGUI::update (double delta_time_sec)
79 {
80     // NO OP
81 }
82
83 void
84 NewGUI::display (const string &name)
85 {
86     if (_activeObject != 0) {
87         SG_LOG(SG_GENERAL, SG_ALERT, "Another GUI object is still active");
88         return;
89     }
90
91     if (_objects.find(name) == _objects.end()) {
92         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
93         return;
94     }
95     SGPropertyNode_ptr props = _objects[name];
96     
97     _activeObject = makeObject(props, 1024, 768);
98
99     if (_activeObject != 0) {
100         _activeObject->reveal();
101     } else {
102         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name
103                << " does not contain a proper GUI definition");
104     }
105 }
106
107 void
108 NewGUI::applyProperties ()
109 {
110     for (int i = 0; i < _propertyObjects.size(); i++) {
111         puObject * object = _propertyObjects[i].object;
112         SGPropertyNode_ptr node = _propertyObjects[i].node;
113         node->setStringValue(object->getStringValue());
114     }
115 }
116
117 void
118 NewGUI::updateProperties ()
119 {
120     for (int i = 0; i < _propertyObjects.size(); i++) {
121         puObject * object = _propertyObjects[i].object;
122         SGPropertyNode_ptr node = _propertyObjects[i].node;
123         object->setValue(node->getStringValue());
124     }
125 }
126
127 void
128 NewGUI::closeActiveObject ()
129 {
130     delete _activeObject;
131     _activeObject = 0;
132     _propertyObjects.clear();
133 }
134
135 void
136 NewGUI::readDir (const char * path)
137 {
138     ulDir * dir = ulOpenDir(path);
139     std::cerr << "Directory opened successfully" << std::endl;
140
141     if (dir == 0) {
142         SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
143                << path);
144         return;
145     }
146
147     ulDirEnt * dirEnt = ulReadDir(dir);
148     while (dirEnt != 0) {
149         char subpath[1024];
150
151         ulMakePath(subpath, path, dirEnt->d_name);
152
153         std::cerr << "Subpath is " << subpath << std::endl;
154         if (dirEnt->d_isdir && dirEnt->d_name[0] != '.') {
155             readDir(subpath);
156         } else {
157             SGPropertyNode_ptr props = new SGPropertyNode;
158             try {
159                 readProperties(subpath, props);
160             } catch (const sg_exception &ex) {
161                 SG_LOG(SG_INPUT, SG_ALERT, "Error parsing GUI file "
162                        << subpath);
163             }
164             if (!props->hasValue("name")) {
165                 SG_LOG(SG_INPUT, SG_WARN, "GUI file " << subpath
166                    << " has no name; skipping.");
167             } else {
168                 string name = props->getStringValue("name");
169                 SG_LOG(SG_INPUT, SG_BULK, "Saving GUI node " << name);
170                 _objects[name] = props;
171             }
172         }
173         dirEnt = ulReadDir(dir);
174     }
175     ulCloseDir(dir);
176 }
177
178 puObject *
179 NewGUI::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
180 {
181     int width = props->getIntValue("width", parentWidth);
182     int height = props->getIntValue("height", parentHeight);
183
184     int x = props->getIntValue("x", (parentWidth - width) / 2);
185     int y = props->getIntValue("y", (parentHeight - height) / 2);
186
187     string type = props->getName();
188     if (type == "")
189         type = props->getStringValue("type");
190     if (type == "") {
191         SG_LOG(SG_GENERAL, SG_ALERT, "No type specified for GUI object");
192         return 0;
193     }
194
195     if (type == "dialog") {
196         puPopup * dialog;
197         if (props->getBoolValue("modal", false))
198             dialog = new puDialogBox(x, y);
199         else
200             dialog = new puPopup(x, y);
201         setupGroup(dialog, props, width, height, true);
202         return dialog;
203     } else if (type == "group") {
204         puGroup * group = new puGroup(x, y);
205         setupGroup(group, props, width, height, false);
206         return group;
207     } else if (type == "input") {
208         puInput * input = new puInput(x, y, x + width, y + height);
209         setupObject(input, props);
210         return input;
211     } else if (type == "text") {
212         puText * text = new puText(x, y);
213         setupObject(text, props);
214         return text;
215     } else if (type == "button") {
216         puButton * b;
217         const char * legend = props->getStringValue("legend", "[none]");
218         if (props->getBoolValue("one-shot", true))
219             b = new puOneShot(x, y, legend);
220         else
221             b = new puButton(x, y, legend);
222         setupObject(b, props);
223         return b;
224     } else {
225         return 0;
226     }
227 }
228
229 void
230 NewGUI::setupObject (puObject * object, SGPropertyNode * props)
231 {
232     object->setUserData(this);
233
234     if (props->hasValue("legend"))
235         object->setLegend(props->getStringValue("legend"));
236
237     if (props->hasValue("label"))
238         object->setLabel(props->getStringValue("label"));
239
240     if (props->hasValue("default-value-prop")) {
241         const char * name = props->getStringValue("default-value-prop");
242         SGPropertyNode_ptr node = fgGetNode(name, true);
243         object->setValue(node->getStringValue());
244         _propertyObjects.push_back(PropertyObject(object, node));
245     }
246
247     if (props->hasValue("action")) {
248         string action = props->getStringValue("action");
249         if (action == "update")
250             object->setCallback(update_callback);
251         else if (action == "close")
252             object->setCallback(close_callback);
253         else if (action == "apply")
254             object->setCallback(apply_callback);
255         else if (action == "close-apply")
256             object->setCallback(close_apply_callback);
257         else
258             SG_LOG(SG_GENERAL, SG_ALERT, "Unknown GUI action " + action);
259     }
260
261     object->makeReturnDefault(props->getBoolValue("default"));
262 }
263
264 void
265 NewGUI::setupGroup (puGroup * group, SGPropertyNode * props,
266                     int width, int height, bool makeFrame)
267 {
268     setupObject(group, props);
269
270     if (makeFrame)
271         new puFrame(0, 0, width, height);
272
273     int nChildren = props->nChildren();
274     for (int i = 0; i < nChildren; i++)
275         makeObject(props->getChild(i), width, height);
276     group->close();
277 }
278
279 NewGUI::PropertyObject::PropertyObject (puObject * o, SGPropertyNode_ptr n)
280     : object(o),
281       node(n)
282 {
283 }
284
285 // end of new_gui.cxx