X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FGUI%2Fnew_gui.cxx;h=5d52b1c1dbb3b306e23b121ecd88a17497ee7661;hb=02fb83c774020633cb62e3b8154337510bed1de3;hp=df81cb1fd13b651e685dde4dec6d59c8ee89614a;hpb=dafa6ced1be06f2f5517cfc81454c62bb5990c00;p=flightgear.git diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx index df81cb1fd..5d52b1c1d 100644 --- a/src/GUI/new_gui.cxx +++ b/src/GUI/new_gui.cxx @@ -1,12 +1,24 @@ // new_gui.cxx: implementation of XML-configurable GUI support. +#ifdef HAVE_CONFIG_H +# include +#endif + #include "new_gui.hxx" +#include +#include +#include +#include + #include -#include #include #include +#include +#include + +#include #include
@@ -26,50 +38,72 @@ extern puFont FONT_SANS_12B; NewGUI::NewGUI () - : _font(FONT_HELVETICA_14), - _menubar(new FGMenuBar), + : _menubar(new FGMenuBar), _active_dialog(0) { } NewGUI::~NewGUI () { - clear(); + delete _menubar; + _dialog_props.clear(); + for (_itt_t it = _colors.begin(); it != _colors.end(); ++it) + delete it->second; } void 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(); } void NewGUI::reinit () +{ + reset(true); + fgSetBool("/sim/signals/reinit-gui", true); +} + +void +NewGUI::redraw () +{ + reset(false); +} + +void +NewGUI::reset (bool reload) { map::iterator iter; vector dlg; // close all open dialogs and remember them ... - for (iter = _active_dialogs.begin(); iter != _active_dialogs.end(); iter++) { + for (iter = _active_dialogs.begin(); iter != _active_dialogs.end(); ++iter) dlg.push_back(iter->first); - closeDialog(iter->first); - } - unbind(); - clear(); + unsigned int i; + for (i = 0; i < dlg.size(); i++) + closeDialog(dlg[i]); + setStyle(); + + unbind(); + delete _menubar; _menubar = new FGMenuBar; - init(); + + if (reload) { + _dialog_props.clear(); + init(); + } else { + _menubar->init(); + } + bind(); - // open remembered dialogs again (no nasal generated ones, unfortunately) -// for (unsigned int i = 0; i < dlg.size(); i++) -// showDialog(dlg[i]); + // open dialogs again + for (i = 0; i < dlg.size(); i++) + showDialog(dlg[i]); } void @@ -142,6 +176,26 @@ NewGUI::closeDialog (const string& name) return false; // dialog wasn't open... } +SGPropertyNode_ptr +NewGUI::getDialogProperties (const string &name) +{ + if(_dialog_props.find(name) != _dialog_props.end()) + return _dialog_props[name]; + + SG_LOG(SG_GENERAL, SG_DEBUG, "dialog '" << name << "' missing"); + return 0; +} + +FGDialog * +NewGUI::getDialog (const string &name) +{ + if(_active_dialogs.find(name) != _active_dialogs.end()) + return _active_dialogs[name]; + + SG_LOG(SG_GENERAL, SG_DEBUG, "dialog '" << name << "' missing"); + return 0; +} + void NewGUI::setActiveDialog (FGDialog * dialog) { @@ -175,31 +229,6 @@ NewGUI::setMenuBarVisible (bool visible) _menubar->hide(); } -void -NewGUI::clear () -{ - delete _menubar; - _menubar = 0; - _dialog_props.clear(); - _itt_t it; - for (it = _colors.begin(); it != _colors.end(); ++it) - delete it->second; - _colors.clear(); -} - -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) { @@ -209,54 +238,36 @@ NewGUI::newDialog (SGPropertyNode* props) return; } string name = cname; - if(!_active_dialogs[name]) + if(_active_dialogs.find(name) == _active_dialogs.end()) _dialog_props[name] = 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; igetNode("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); } @@ -280,16 +291,17 @@ NewGUI::setStyle (void) _colors["label"] = new FGColor(0.0f, 0.0f, 0.0f, 1.0f); _colors["legend"] = new FGColor(0.0f, 0.0f, 0.0f, 1.0f); _colors["misc"] = new FGColor(0.0f, 0.0f, 0.0f, 1.0f); + _colors["inputfield"] = new FGColor(0.8f, 0.7f, 0.7f, 1.0f); //puSetDefaultStyle(); - int which = fgGetInt("/sim/current-gui", 0); - SGPropertyNode *sim = globals->get_props()->getNode("sim"); - SGPropertyNode *n = sim->getChild("gui", which); + int which = fgGetInt("/sim/gui/current-style", 0); + SGPropertyNode *sim = globals->get_props()->getNode("sim/gui", true); + SGPropertyNode *n = sim->getChild("style", which); if (!n) - n = sim->getChild("gui", 0, true); + n = sim->getChild("style", 0, true); - setupFont(n->getNode("font", true)); + setupFont(n->getNode("fonts/gui", true)); n = n->getNode("colors", true); for (int i = 0; i < n->nChildren(); i++) { @@ -302,60 +314,12 @@ NewGUI::setStyle (void) } - - -static const struct { - char *name; - puFont *font; -} 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 }, - { 0, 0 } -}; - void NewGUI::setupFont (SGPropertyNode *node) { - string fontname = node->getStringValue("name", "Helvetica.txf"); - float size = node->getFloatValue("size", 15.0); - float slant = node->getFloatValue("slant", 0.0); - - int i; - for (i = 0; guifonts[i].name; i++) - if (fontname == guifonts[i].name) - break; - if (guifonts[i].name) - _font = *guifonts[i].font; - else { - SGPath fontpath; - char* envp = ::getenv("FG_FONTS"); - if (envp != NULL) { - fontpath.set(envp); - } else { - fontpath.set(globals->get_fg_root()); - fontpath.append("Fonts"); - } - - SGPath path(fontpath); - path.append(fontname); - - if (_tex_font.load((char *)path.c_str())) { - _font.initialize((fntFont *)&_tex_font, size, slant); - } else { - _font = *guifonts[0].font; - fontname = "default"; - } - } - puSetDefaultFonts(_font, _font); - node->setStringValue("name", fontname.c_str()); + _font = globals->get_fontcache()->get(node); + puSetDefaultFonts(*_font, *_font); + return; } @@ -365,6 +329,12 @@ NewGUI::setupFont (SGPropertyNode *node) // FGColor class. //////////////////////////////////////////////////////////////////////// +void +FGColor::print() const { + std::cerr << "red=" << _red << ", green=" << _green + << ", blue=" << _blue << ", alpha=" << _alpha << std::endl; +} + bool FGColor::merge(const SGPropertyNode *node) { @@ -400,61 +370,131 @@ FGColor::merge(const FGColor *color) } -// -FGFontCache::FGFontCache() + + +//////////////////////////////////////////////////////////////////////// +// FGFontCache class. +//////////////////////////////////////////////////////////////////////// + +namespace { - char *envp = ::getenv("FG_FONTS"); - if (envp != NULL) { - _path.set(envp); - } else { - _path.set(globals->get_fg_root()); - _path.append("Fonts"); - } +struct GuiFont +{ + const char *name; + puFont *font; + struct Predicate + : public std::unary_function + { + Predicate(const char* name_) : name(name_) {} + bool operator() (const GuiFont& f1) const + { + return std::strcmp(f1.name, name) == 0; + } + const char* name; + }; +}; - for (int i=0; guifonts[i].name; i++) - _fonts[guifonts[i].name] = guifonts[i].font; +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() +FGFontCache::FGFontCache() : + _initialized(false) { - _fonts.clear(); } -puFont * -FGFontCache::get(const char *name, float size, float slant) +FGFontCache::~FGFontCache() { - puFont *font; - _itt_t it; + PuFontMap::iterator it, end = _puFonts.end(); + for (it = _puFonts.begin(); it != end; ++it) + delete it->second; +} - if ((it = _fonts.find(name)) == _fonts.end()) - { - SGPath path(_path); - path.append(name); +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; +} - fntTexFont tex_font; - if (tex_font.load((char *)path.c_str())) - { - font = new puFont; - font->initialize((fntFont *)&tex_font, size, slant); - _fonts[name] = font; - } - else - { - font = _fonts["default"]; - // puSetDefaultFonts(font, font); +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; } } - else - { - font = it->second; + + fnt* f = new fnt; + if (pufont) { + f->pufont = pufont; + } else if (texfont) { + f->texfont = texfont; + f->pufont = new puFont; + f->pufont->initialize(static_cast(f->texfont), size, slant); + } else { + f->pufont = guifonts[0].font; } + _puFonts[fntParams] = f; + return f; +} - return font; +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); @@ -462,4 +502,62 @@ FGFontCache::get(SGPropertyNode *node) 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