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