]> git.mxchange.org Git - flightgear.git/blob - src/GUI/new_gui.cxx
Restructure GUI code, isolate PLIB in source files, to ease future refactoring and...
[flightgear.git] / src / GUI / new_gui.cxx
1 // new_gui.cxx: implementation of XML-configurable GUI support.
2
3 #ifdef HAVE_CONFIG_H
4 #  include <config.h>
5 #endif
6
7 #include "new_gui.hxx"
8
9 #include <algorithm>
10 #include <iostream>
11 #include <cstring>
12 #include <sys/types.h>
13
14 #include <plib/pu.h>
15
16 #include <simgear/compiler.h>
17 #include <simgear/structure/exception.hxx>
18 #include <simgear/props/props_io.hxx>
19 #include <simgear/misc/sg_dir.hxx>
20
21 #include <boost/algorithm/string/case_conv.hpp>
22
23 #include <Main/fg_props.hxx>
24
25 #if defined(SG_UNIX) && !defined(SG_MAC) 
26 #include "GL/glx.h"
27 #endif
28
29 #include "menubar.hxx"
30 #include "dialog.hxx"
31 #include "FGFontCache.hxx"
32 #include "FGColor.hxx"
33
34 using std::map;
35 using std::string;
36
37 ////////////////////////////////////////////////////////////////////////
38 // Implementation of NewGUI.
39 ////////////////////////////////////////////////////////////////////////
40
41
42
43 NewGUI::NewGUI ()
44     : _menubar(new FGMenuBar),
45       _active_dialog(0)
46 {
47 }
48
49 NewGUI::~NewGUI ()
50 {
51     delete _menubar;
52     _dialog_props.clear();
53     for (_itt_t it = _colors.begin(); it != _colors.end(); ++it)
54         delete it->second;
55 }
56
57 void
58 NewGUI::init ()
59 {
60     setStyle();
61     SGPath p(globals->get_fg_root(), "gui/dialogs");
62     readDir(p);
63     _menubar->init();
64 }
65
66 void
67 NewGUI::reinit ()
68 {
69     reset(true);
70     fgSetBool("/sim/signals/reinit-gui", true);
71 }
72
73 void
74 NewGUI::redraw ()
75 {
76     reset(false);
77 }
78
79 void
80 NewGUI::reset (bool reload)
81 {
82     map<string,FGDialog *>::iterator iter;
83     vector<string> dlg;
84     // close all open dialogs and remember them ...
85     for (iter = _active_dialogs.begin(); iter != _active_dialogs.end(); ++iter)
86         dlg.push_back(iter->first);
87
88     unsigned int i;
89     for (i = 0; i < dlg.size(); i++)
90         closeDialog(dlg[i]);
91
92     setStyle();
93
94     unbind();
95     delete _menubar;
96     _menubar = new FGMenuBar;
97
98     if (reload) {
99         _dialog_props.clear();
100         init();
101     } else {
102         _menubar->init();
103     }
104
105     bind();
106
107     // open dialogs again
108     for (i = 0; i < dlg.size(); i++)
109         showDialog(dlg[i]);
110 }
111
112 void
113 NewGUI::bind ()
114 {
115     fgTie("/sim/menubar/visibility", this,
116           &NewGUI::getMenuBarVisible, &NewGUI::setMenuBarVisible);
117 }
118
119 void
120 NewGUI::unbind ()
121 {
122     fgUntie("/sim/menubar/visibility");
123 }
124
125 void
126 NewGUI::update (double delta_time_sec)
127 {
128     map<string,FGDialog *>::iterator iter = _active_dialogs.begin();
129     for(/**/; iter != _active_dialogs.end(); iter++)
130         iter->second->update();
131 }
132
133 bool
134 NewGUI::showDialog (const string &name)
135 {
136     if (_dialog_props.find(name) == _dialog_props.end()) {
137         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
138         return false;
139     } else {
140         if(!_active_dialogs[name])
141             _active_dialogs[name] = new FGDialog(_dialog_props[name]);
142         return true;
143     }
144 }
145
146 bool
147 NewGUI::closeActiveDialog ()
148 {
149     if (_active_dialog == 0)
150         return false;
151
152     // Kill any entries in _active_dialogs...  Is there an STL
153     // algorithm to do (delete map entries by value, not key)?  I hate
154     // the STL :) -Andy
155     map<string,FGDialog *>::iterator iter = _active_dialogs.begin();
156     for(/**/; iter != _active_dialogs.end(); iter++) {
157         if(iter->second == _active_dialog) {
158             _active_dialogs.erase(iter);
159             // iter is no longer valid
160             break;
161         }
162     }
163
164     delete _active_dialog;
165     _active_dialog = 0;
166     return true;
167 }
168
169 bool
170 NewGUI::closeDialog (const string& name)
171 {
172     if(_active_dialogs.find(name) != _active_dialogs.end()) {
173         if(_active_dialog == _active_dialogs[name])
174             _active_dialog = 0;
175         delete _active_dialogs[name];
176         _active_dialogs.erase(name);
177         return true;
178     }
179     return false; // dialog wasn't open...
180 }
181
182 SGPropertyNode_ptr
183 NewGUI::getDialogProperties (const string &name)
184 {
185     if(_dialog_props.find(name) != _dialog_props.end())
186         return _dialog_props[name];
187
188     SG_LOG(SG_GENERAL, SG_DEBUG, "dialog '" << name << "' missing");
189     return 0;
190 }
191
192 FGDialog *
193 NewGUI::getDialog (const string &name)
194 {
195     if(_active_dialogs.find(name) != _active_dialogs.end())
196         return _active_dialogs[name];
197
198     SG_LOG(SG_GENERAL, SG_DEBUG, "dialog '" << name << "' missing");
199     return 0;
200 }
201
202 void
203 NewGUI::setActiveDialog (FGDialog * dialog)
204 {
205     _active_dialog = dialog;
206 }
207
208 FGDialog *
209 NewGUI::getActiveDialog ()
210 {
211     return _active_dialog;
212 }
213
214 FGMenuBar *
215 NewGUI::getMenuBar ()
216 {
217     return _menubar;
218 }
219
220 bool
221 NewGUI::getMenuBarVisible () const
222 {
223     return _menubar->isVisible();
224 }
225
226 void
227 NewGUI::setMenuBarVisible (bool visible)
228 {
229     if (visible)
230         _menubar->show();
231     else
232         _menubar->hide();
233 }
234
235 void
236 NewGUI::newDialog (SGPropertyNode* props)
237 {
238     const char* cname = props->getStringValue("name");
239     if(!cname) {
240         SG_LOG(SG_GENERAL, SG_ALERT, "New dialog has no <name> property");
241         return;
242     }
243     string name = cname;
244     if(_active_dialogs.find(name) == _active_dialogs.end())
245         _dialog_props[name] = props;
246 }
247
248 void
249 NewGUI::readDir (const SGPath& path)
250 {
251     simgear::Dir dir(path);
252     simgear::PathList xmls = dir.children(simgear::Dir::TYPE_FILE, ".xml");
253     
254     for (unsigned int i=0; i<xmls.size(); ++i) {
255       SGPropertyNode * props = new SGPropertyNode;
256       try {
257           readProperties(xmls[i].str(), props);
258       } catch (const sg_exception &) {
259           SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
260                  << xmls[i].str());
261           delete props;
262           continue;
263       }
264       SGPropertyNode *nameprop = props->getNode("name");
265       if (!nameprop) {
266           SG_LOG(SG_INPUT, SG_WARN, "dialog " << xmls[i].str()
267              << " has no name; skipping.");
268           delete props;
269           continue;
270       }
271       string name = nameprop->getStringValue();
272       _dialog_props[name] = props;
273     }
274 }
275
276
277 \f
278 ////////////////////////////////////////////////////////////////////////
279 // Style handling.
280 ////////////////////////////////////////////////////////////////////////
281
282 void
283 NewGUI::setStyle (void)
284 {
285     _itt_t it;
286     for (it = _colors.begin(); it != _colors.end(); ++it)
287       delete it->second;
288     _colors.clear();
289
290     // set up the traditional colors as default
291     _colors["background"] = new FGColor(0.8f, 0.8f, 0.9f, 0.85f);
292     _colors["foreground"] = new FGColor(0.0f, 0.0f, 0.0f, 1.0f);
293     _colors["highlight"]  = new FGColor(0.7f, 0.7f, 0.7f, 1.0f);
294     _colors["label"]      = new FGColor(0.0f, 0.0f, 0.0f, 1.0f);
295     _colors["legend"]     = new FGColor(0.0f, 0.0f, 0.0f, 1.0f);
296     _colors["misc"]       = new FGColor(0.0f, 0.0f, 0.0f, 1.0f);
297     _colors["inputfield"] = new FGColor(0.8f, 0.7f, 0.7f, 1.0f);
298
299     //puSetDefaultStyle();
300
301     int which = fgGetInt("/sim/gui/current-style", 0);
302     SGPropertyNode *sim = globals->get_props()->getNode("sim/gui", true);
303     SGPropertyNode *n = sim->getChild("style", which);
304     if (!n)
305         n = sim->getChild("style", 0, true);
306
307     setupFont(n->getNode("fonts/gui", true));
308     n = n->getNode("colors", true);
309
310     for (int i = 0; i < n->nChildren(); i++) {
311         SGPropertyNode *child = n->getChild(i);
312         _colors[child->getName()] = new FGColor(child);
313     }
314
315     FGColor *c = _colors["background"];
316     puSetDefaultColourScheme(c->red(), c->green(), c->blue(), c->alpha());
317 }
318
319
320 void
321 NewGUI::setupFont (SGPropertyNode *node)
322 {
323     _font = globals->get_fontcache()->get(node);
324     puSetDefaultFonts(*_font, *_font);
325     return;
326 }
327
328 // end of new_gui.cxx