1 // new_gui.cxx: implementation of XML-configurable GUI support.
11 #include <simgear/misc/exception.hxx>
12 #include <Main/fg_props.hxx>
16 ////////////////////////////////////////////////////////////////////////
18 ////////////////////////////////////////////////////////////////////////
22 * Callback to update all property values.
25 update_callback (puObject * object)
27 ((GUIWidget *)object->getUserData())->updateProperties();
32 * Callback to close the dialog.
35 close_callback (puObject * object)
37 delete ((GUIWidget *)object->getUserData());
42 * Callback to apply the property value for every field.
45 apply_callback (puObject * object)
47 ((GUIWidget *)object->getUserData())->applyProperties();
48 update_callback(object);
53 * Callback to apply the property values and close the dialog.
56 close_apply_callback (puObject * object)
58 apply_callback(object);
59 close_callback(object);
64 ////////////////////////////////////////////////////////////////////////
65 // Implementation of GUIWidget.
66 ////////////////////////////////////////////////////////////////////////
68 GUIWidget::GUIWidget (SGPropertyNode_ptr props)
74 GUIWidget::~GUIWidget ()
80 GUIWidget::display (SGPropertyNode_ptr props)
83 SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active");
87 _object = makeObject(props, 1024, 768);
92 SG_LOG(SG_GENERAL, SG_ALERT, "Widget "
93 << props->getStringValue("name", "[unnamed]")
94 << " does not contain a proper GUI definition");
100 GUIWidget::applyProperties ()
102 for (int i = 0; i < _propertyObjects.size(); i++) {
103 puObject * object = _propertyObjects[i].object;
104 SGPropertyNode_ptr node = _propertyObjects[i].node;
105 node->setStringValue(object->getStringValue());
110 GUIWidget::updateProperties ()
112 for (int i = 0; i < _propertyObjects.size(); i++) {
113 puObject * object = _propertyObjects[i].object;
114 SGPropertyNode_ptr node = _propertyObjects[i].node;
115 object->setValue(node->getStringValue());
120 GUIWidget::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
122 int width = props->getIntValue("width", parentWidth);
123 int height = props->getIntValue("height", parentHeight);
125 int x = props->getIntValue("x", (parentWidth - width) / 2);
126 int y = props->getIntValue("y", (parentHeight - height) / 2);
128 string type = props->getName();
130 type = props->getStringValue("type");
132 SG_LOG(SG_GENERAL, SG_ALERT, "No type specified for GUI object");
136 if (type == "dialog") {
138 if (props->getBoolValue("modal", false))
139 dialog = new puDialogBox(x, y);
141 dialog = new puPopup(x, y);
142 setupGroup(dialog, props, width, height, true);
144 } else if (type == "group") {
145 puGroup * group = new puGroup(x, y);
146 setupGroup(group, props, width, height, false);
148 } else if (type == "input") {
149 puInput * input = new puInput(x, y, x + width, y + height);
150 setupObject(input, props);
152 } else if (type == "text") {
153 puText * text = new puText(x, y);
154 setupObject(text, props);
156 } else if (type == "button") {
158 const char * legend = props->getStringValue("legend", "[none]");
159 if (props->getBoolValue("one-shot", true))
160 b = new puOneShot(x, y, legend);
162 b = new puButton(x, y, legend);
163 setupObject(b, props);
171 GUIWidget::setupObject (puObject * object, SGPropertyNode * props)
173 object->setUserData(this);
175 if (props->hasValue("legend"))
176 object->setLegend(props->getStringValue("legend"));
178 if (props->hasValue("label"))
179 object->setLabel(props->getStringValue("label"));
181 if (props->hasValue("default-value-prop")) {
182 const char * name = props->getStringValue("default-value-prop");
183 SGPropertyNode_ptr node = fgGetNode(name, true);
184 object->setValue(node->getStringValue());
185 _propertyObjects.push_back(PropertyObject(object, node));
188 if (props->hasValue("action")) {
189 string action = props->getStringValue("action");
190 if (action == "update")
191 object->setCallback(update_callback);
192 else if (action == "close")
193 object->setCallback(close_callback);
194 else if (action == "apply")
195 object->setCallback(apply_callback);
196 else if (action == "close-apply")
197 object->setCallback(close_apply_callback);
199 SG_LOG(SG_GENERAL, SG_ALERT, "Unknown GUI action " + action);
202 object->makeReturnDefault(props->getBoolValue("default"));
206 GUIWidget::setupGroup (puGroup * group, SGPropertyNode * props,
207 int width, int height, bool makeFrame)
209 setupObject(group, props);
212 new puFrame(0, 0, width, height);
214 int nChildren = props->nChildren();
215 for (int i = 0; i < nChildren; i++)
216 makeObject(props->getChild(i), width, height);
220 GUIWidget::PropertyObject::PropertyObject (puObject * o, SGPropertyNode_ptr n)
228 ////////////////////////////////////////////////////////////////////////
229 // Implementation of NewGUI.
230 ////////////////////////////////////////////////////////////////////////
245 ulMakePath(path, getenv("FG_ROOT"), "gui");
250 NewGUI::update (double delta_time_sec)
256 NewGUI::display (const string &name)
258 if (_widgets.find(name) == _widgets.end())
259 SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
261 new GUIWidget(_widgets[name]); // PUI will delete it
265 NewGUI::readDir (const char * path)
267 ulDir * dir = ulOpenDir(path);
270 SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
275 ulDirEnt * dirEnt = ulReadDir(dir);
276 while (dirEnt != 0) {
279 ulMakePath(subpath, path, dirEnt->d_name);
281 if (dirEnt->d_isdir && dirEnt->d_name[0] != '.') {
284 SGPropertyNode_ptr props = new SGPropertyNode;
286 readProperties(subpath, props);
287 } catch (const sg_exception &ex) {
288 SG_LOG(SG_INPUT, SG_ALERT, "Error parsing GUI file "
291 if (!props->hasValue("name")) {
292 SG_LOG(SG_INPUT, SG_WARN, "GUI file " << subpath
293 << " has no name; skipping.");
295 string name = props->getStringValue("name");
296 SG_LOG(SG_INPUT, SG_BULK, "Saving GUI node " << name);
297 _widgets[name] = props;
300 dirEnt = ulReadDir(dir);
305 // end of new_gui.cxx