]> git.mxchange.org Git - flightgear.git/blob - src/GUI/dialog.cxx
Add support for a "checkbox" dialog widget (for boolean properties).
[flightgear.git] / src / GUI / dialog.cxx
1 // dialog.cxx: implementation of an XML-configurable dialog box.
2
3 #include <Input/input.hxx>
4
5 #include "dialog.hxx"
6 #include "new_gui.hxx"
7
8
9 \f
10 ////////////////////////////////////////////////////////////////////////
11 // Callbacks.
12 ////////////////////////////////////////////////////////////////////////
13
14 /**
15  * Action callback.
16  */
17 static void
18 action_callback (puObject * object)
19 {
20     GUIInfo * info = (GUIInfo *)object->getUserData();
21     NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
22     gui->setCurrentWidget(info->widget);
23     for (int i = 0; i < info->bindings.size(); i++)
24         info->bindings[i]->fire();
25     gui->setCurrentWidget(0);
26 }
27
28
29 \f
30 ////////////////////////////////////////////////////////////////////////
31 // Static helper functions.
32 ////////////////////////////////////////////////////////////////////////
33
34 /**
35  * Copy a property value to a PUI object.
36  */
37 static void
38 copy_to_pui (SGPropertyNode * node, puObject * object)
39 {
40     switch (node->getType()) {
41     case SGPropertyNode::BOOL:
42     case SGPropertyNode::INT:
43     case SGPropertyNode::LONG:
44         object->setValue(node->getIntValue());
45         break;
46     case SGPropertyNode::FLOAT:
47     case SGPropertyNode::DOUBLE:
48         object->setValue(node->getFloatValue());
49         break;
50     default:
51         object->setValue(node->getStringValue());
52         break;
53     }
54 }
55
56
57 static void
58 copy_from_pui (puObject * object, SGPropertyNode * node)
59 {
60     switch (node->getType()) {
61     case SGPropertyNode::BOOL:
62     case SGPropertyNode::INT:
63     case SGPropertyNode::LONG:
64         node->setIntValue(object->getIntegerValue());
65         break;
66     case SGPropertyNode::FLOAT:
67     case SGPropertyNode::DOUBLE:
68         node->setFloatValue(object->getFloatValue());
69         break;
70     default:
71         node->setStringValue(object->getStringValue());
72         break;
73     }
74 }
75
76
77 \f
78 ////////////////////////////////////////////////////////////////////////
79 // Implementation of GUIInfo.
80 ////////////////////////////////////////////////////////////////////////
81
82 GUIInfo::GUIInfo (FGDialog * w)
83     : widget(w)
84 {
85 }
86
87 GUIInfo::~GUIInfo ()
88 {
89     for (int i = 0; i < bindings.size(); i++) {
90         delete bindings[i];
91         bindings[i] = 0;
92     }
93 }
94
95
96 \f
97 ////////////////////////////////////////////////////////////////////////
98 // Implementation of FGDialog.
99 ////////////////////////////////////////////////////////////////////////
100
101 FGDialog::FGDialog (SGPropertyNode_ptr props)
102     : _object(0)
103 {
104     display(props);
105 }
106
107 FGDialog::~FGDialog ()
108 {
109     delete _object;
110
111     int i;
112     for (i = 0; i < _info.size(); i++) {
113         delete _info[i];
114         _info[i] = 0;
115     }
116
117     for (i = 0; i < _propertyObjects.size(); i++) {
118         delete _propertyObjects[i];
119         _propertyObjects[i] = 0;
120     }
121 }
122
123 void
124 FGDialog::updateValue (const char * objectName)
125 {
126     for (int i = 0; i < _propertyObjects.size(); i++) {
127         const string &name = _propertyObjects[i]->name;
128         if (name == objectName)
129             copy_to_pui(_propertyObjects[i]->node,
130                         _propertyObjects[i]->object);
131     }
132 }
133
134 void
135 FGDialog::applyValue (const char * objectName)
136 {
137     for (int i = 0; i < _propertyObjects.size(); i++) {
138         if (_propertyObjects[i]->name == objectName)
139             copy_from_pui(_propertyObjects[i]->object,
140                           _propertyObjects[i]->node);
141     }
142 }
143
144 void
145 FGDialog::updateValues ()
146 {
147     for (int i = 0; i < _propertyObjects.size(); i++)
148         copy_to_pui(_propertyObjects[i]->node, _propertyObjects[i]->object);
149 }
150
151 void
152 FGDialog::applyValues ()
153 {
154     for (int i = 0; i < _propertyObjects.size(); i++)
155         copy_from_pui(_propertyObjects[i]->object,
156                       _propertyObjects[i]->node);
157 }
158
159 void
160 FGDialog::display (SGPropertyNode_ptr props)
161 {
162     if (_object != 0) {
163         SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active");
164         return;
165     }
166
167     _object = makeObject(props, 1024, 768);
168
169     if (_object != 0) {
170         _object->reveal();
171     } else {
172         SG_LOG(SG_GENERAL, SG_ALERT, "Widget "
173                << props->getStringValue("name", "[unnamed]")
174                << " does not contain a proper GUI definition");
175     }
176 }
177
178 puObject *
179 FGDialog::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 == "checkbox") {
216         puButton * b;
217         b = new puButton(x, y, x + width, y + height, PUBUTTON_CIRCLE);
218         setupObject(b, props);
219         return b;
220     } else if (type == "button") {
221         puButton * b;
222         const char * legend = props->getStringValue("legend", "[none]");
223         if (props->getBoolValue("one-shot", true))
224             b = new puOneShot(x, y, legend);
225         else
226             b = new puButton(x, y, legend);
227         setupObject(b, props);
228         return b;
229     } else {
230         return 0;
231     }
232 }
233
234 void
235 FGDialog::setupObject (puObject * object, SGPropertyNode * props)
236 {
237     if (props->hasValue("legend"))
238         object->setLegend(props->getStringValue("legend"));
239
240     if (props->hasValue("label"))
241         object->setLabel(props->getStringValue("label"));
242
243     if (props->hasValue("property")) {
244         const char * name = props->getStringValue("name");
245         if (name == 0)
246             name = "";
247         const char * propname = props->getStringValue("property");
248         SGPropertyNode_ptr node = fgGetNode(propname, true);
249         copy_to_pui(node, object);
250         if (name != 0)
251             _propertyObjects.push_back(new PropertyObject(name, object, node));
252     }
253
254     vector<SGPropertyNode_ptr> nodes = props->getChildren("binding");
255     if (nodes.size() > 0) {
256         GUIInfo * info = new GUIInfo(this);
257
258         for (int i = 0; i < nodes.size(); i++)
259             info->bindings.push_back(new FGBinding(nodes[i]));
260         object->setCallback(action_callback);
261         object->setUserData(info);
262         _info.push_back(info);
263     }
264
265     object->makeReturnDefault(props->getBoolValue("default"));
266 }
267
268 void
269 FGDialog::setupGroup (puGroup * group, SGPropertyNode * props,
270                     int width, int height, bool makeFrame)
271 {
272     setupObject(group, props);
273
274     if (makeFrame)
275         new puFrame(0, 0, width, height);
276
277     int nChildren = props->nChildren();
278     for (int i = 0; i < nChildren; i++)
279         makeObject(props->getChild(i), width, height);
280     group->close();
281 }
282
283
284 \f
285 ////////////////////////////////////////////////////////////////////////
286 // Implementation of FGDialog::PropertyObject.
287 ////////////////////////////////////////////////////////////////////////
288
289 FGDialog::PropertyObject::PropertyObject (const char * n,
290                                            puObject * o,
291                                            SGPropertyNode_ptr p)
292     : name(n),
293       object(o),
294       node(p)
295 {
296 }
297
298
299 // end of dialog.cxx