1 // new_gui.cxx: implementation of XML-configurable GUI support.
11 #include <simgear/misc/exception.hxx>
12 #include <Main/fg_props.hxx>
16 ////////////////////////////////////////////////////////////////////////
18 ////////////////////////////////////////////////////////////////////////
24 action_callback (puObject * object)
26 GUIInfo * info = (GUIInfo *)object->getUserData();
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);
38 ////////////////////////////////////////////////////////////////////////
39 // Implementation of GUIInfo.
40 ////////////////////////////////////////////////////////////////////////
42 GUIInfo::GUIInfo (GUIWidget * w)
49 for (int i = 0; i < bindings.size(); i++) {
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of GUIWidget.
59 ////////////////////////////////////////////////////////////////////////
61 GUIWidget::GUIWidget (SGPropertyNode_ptr props)
67 GUIWidget::~GUIWidget ()
72 for (i = 0; i < _info.size(); i++) {
77 for (i = 0; i < _propertyObjects.size(); i++) {
78 delete _propertyObjects[i];
79 _propertyObjects[i] = 0;
84 GUIWidget::updateValue (const char * objectName)
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());
94 GUIWidget::applyValue (const char * objectName)
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());
105 GUIWidget::updateValues ()
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());
115 GUIWidget::applyValues ()
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());
125 GUIWidget::display (SGPropertyNode_ptr props)
128 SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active");
132 _object = makeObject(props, 1024, 768);
137 SG_LOG(SG_GENERAL, SG_ALERT, "Widget "
138 << props->getStringValue("name", "[unnamed]")
139 << " does not contain a proper GUI definition");
144 GUIWidget::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
146 int width = props->getIntValue("width", parentWidth);
147 int height = props->getIntValue("height", parentHeight);
149 int x = props->getIntValue("x", (parentWidth - width) / 2);
150 int y = props->getIntValue("y", (parentHeight - height) / 2);
152 string type = props->getName();
154 type = props->getStringValue("type");
156 SG_LOG(SG_GENERAL, SG_ALERT, "No type specified for GUI object");
160 if (type == "dialog") {
162 if (props->getBoolValue("modal", false))
163 dialog = new puDialogBox(x, y);
165 dialog = new puPopup(x, y);
166 setupGroup(dialog, props, width, height, true);
168 } else if (type == "group") {
169 puGroup * group = new puGroup(x, y);
170 setupGroup(group, props, width, height, false);
172 } else if (type == "input") {
173 puInput * input = new puInput(x, y, x + width, y + height);
174 setupObject(input, props);
176 } else if (type == "text") {
177 puText * text = new puText(x, y);
178 setupObject(text, props);
180 } else if (type == "button") {
182 const char * legend = props->getStringValue("legend", "[none]");
183 if (props->getBoolValue("one-shot", true))
184 b = new puOneShot(x, y, legend);
186 b = new puButton(x, y, legend);
187 setupObject(b, props);
195 GUIWidget::setupObject (puObject * object, SGPropertyNode * props)
197 if (props->hasValue("legend"))
198 object->setLegend(props->getStringValue("legend"));
200 if (props->hasValue("label"))
201 object->setLabel(props->getStringValue("label"));
203 if (props->hasValue("property")) {
204 const char * name = props->getStringValue("name");
207 const char * propname = props->getStringValue("property");
208 SGPropertyNode_ptr node = fgGetNode(propname, true);
209 object->setValue(node->getStringValue());
211 _propertyObjects.push_back(new PropertyObject(name, object, node));
214 vector<SGPropertyNode_ptr> nodes = props->getChildren("binding");
215 if (nodes.size() > 0) {
216 GUIInfo * info = new GUIInfo(this);
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);
225 object->makeReturnDefault(props->getBoolValue("default"));
229 GUIWidget::setupGroup (puGroup * group, SGPropertyNode * props,
230 int width, int height, bool makeFrame)
232 setupObject(group, props);
235 new puFrame(0, 0, width, height);
237 int nChildren = props->nChildren();
238 for (int i = 0; i < nChildren; i++)
239 makeObject(props->getChild(i), width, height);
243 GUIWidget::PropertyObject::PropertyObject (const char * n,
245 SGPropertyNode_ptr p)
254 ////////////////////////////////////////////////////////////////////////
255 // Implementation of NewGUI.
256 ////////////////////////////////////////////////////////////////////////
272 ulMakePath(path, getenv("FG_ROOT"), "gui");
277 NewGUI::update (double delta_time_sec)
283 NewGUI::display (const string &name)
285 if (_widgets.find(name) == _widgets.end())
286 SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
288 new GUIWidget(_widgets[name]);
292 NewGUI::setCurrentWidget (GUIWidget * widget)
294 _current_widget = widget;
298 NewGUI::getCurrentWidget ()
300 return _current_widget;
304 NewGUI::readDir (const char * path)
306 ulDir * dir = ulOpenDir(path);
309 SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
314 ulDirEnt * dirEnt = ulReadDir(dir);
315 while (dirEnt != 0) {
318 ulMakePath(subpath, path, dirEnt->d_name);
320 if (dirEnt->d_isdir && dirEnt->d_name[0] != '.') {
323 SGPropertyNode_ptr props = new SGPropertyNode;
325 readProperties(subpath, props);
326 } catch (const sg_exception &ex) {
327 SG_LOG(SG_INPUT, SG_ALERT, "Error parsing GUI file "
330 if (!props->hasValue("name")) {
331 SG_LOG(SG_INPUT, SG_WARN, "GUI file " << subpath
332 << " has no name; skipping.");
334 string name = props->getStringValue("name");
335 SG_LOG(SG_INPUT, SG_BULK, "Saving GUI node " << name);
336 _widgets[name] = props;
339 dirEnt = ulReadDir(dir);
344 // end of new_gui.cxx