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