#include <iostream>
#include <cstring>
#include <sys/types.h>
-#include <plib/ul.h>
#include <plib/pu.h>
-#include <plib/ul.h>
#include <simgear/compiler.h>
#include <simgear/structure/exception.hxx>
#include <simgear/props/props_io.hxx>
+#include <simgear/misc/sg_dir.hxx>
#include <boost/algorithm/string/case_conv.hpp>
#include <Main/fg_props.hxx>
-#include "menubar.hxx"
-#include "dialog.hxx"
+#if defined(SG_UNIX) && !defined(SG_MAC)
+#include "GL/glx.h"
+#endif
+
+#include "FGPUIMenuBar.hxx"
-extern puFont FONT_HELVETICA_14;
-extern puFont FONT_SANS_12B;
+#if defined(SG_MAC)
+#include "FGCocoaMenuBar.hxx"
+#endif
+#include "FGPUIDialog.hxx"
+#include "FGFontCache.hxx"
+#include "FGColor.hxx"
+using std::map;
+using std::string;
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of NewGUI.
////////////////////////////////////////////////////////////////////////
-NewGUI::NewGUI ()
- : _menubar(new FGMenuBar),
- _active_dialog(0)
+NewGUI::NewGUI () :
+ _active_dialog(0)
{
+#if defined(SG_MAC)
+ _menubar.reset(new FGCocoaMenuBar);
+#else
+ _menubar.reset(new FGPUIMenuBar);
+#endif
}
NewGUI::~NewGUI ()
{
- delete _menubar;
_dialog_props.clear();
for (_itt_t it = _colors.begin(); it != _colors.end(); ++it)
delete it->second;
NewGUI::init ()
{
setStyle();
- char path1[1024];
- char path2[1024];
- ulMakePath(path1, globals->get_fg_root().c_str(), "gui");
- ulMakePath(path2, path1, "dialogs");
- readDir(path2);
+ SGPath p(globals->get_fg_root(), "gui/dialogs");
+ readDir(p);
_menubar->init();
}
NewGUI::reset (bool reload)
{
map<string,FGDialog *>::iterator iter;
- vector<string> dlg;
+ std::vector<string> dlg;
// close all open dialogs and remember them ...
for (iter = _active_dialogs.begin(); iter != _active_dialogs.end(); ++iter)
dlg.push_back(iter->first);
setStyle();
unbind();
- delete _menubar;
- _menubar = new FGMenuBar;
+#if !defined(SG_MAC)
+ _menubar.reset(new FGPUIMenuBar);
+#endif
if (reload) {
_dialog_props.clear();
return false;
} else {
if(!_active_dialogs[name])
- _active_dialogs[name] = new FGDialog(_dialog_props[name]);
+ _active_dialogs[name] = new FGPUIDialog(_dialog_props[name]);
return true;
}
}
FGMenuBar *
NewGUI::getMenuBar ()
{
- return _menubar;
+ return _menubar.get();
}
bool
_menubar->hide();
}
-static bool
-test_extension (const char * path, const char * ext)
-{
- int pathlen = strlen(path);
- int extlen = strlen(ext);
-
- for (int i = 1; i <= pathlen && i <= extlen; i++) {
- if (path[pathlen-i] != ext[extlen-i])
- return false;
- }
- return true;
-}
-
void
NewGUI::newDialog (SGPropertyNode* props)
{
}
void
-NewGUI::readDir (const char * path)
+NewGUI::readDir (const SGPath& path)
{
- ulDir * dir = ulOpenDir(path);
-
- if (dir == 0) {
- SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
- << path);
- return;
- }
-
- for (ulDirEnt * dirEnt = ulReadDir(dir);
- dirEnt != 0;
- dirEnt = ulReadDir(dir)) {
-
- char subpath[1024];
-
- ulMakePath(subpath, path, dirEnt->d_name);
-
- if (!dirEnt->d_isdir && test_extension(subpath, ".xml")) {
- SGPropertyNode * props = new SGPropertyNode;
- try {
- readProperties(subpath, props);
- } catch (const sg_exception &) {
- SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
- << subpath);
- delete props;
- continue;
- }
- SGPropertyNode *nameprop = props->getNode("name");
- if (!nameprop) {
- SG_LOG(SG_INPUT, SG_WARN, "dialog " << subpath
- << " has no name; skipping.");
- delete props;
- continue;
- }
- string name = nameprop->getStringValue();
- if (_dialog_props[name])
- delete (SGPropertyNode *)_dialog_props[name];
-
- _dialog_props[name] = props;
- }
+ simgear::Dir dir(path);
+ simgear::PathList xmls = dir.children(simgear::Dir::TYPE_FILE, ".xml");
+
+ for (unsigned int i=0; i<xmls.size(); ++i) {
+ SGPropertyNode * props = new SGPropertyNode;
+ try {
+ readProperties(xmls[i].str(), props);
+ } catch (const sg_exception &) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
+ << xmls[i].str());
+ delete props;
+ continue;
+ }
+ SGPropertyNode *nameprop = props->getNode("name");
+ if (!nameprop) {
+ SG_LOG(SG_INPUT, SG_WARN, "dialog " << xmls[i].str()
+ << " has no name; skipping.");
+ delete props;
+ continue;
+ }
+ string name = nameprop->getStringValue();
+ _dialog_props[name] = props;
}
- ulCloseDir(dir);
}
return;
}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// FGColor class.
-////////////////////////////////////////////////////////////////////////
-
-void
-FGColor::print() const {
- std::cerr << "red=" << _red << ", green=" << _green
- << ", blue=" << _blue << ", alpha=" << _alpha << std::endl;
-}
-
-bool
-FGColor::merge(const SGPropertyNode *node)
-{
- if (!node)
- return false;
-
- bool dirty = false;
- const SGPropertyNode * n;
- if ((n = node->getNode("red")))
- _red = n->getFloatValue(), dirty = true;
- if ((n = node->getNode("green")))
- _green = n->getFloatValue(), dirty = true;
- if ((n = node->getNode("blue")))
- _blue = n->getFloatValue(), dirty = true;
- if ((n = node->getNode("alpha")))
- _alpha = n->getFloatValue(), dirty = true;
- return dirty;
-}
-
-bool
-FGColor::merge(const FGColor *color)
-{
- bool dirty = false;
- if (color && color->_red >= 0.0)
- _red = color->_red, dirty = true;
- if (color && color->_green >= 0.0)
- _green = color->_green, dirty = true;
- if (color && color->_blue >= 0.0)
- _blue = color->_blue, dirty = true;
- if (color && color->_alpha >= 0.0)
- _alpha = color->_alpha, dirty = true;
- return dirty;
-}
-
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// FGFontCache class.
-////////////////////////////////////////////////////////////////////////
-
-namespace
-{
-struct GuiFont
-{
- const char *name;
- puFont *font;
- struct Predicate
- : public std::unary_function<const GuiFont, bool>
- {
- Predicate(const char* name_) : name(name_) {}
- bool operator() (const GuiFont& f1) const
- {
- return std::strcmp(f1.name, name) == 0;
- }
- const char* name;
- };
-};
-
-const GuiFont guifonts[] = {
- { "default", &FONT_HELVETICA_14 },
- { "FIXED_8x13", &PUFONT_8_BY_13 },
- { "FIXED_9x15", &PUFONT_9_BY_15 },
- { "TIMES_10", &PUFONT_TIMES_ROMAN_10 },
- { "TIMES_24", &PUFONT_TIMES_ROMAN_24 },
- { "HELVETICA_10", &PUFONT_HELVETICA_10 },
- { "HELVETICA_12", &PUFONT_HELVETICA_12 },
- { "HELVETICA_14", &FONT_HELVETICA_14 },
- { "HELVETICA_18", &PUFONT_HELVETICA_18 },
- { "SANS_12B", &FONT_SANS_12B }
-};
-
-const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
-}
-
-FGFontCache::FGFontCache() :
- _initialized(false)
-{
-}
-
-FGFontCache::~FGFontCache()
-{
- PuFontMap::iterator it, end = _puFonts.end();
- for (it = _puFonts.begin(); it != end; ++it)
- delete it->second;
-}
-
-inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
- const FntParams& f2) const
-{
- int comp = f1.name.compare(f2.name);
- if (comp < 0)
- return true;
- else if (comp > 0)
- return false;
- if (f1.size < f2.size)
- return true;
- else if (f1.size > f2.size)
- return false;
- return f1.slant < f2.slant;
-}
-
-struct FGFontCache::fnt *
-FGFontCache::getfnt(const char *name, float size, float slant)
-{
- string fontName = boost::to_lower_copy(string(name));
- FntParams fntParams(fontName, size, slant);
- PuFontMap::iterator i = _puFonts.find(fntParams);
- if (i != _puFonts.end()) {
- // found in the puFonts map, all done
- return i->second;
- }
-
- // fntTexFont s are all preloaded into the _texFonts map
- TexFontMap::iterator texi = _texFonts.find(fontName);
- fntTexFont* texfont = NULL;
- puFont* pufont = NULL;
- if (texi != _texFonts.end()) {
- texfont = texi->second;
- } else {
- // check the built-in PUI fonts (in guifonts array)
- const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
- GuiFont::Predicate(name));
- if (guifont != guifontsEnd) {
- pufont = guifont->font;
- }
- }
-
- fnt* f = new fnt;
- if (pufont) {
- f->pufont = pufont;
- } else if (texfont) {
- f->texfont = texfont;
- f->pufont = new puFont;
- f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
- } else {
- f->pufont = guifonts[0].font;
- }
- _puFonts[fntParams] = f;
- return f;
-}
-
-puFont *
-FGFontCache::get(const char *name, float size, float slant)
-{
- return getfnt(name, size, slant)->pufont;
-}
-
-fntTexFont *
-FGFontCache::getTexFont(const char *name, float size, float slant)
-{
- return getfnt(name, size, slant)->texfont;
-}
-
-puFont *
-FGFontCache::get(SGPropertyNode *node)
-{
- if (!node)
- return get("Helvetica.txf", 15.0, 0.0);
-
- const char *name = node->getStringValue("name", "Helvetica.txf");
- float size = node->getFloatValue("size", 15.0);
- float slant = node->getFloatValue("slant", 0.0);
-
- return get(name, size, slant);
-}
-
-void FGFontCache::init()
-{
- if (_initialized) {
- return;
- }
-
- char *envp = ::getenv("FG_FONTS");
- if (envp != NULL) {
- _path.set(envp);
- } else {
- _path.set(globals->get_fg_root());
- _path.append("Fonts");
- }
- _initialized = true;
-}
-
-SGPath
-FGFontCache::getfntpath(const char *name)
-{
- init();
- SGPath path(_path);
- if (name && std::string(name) != "") {
- path.append(name);
- if (path.exists())
- return path;
- }
-
- path = SGPath(_path);
- path.append("Helvetica.txf");
- SG_LOG(SG_GENERAL, SG_WARN, "Unknown font name '" << name << "', defaulting to Helvetica");
- return path;
-}
-
-bool FGFontCache::initializeFonts()
-{
- static string fontext("txf");
- init();
- ulDir* fontdir = ulOpenDir(_path.c_str());
- if (!fontdir)
- return false;
- const ulDirEnt *dirEntry;
- while ((dirEntry = ulReadDir(fontdir)) != 0) {
- SGPath path(_path);
- path.append(dirEntry->d_name);
- if (path.extension() == fontext) {
- fntTexFont* f = new fntTexFont;
- if (f->load((char *)path.c_str())) {
- // convert font names in the map to lowercase for matching
- string fontName = boost::to_lower_copy(string(dirEntry->d_name));
- _texFonts[fontName] = f;
- } else
- delete f;
- }
- }
- ulCloseDir(fontdir);
- return true;
-}
-
// end of new_gui.cxx