]> git.mxchange.org Git - flightgear.git/blob - src/GUI/new_gui.cxx
Removed debugging statements accidentally left in.
[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 \f
16 ////////////////////////////////////////////////////////////////////////
17 // Callbacks.
18 ////////////////////////////////////////////////////////////////////////
19
20 /**
21  * Action callback.
22  */
23 static void
24 action_callback (puObject * object)
25 {
26     GUIInfo * info = (GUIInfo *)object->getUserData();
27     NewGUI * gui =
28         (NewGUI *)globals->get_subsystem_mgr()
29           ->get_group(FGSubsystemMgr::INIT)->get_subsystem("gui");
30     gui->setCurrentWidget(info->widget);
31     for (int i = 0; i < info->bindings.size(); i++)
32         info->bindings[i]->fire();
33     gui->setCurrentWidget(0);
34 }
35
36
37 \f
38 ////////////////////////////////////////////////////////////////////////
39 // Implementation of GUIInfo.
40 ////////////////////////////////////////////////////////////////////////
41
42 GUIInfo::GUIInfo (GUIWidget * w)
43     : widget(w)
44 {
45 }
46
47 GUIInfo::~GUIInfo ()
48 {
49     for (int i = 0; i < bindings.size(); i++) {
50         delete bindings[i];
51         bindings[i] = 0;
52     }
53 }
54
55
56 \f
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of GUIWidget.
59 ////////////////////////////////////////////////////////////////////////
60
61 GUIWidget::GUIWidget (SGPropertyNode_ptr props)
62     : _object(0)
63 {
64     display(props);
65 }
66
67 GUIWidget::~GUIWidget ()
68 {
69     delete _object;
70
71     int i;
72     for (i = 0; i < _info.size(); i++) {
73         delete _info[i];
74         _info[i] = 0;
75     }
76
77     for (i = 0; i < _propertyObjects.size(); i++) {
78         delete _propertyObjects[i];
79         _propertyObjects[i] = 0;
80     }
81 }
82
83 void
84 GUIWidget::updateValue (const char * objectName)
85 {
86     for (int i = 0; i < _propertyObjects.size(); i++) {
87         if (_propertyObjects[i]->name == objectName)
88             _propertyObjects[i]->object
89                 ->setValue(_propertyObjects[i]->node->getStringValue());
90     }
91 }
92
93 void
94 GUIWidget::applyValue (const char * objectName)
95 {
96     for (int i = 0; i < _propertyObjects.size(); i++) {
97         if (_propertyObjects[i]->name == objectName)
98             _propertyObjects[i]->node
99                 ->setStringValue(_propertyObjects[i]
100                                  ->object->getStringValue());
101     }
102 }
103
104 void
105 GUIWidget::updateValues ()
106 {
107     for (int i = 0; i < _propertyObjects.size(); i++) {
108         puObject * object = _propertyObjects[i]->object;
109         SGPropertyNode_ptr node = _propertyObjects[i]->node;
110         object->setValue(node->getStringValue());
111     }
112 }
113
114 void
115 GUIWidget::applyValues ()
116 {
117     for (int i = 0; i < _propertyObjects.size(); i++) {
118         puObject * object = _propertyObjects[i]->object;
119         SGPropertyNode_ptr node = _propertyObjects[i]->node;
120         node->setStringValue(object->getStringValue());
121     }
122 }
123
124 void
125 GUIWidget::display (SGPropertyNode_ptr props)
126 {
127     if (_object != 0) {
128         SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active");
129         return;
130     }
131
132     _object = makeObject(props, 1024, 768);
133
134     if (_object != 0) {
135         _object->reveal();
136     } else {
137         SG_LOG(SG_GENERAL, SG_ALERT, "Widget "
138                << props->getStringValue("name", "[unnamed]")
139                << " does not contain a proper GUI definition");
140     }
141 }
142
143 puObject *
144 GUIWidget::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
145 {
146     int width = props->getIntValue("width", parentWidth);
147     int height = props->getIntValue("height", parentHeight);
148
149     int x = props->getIntValue("x", (parentWidth - width) / 2);
150     int y = props->getIntValue("y", (parentHeight - height) / 2);
151
152     string type = props->getName();
153     if (type == "")
154         type = props->getStringValue("type");
155     if (type == "") {
156         SG_LOG(SG_GENERAL, SG_ALERT, "No type specified for GUI object");
157         return 0;
158     }
159
160     if (type == "dialog") {
161         puPopup * dialog;
162         if (props->getBoolValue("modal", false))
163             dialog = new puDialogBox(x, y);
164         else
165             dialog = new puPopup(x, y);
166         setupGroup(dialog, props, width, height, true);
167         return dialog;
168     } else if (type == "group") {
169         puGroup * group = new puGroup(x, y);
170         setupGroup(group, props, width, height, false);
171         return group;
172     } else if (type == "input") {
173         puInput * input = new puInput(x, y, x + width, y + height);
174         setupObject(input, props);
175         return input;
176     } else if (type == "text") {
177         puText * text = new puText(x, y);
178         setupObject(text, props);
179         return text;
180     } else if (type == "button") {
181         puButton * b;
182         const char * legend = props->getStringValue("legend", "[none]");
183         if (props->getBoolValue("one-shot", true))
184             b = new puOneShot(x, y, legend);
185         else
186             b = new puButton(x, y, legend);
187         setupObject(b, props);
188         return b;
189     } else {
190         return 0;
191     }
192 }
193
194 void
195 GUIWidget::setupObject (puObject * object, SGPropertyNode * props)
196 {
197     if (props->hasValue("legend"))
198         object->setLegend(props->getStringValue("legend"));
199
200     if (props->hasValue("label"))
201         object->setLabel(props->getStringValue("label"));
202
203     if (props->hasValue("property")) {
204         const char * name = props->getStringValue("name");
205         if (name == 0)
206             name = "";
207         const char * propname = props->getStringValue("property");
208         SGPropertyNode_ptr node = fgGetNode(propname, true);
209         object->setValue(node->getStringValue());
210         if (name != 0)
211             _propertyObjects.push_back(new PropertyObject(name, object, node));
212     }
213
214     vector<SGPropertyNode_ptr> nodes = props->getChildren("binding");
215     if (nodes.size() > 0) {
216         GUIInfo * info = new GUIInfo(this);
217
218         for (int i = 0; i < nodes.size(); i++)
219             info->bindings.push_back(new FGBinding(nodes[i]));
220         object->setCallback(action_callback);
221         object->setUserData(info);
222         _info.push_back(info);
223     }
224
225     object->makeReturnDefault(props->getBoolValue("default"));
226 }
227
228 void
229 GUIWidget::setupGroup (puGroup * group, SGPropertyNode * props,
230                     int width, int height, bool makeFrame)
231 {
232     setupObject(group, props);
233
234     if (makeFrame)
235         new puFrame(0, 0, width, height);
236
237     int nChildren = props->nChildren();
238     for (int i = 0; i < nChildren; i++)
239         makeObject(props->getChild(i), width, height);
240     group->close();
241 }
242
243 GUIWidget::PropertyObject::PropertyObject (const char * n,
244                                            puObject * o,
245                                            SGPropertyNode_ptr p)
246     : name(n),
247       object(o),
248       node(p)
249 {
250 }
251
252
253 \f
254 ////////////////////////////////////////////////////////////////////////
255 // Implementation of NewGUI.
256 ////////////////////////////////////////////////////////////////////////
257
258
259 NewGUI::NewGUI ()
260     : _current_widget(0)
261 {
262 }
263
264 NewGUI::~NewGUI ()
265 {
266 }
267
268 void
269 NewGUI::init ()
270 {
271     char path[1024];
272     ulMakePath(path, getenv("FG_ROOT"), "gui");
273     readDir(path);
274 }
275
276 void
277 NewGUI::update (double delta_time_sec)
278 {
279     // NO OP
280 }
281
282 void
283 NewGUI::display (const string &name)
284 {
285     if (_widgets.find(name) == _widgets.end())
286         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
287     else
288         new GUIWidget(_widgets[name]);
289 }
290
291 void
292 NewGUI::setCurrentWidget (GUIWidget * widget)
293 {
294     _current_widget = widget;
295 }
296
297 GUIWidget *
298 NewGUI::getCurrentWidget ()
299 {
300     return _current_widget;
301 }
302
303 void
304 NewGUI::readDir (const char * path)
305 {
306     ulDir * dir = ulOpenDir(path);
307
308     if (dir == 0) {
309         SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
310                << path);
311         return;
312     }
313
314     ulDirEnt * dirEnt = ulReadDir(dir);
315     while (dirEnt != 0) {
316         char subpath[1024];
317
318         ulMakePath(subpath, path, dirEnt->d_name);
319
320         if (dirEnt->d_isdir && dirEnt->d_name[0] != '.') {
321             readDir(subpath);
322         } else {
323             SGPropertyNode_ptr props = new SGPropertyNode;
324             try {
325                 readProperties(subpath, props);
326             } catch (const sg_exception &ex) {
327                 SG_LOG(SG_INPUT, SG_ALERT, "Error parsing GUI file "
328                        << subpath);
329             }
330             if (!props->hasValue("name")) {
331                 SG_LOG(SG_INPUT, SG_WARN, "GUI file " << subpath
332                    << " has no name; skipping.");
333             } else {
334                 string name = props->getStringValue("name");
335                 SG_LOG(SG_INPUT, SG_BULK, "Saving GUI node " << name);
336                 _widgets[name] = props;
337             }
338         }
339         dirEnt = ulReadDir(dir);
340     }
341     ulCloseDir(dir);
342 }
343
344 // end of new_gui.cxx