From 39b239957e39c3dd22502ddb4f7f580d8b9c759f Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 26 Feb 2017 21:59:05 +0000 Subject: [PATCH] Startup-tip system. Replace the license / website text with a startup tip. Tips are shown based on the day of the year, can be changed easily. --- src/ATC/ATISEncoder.cxx | 4 +- src/ATC/ATISEncoder.hxx | 2 +- src/GUI/menubar.cxx | 6 +-- src/GUI/menubar.hxx | 4 +- src/Main/locale.cxx | 99 ++++++++++++++++++++++++++++++++--------- src/Main/locale.hxx | 17 +++++-- src/Main/options.cxx | 12 ++--- src/Viewer/splash.cxx | 31 +++++++++++-- src/Viewer/splash.hxx | 4 +- 9 files changed, 139 insertions(+), 40 deletions(-) diff --git a/src/ATC/ATISEncoder.cxx b/src/ATC/ATISEncoder.cxx index 256166cd7..6cc060877 100644 --- a/src/ATC/ATISEncoder.cxx +++ b/src/ATC/ATISEncoder.cxx @@ -36,7 +36,7 @@ static string NO_ATIS("nil"); static string EMPTY(""); #define SPACE append(1,' ') -const char * ATCSpeech::getSpokenDigit( int i ) +std::string ATCSpeech::getSpokenDigit( int i ) { string key = "n" + boost::lexical_cast( i ); return globals->get_locale()->getLocalizedString(key.c_str(), "atc", "" ); @@ -55,7 +55,7 @@ string ATCSpeech::getSpokenNumber( string number ) string ATCSpeech::getSpokenNumber( int number, bool leadingZero, int digits ) { - vector spokenDigits; + string_list spokenDigits; bool negative = false; if( number < 0 ) { negative = true; diff --git a/src/ATC/ATISEncoder.hxx b/src/ATC/ATISEncoder.hxx index ee5089a0e..670dd66e7 100644 --- a/src/ATC/ATISEncoder.hxx +++ b/src/ATC/ATISEncoder.hxx @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class ATCSpeech { public: - static const char * getSpokenDigit( int i ); + static std::string getSpokenDigit( int i ); static std::string getSpokenNumber( std::string number ); static std::string getSpokenNumber( int number, bool leadingZero = false, int digits = 1 ); static std::string getSpokenAltitude( int altitude ); diff --git a/src/GUI/menubar.cxx b/src/GUI/menubar.cxx index 40191e37b..0674a09e4 100644 --- a/src/GUI/menubar.cxx +++ b/src/GUI/menubar.cxx @@ -17,13 +17,13 @@ FGMenuBar::~FGMenuBar () { } -const char* +std::string FGMenuBar::getLocalizedLabel(SGPropertyNode* node) { const char* name = node->getStringValue("name", 0); - const char* translated = globals->get_locale()->getLocalizedString(name, "menu"); - if (translated) + std::string translated = globals->get_locale()->getLocalizedString(name, "menu"); + if (!translated.empty()) return translated; // return default with fallback to name diff --git a/src/GUI/menubar.hxx b/src/GUI/menubar.hxx index 3e70c48c1..2c6f0f33d 100644 --- a/src/GUI/menubar.hxx +++ b/src/GUI/menubar.hxx @@ -3,6 +3,8 @@ #ifndef __MENUBAR_HXX #define __MENUBAR_HXX 1 +#include + class SGPropertyNode; /** @@ -51,7 +53,7 @@ public: * Take care of mapping it to the appropriate translation, if available. * Returns an UTF-8 encoded string. */ - static const char* getLocalizedLabel(SGPropertyNode* node); + static std::string getLocalizedLabel(SGPropertyNode* node); }; diff --git a/src/Main/locale.cxx b/src/Main/locale.cxx index b8a02cd2a..da0ff460f 100644 --- a/src/Main/locale.cxx +++ b/src/Main/locale.cxx @@ -187,6 +187,8 @@ FGLocale::selectLanguage(const char *language) // load resource for atc messages loadResource("atc"); + loadResource("tips"); + if (!_currentLocale) { SG_LOG(SG_GENERAL, SG_ALERT, @@ -250,32 +252,67 @@ FGLocale::loadResource(const char* resource) return Ok; } -const char* -FGLocale::getLocalizedString(SGPropertyNode *localeNode, const char* id, const char* context) +std::string +FGLocale::getLocalizedString(SGPropertyNode *localeNode, const char* id, const char* context, int index) const { SGPropertyNode *n = localeNode->getNode("strings",0, true)->getNode(context); - if (n) - return n->getStringValue(id, NULL); - return NULL; + if (!n) { + return std::string(); + } + + n = n->getNode(id, index); + if (n && n->hasValue()) { + return std::string(n->getStringValue()); + } + + return std::string(); } -const char* +std::string FGLocale::getLocalizedString(const char* id, const char* resource, const char* Default) { if (id && resource) { - const char* s = NULL; - if (_currentLocale) - s = getLocalizedString(_currentLocale, id, resource); - if (s && s[0]!=0) - return s; + std::string s; + if (_currentLocale) { + s = getLocalizedString(_currentLocale, id, resource, 0); + if (!s.empty()) { + return s; + } + } - if (_defaultLocale) - s = getLocalizedString(_defaultLocale, id, resource); - if (s && s[0]!=0) - return s; + if (_defaultLocale) { + s = getLocalizedString(_defaultLocale, id, resource, 0); + if (!s.empty()) { + return s; + } + } } - return Default; + + return (Default == nullptr) ? std::string() : std::string(Default); +} + +std::string +FGLocale::getLocalizedStringWithIndex(const char* id, const char* resource, unsigned int index) const +{ + if (id && resource) { + std::string s; + if (_currentLocale) { + s = getLocalizedString(_currentLocale, id, resource, index); + if (!s.empty()) { + return s; + } + } + + if (_defaultLocale) { + s = getLocalizedString(_defaultLocale, id, resource, index); + if (!s.empty()) { + return s; + } + } + } + + return std::string(); } simgear::PropertyList @@ -289,6 +326,28 @@ FGLocale::getLocalizedStrings(SGPropertyNode *localeNode, const char* id, const return simgear::PropertyList(); } +size_t FGLocale::getLocalizedStringCount(const char* id, const char* resource) const +{ + if (_currentLocale) { + SGPropertyNode* resourceNode = _currentLocale->getNode("strings",0, true)->getNode(resource); + if (resourceNode) { + const size_t count = resourceNode->getChildren(id).size(); + if (count > 0) { + return count; + } + } + } + + if (_defaultLocale) { + size_t count = _defaultLocale->getNode("strings",0, true)->getNode(resource)->getChildren(id).size(); + if (count > 0) { + return count; + } + } + + return 0; +} + simgear::PropertyList FGLocale::getLocalizedStrings(const char* id, const char* resource) { @@ -343,10 +402,10 @@ std::string FGLocale::localizedPrintf(const char* id, const char* resource, ... std::string FGLocale::vlocalizedPrintf(const char* id, const char* resource, va_list args) { - const char* format = getLocalizedString(id, resource); - int len = ::vsprintf(NULL, format, args); + std::string format = getLocalizedString(id, resource); + int len = ::vsprintf(NULL, format.c_str(), args); char* buf = (char*) alloca(len); - ::vsprintf(buf, format, args); + ::vsprintf(buf, format.c_str(), args); return std::string(buf); } @@ -400,7 +459,7 @@ void FGLocale::utf8toLatin1(string& s) } } -const char* fgTrMsg(const char* key) +std::string fgTrMsg(const char* key) { return globals->get_locale()->getLocalizedString(key, "message"); } diff --git a/src/Main/locale.hxx b/src/Main/locale.hxx index 7119e9ee6..2bd799691 100644 --- a/src/Main/locale.hxx +++ b/src/Main/locale.hxx @@ -54,7 +54,7 @@ public: * Obtain a single string from the localized resource matching the given identifier. * Selected context refers to "menu", "options", "dialog" etc. */ - const char* getLocalizedString (const char* id, const char* resource, const char* Default=NULL); + std::string getLocalizedString (const char* id, const char* resource, const char* Default=NULL); /** * Obtain a list of strings from the localized resource matching the given identifier. @@ -63,6 +63,17 @@ public: */ simgear::PropertyList getLocalizedStrings(const char* id, const char* resource); + + /** + * Obtain a single string from the resource matching an identifier and ID. + */ + std::string getLocalizedStringWithIndex(const char* id, const char* resource, unsigned int index) const; + + /** + * Return the number of strings matching a resource + */ + size_t getLocalizedStringCount(const char* id, const char* resource) const; + /** * Obtain default font for current locale. */ @@ -97,7 +108,7 @@ protected: /** * Obtain a single string from locale node matching the given identifier and context. */ - const char* getLocalizedString (SGPropertyNode *localeNode, const char* id, const char* context); + std::string getLocalizedString (SGPropertyNode *localeNode, const char* id, const char* context, int index) const; /** * Obtain a list of strings from locale node matching the given identifier and context. @@ -116,7 +127,7 @@ protected: // global translation wrappers -const char* fgTrMsg(const char* key); +std::string fgTrMsg(const char* key); std::string fgTrPrintfMsg(const char* key, ...); diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 4d3b38ebb..01691f07a 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -2531,8 +2531,8 @@ void Options::showUsage() const exit(-1); } - const char* usage = locale->getLocalizedString(options->getStringValue("usage"), "options"); - if (usage) { + std::string usage = locale->getLocalizedString(options->getStringValue("usage"), "options"); + if (!usage.empty()) { cout << usage << endl; } @@ -2610,8 +2610,8 @@ void Options::showUsage() const } } - const char* name = locale->getLocalizedString(section[j]->getStringValue("name"),"options"); - if (!msg.empty() && name) { + std::string name = locale->getLocalizedString(section[j]->getStringValue("name"),"options"); + if (!msg.empty() && !name.empty()) { cout << endl << name << ":" << endl; cout << msg; msg.erase(); @@ -2619,8 +2619,8 @@ void Options::showUsage() const } if ( !p->verbose ) { - const char* verbose_help = locale->getLocalizedString(options->getStringValue("verbose-help"),"options"); - if (verbose_help) + std::string verbose_help = locale->getLocalizedString(options->getStringValue("verbose-help"),"options"); + if (!verbose_help.empty()) cout << endl << verbose_help << endl; } #ifdef _MSC_VER diff --git a/src/Viewer/splash.cxx b/src/Viewer/splash.cxx index d69b803ee..d92d25ef9 100644 --- a/src/Viewer/splash.cxx +++ b/src/Viewer/splash.cxx @@ -142,12 +142,15 @@ void SplashScreen::createNodes() } else { setupLogoImage(); - addText(geode, osg::Vec2(0.025, 0.025), 0.10, std::string("FlightGear ") + fgGetString("/sim/version/flightgear"), osgText::Text::LEFT_TOP); + // order here is important so we can re-write first item with the + // startup tip. addText(geode, osg::Vec2(0.025, 0.15), 0.03, LICENSE_URL_TEXT, osgText::Text::LEFT_TOP, nullptr, 0.6); + addText(geode, osg::Vec2(0.025, 0.025), 0.10, std::string("FlightGear ") + fgGetString("/sim/version/flightgear"), osgText::Text::LEFT_TOP); + if (!_aircraftLogoVertexArray) { addText(geode, osg::Vec2(0.025, 0.935), 0.10, fgGetString("/sim/description"), @@ -177,8 +180,9 @@ void SplashScreen::createNodes() fgGetNode("/sim/startup/splash-progress-spinner", true)); if (!strcmp(FG_BUILD_TYPE, "Nightly")) { - addText(geode, osg::Vec2(0.5, 0.5), 0.03, - "Unstable nightly build - some features may be under active development", + std::string unstableWarningText = globals->get_locale()->getLocalizedString("splash/unstable-warning", "sys", "unstable!"); + addText(geode, osg::Vec2(0.5, 0.5), 0.03, + unstableWarningText, osgText::Text::CENTER_CENTER, nullptr, -1.0, osg::Vec4(1.0, 0.0, 0.0, 1.0)); } @@ -460,6 +464,7 @@ void SplashScreen::doUpdate() } updateSplashSpinner(); + updateText(); } } @@ -509,6 +514,26 @@ void SplashScreen::updateSplashSpinner() _splashSpinnerVertexArray->dirty(); } +void SplashScreen::updateText() +{ + if (!_haveSetStartupTip && (_splashStartTime.elapsedMSec() > 5000)) { + // switch to show tooltip + _haveSetStartupTip = true; + FGLocale* locale = globals->get_locale(); + const int tipCount = locale->getLocalizedStringCount("tip", "tips"); + + time_t now; + ::time(&now); + struct tm* currentTime = ::localtime(&now); + int tipIndex = currentTime->tm_yday % tipCount; + + std::string tipText = locale->getLocalizedStringWithIndex("tip", "tips", tipIndex); + + // find the item to switch + _items.front().textNode->setText(tipText); + } +} + // remove once we require OSG 3.4 void SplashScreen::manuallyResizeFBO(int width, int height) { diff --git a/src/Viewer/splash.hxx b/src/Viewer/splash.hxx index 4969ab5bf..7108c85e5 100644 --- a/src/Viewer/splash.hxx +++ b/src/Viewer/splash.hxx @@ -56,7 +56,8 @@ private: void doUpdate(); void updateSplashSpinner(); - + void updateText(); + std::string selectSplashImage(); void addText(osg::Geode* geode, const osg::Vec2& pos, double size, const std::string& text, @@ -99,6 +100,7 @@ private: std::vector _items; SGTimeStamp _splashStartTime; + bool _haveSetStartupTip = false; }; /** Set progress information.