]> git.mxchange.org Git - flightgear.git/blob - src/GUI/new_gui.cxx
fce518055bbf85648093610d04729d5d3a5479e6
[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 <simgear/compiler.h>
9 #include <simgear/structure/exception.hxx>
10
11 #include <Main/fg_props.hxx>
12
13 #include "menubar.hxx"
14 #include "dialog.hxx"
15
16 SG_USING_STD(map);
17
18 \f
19 ////////////////////////////////////////////////////////////////////////
20 // Implementation of NewGUI.
21 ////////////////////////////////////////////////////////////////////////
22
23
24 NewGUI::NewGUI ()
25     : _menubar(new FGMenuBar),
26       _active_dialog(0)
27 {
28 }
29
30 NewGUI::~NewGUI ()
31 {
32     clear();
33 }
34
35 void
36 NewGUI::init ()
37 {
38     char path1[1024];
39     char path2[1024];
40     ulMakePath(path1, globals->get_fg_root().c_str(), "gui");
41     ulMakePath(path2, path1, "dialogs");
42     readDir(path2);
43     _menubar->init();
44 }
45
46 void
47 NewGUI::reinit ()
48 {
49     unbind();
50     clear();
51     _menubar = new FGMenuBar;
52     init();
53     bind();
54 }
55
56 void
57 NewGUI::bind ()
58 {
59     fgTie("/sim/menubar/visibility", this,
60           &NewGUI::getMenuBarVisible, &NewGUI::setMenuBarVisible);
61 }
62
63 void
64 NewGUI::unbind ()
65 {
66     fgUntie("/sim/menubar/visibility");
67 }
68
69 void
70 NewGUI::update (double delta_time_sec)
71 {
72     map<string,FGDialog *>::iterator iter = _active_dialogs.begin();
73     for(/**/; iter != _active_dialogs.end(); iter++)
74         iter->second->update();
75 }
76
77 bool
78 NewGUI::showDialog (const string &name)
79 {
80     if (_dialog_props.find(name) == _dialog_props.end()) {
81         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
82         return false;
83     } else {
84         if(!_active_dialogs[name])
85             _active_dialogs[name] = new FGDialog(_dialog_props[name]);
86         return true;
87     }
88 }
89
90 bool
91 NewGUI::closeActiveDialog ()
92 {
93     if (_active_dialog == 0)
94         return false;
95
96     // Kill any entries in _active_dialogs...  Is there an STL
97     // algorithm to do (delete map entries by value, not key)?  I hate
98     // the STL :) -Andy
99     map<string,FGDialog *>::iterator iter = _active_dialogs.begin();
100     for(/**/; iter != _active_dialogs.end(); iter++) {
101         if(iter->second == _active_dialog) {
102             _active_dialogs.erase(iter);
103             // iter is no longer valid
104             break;
105         }
106     }
107
108     delete _active_dialog;
109     _active_dialog = 0;
110     return true;
111 }
112
113 bool
114 NewGUI::closeDialog (const string& name)
115 {
116     if(_active_dialogs.find(name) != _active_dialogs.end()) {
117         if(_active_dialog == _active_dialogs[name])
118             _active_dialog = 0;
119         delete _active_dialogs[name];
120         _active_dialogs.erase(name);
121         return true;
122     }
123     return false; // dialog wasn't open...
124 }
125
126 void
127 NewGUI::setActiveDialog (FGDialog * dialog)
128 {
129     _active_dialog = dialog;
130 }
131
132 FGDialog *
133 NewGUI::getActiveDialog ()
134 {
135     return _active_dialog;
136 }
137
138 FGMenuBar *
139 NewGUI::getMenuBar ()
140 {
141     return _menubar;
142 }
143
144 bool
145 NewGUI::getMenuBarVisible () const
146 {
147     return _menubar->isVisible();
148 }
149
150 void
151 NewGUI::setMenuBarVisible (bool visible)
152 {
153     if (visible)
154         _menubar->show();
155     else
156         _menubar->hide();
157 }
158
159 void
160 NewGUI::clear ()
161 {
162     delete _menubar;
163     _menubar = 0;
164     _dialog_props.clear();
165 }
166
167 static bool
168 test_extension (const char * path, const char * ext)
169 {
170     int pathlen = strlen(path);
171     int extlen = strlen(ext);
172     
173     for (int i = 1; i <= pathlen && i <= extlen; i++) {
174         if (path[pathlen-i] != ext[extlen-i])
175             return false;
176     }
177     return true;
178 }
179
180 void
181 NewGUI::newDialog (SGPropertyNode* props)
182 {
183     const char* cname = props->getStringValue("name");
184     if(!cname) {
185         SG_LOG(SG_GENERAL, SG_ALERT, "New dialog has no <name> property");
186         return;
187     }
188     string name = cname;
189     if(!_active_dialogs[name])
190         _dialog_props[name] = props;
191 }
192
193 void
194 NewGUI::readDir (const char * path)
195 {
196     ulDir * dir = ulOpenDir(path);
197
198     if (dir == 0) {
199         SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
200                << path);
201         return;
202     }
203
204     for (ulDirEnt * dirEnt = ulReadDir(dir);
205          dirEnt != 0;
206          dirEnt = ulReadDir(dir)) {
207
208         char subpath[1024];
209
210         ulMakePath(subpath, path, dirEnt->d_name);
211
212         if (!dirEnt->d_isdir && test_extension(subpath, ".xml")) {
213             SGPropertyNode * props = new SGPropertyNode;
214             try {
215                 readProperties(subpath, props);
216             } catch (const sg_exception &) {
217                 SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
218                        << subpath);
219                 delete props;
220                 continue;
221             }
222             SGPropertyNode *nameprop = props->getNode("name");
223             if (!nameprop) {
224                 SG_LOG(SG_INPUT, SG_WARN, "dialog " << subpath
225                    << " has no name; skipping.");
226                 delete props;
227                 continue;
228             }
229             string name = nameprop->getStringValue();
230             if (_dialog_props[name])
231                 delete (SGPropertyNode *)_dialog_props[name];
232
233             _dialog_props[name] = props;
234         }
235     }
236     ulCloseDir(dir);
237 }
238
239 // end of new_gui.cxx