diff --git a/specter/CMakeLists.txt b/specter/CMakeLists.txt index 74d62b2bc..e65d50391 100644 --- a/specter/CMakeLists.txt +++ b/specter/CMakeLists.txt @@ -32,6 +32,7 @@ include_directories(include ${HECL_INCLUDE_DIR} ${BOO_INCLUDE_DIR} list(APPEND SPECTER_HEADERS include/Specter/Specter.hpp include/Specter/ViewResources.hpp + include/Specter/IViewManager.hpp include/Specter/DeferredWindowEvents.hpp include/Specter/View.hpp include/Specter/RootView.hpp diff --git a/specter/include/Specter/FileBrowser.hpp b/specter/include/Specter/FileBrowser.hpp index 9ccadab23..e5174f639 100644 --- a/specter/include/Specter/FileBrowser.hpp +++ b/specter/include/Specter/FileBrowser.hpp @@ -8,6 +8,7 @@ #include "ScrollView.hpp" #include "Table.hpp" #include "ViewResources.hpp" +#include "IViewManager.hpp" #include namespace Specter @@ -68,13 +69,14 @@ private: { FileBrowser& m_fb; ViewChild> m_button; - CancelButton(FileBrowser& fb, ViewResources& res) - : m_fb(fb) + std::string m_text; + CancelButton(FileBrowser& fb, ViewResources& res, const std::string& text) + : m_fb(fb), m_text(text) { - m_button.m_view.reset(new Button(res, fb, this, "Cancel", Button::Style::Block, - RectangleConstraint(100 * res.pixelFactor(), -1, RectangleConstraint::Test::Minimum))); + m_button.m_view.reset(new Button(res, fb, this, text, Button::Style::Block, + RectangleConstraint(m_fb.m_ok.m_button.m_view->nominalWidth(), -1, RectangleConstraint::Test::Minimum))); } - const char* name() const {return "Cancel";} + const char* name() const {return m_text.c_str();} void activated(const boo::SWindowCoord&) {m_fb.cancelActivated();} } m_cancel; @@ -101,8 +103,10 @@ private: struct FileFieldBind : IStringBinding { FileBrowser& m_browser; - FileFieldBind(FileBrowser& browser) : m_browser(browser) {} - const char* name() const {return "File Name";} + std::string m_name; + FileFieldBind(FileBrowser& browser, const IViewManager& vm) + : m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {} + const char* name() const {return m_name.c_str();} void changed(const std::string& val) { } @@ -119,9 +123,12 @@ private: }; std::vector m_entries; - std::string m_nameCol = "Name"; - std::string m_typeCol = "Type"; - std::string m_sizeCol = "Size"; + std::string m_nameCol; + std::string m_typeCol; + std::string m_sizeCol; + + std::string m_dirStr; + std::string m_fileStr; size_t columnCount() const {return 3;} size_t rowCount() const {return m_entries.size();} @@ -169,16 +176,25 @@ private: HECL::SystemUTF8View nameUtf8(d.m_name); ent.m_name = nameUtf8.str(); if (d.m_isDir) - ent.m_type = "Directory"; + ent.m_type = m_dirStr; else { - ent.m_type = "File"; + ent.m_type = m_fileStr; ent.m_size = HECL::HumanizeNumber(d.m_fileSz, 7, nullptr, int(HECL::HNScale::AutoScale), HECL::HNFlags::B | HECL::HNFlags::Decimal); } } } + FileListingDataBind(const IViewManager& vm) + { + m_nameCol = vm.translateOr("name", "Name"); + m_typeCol = vm.translateOr("type", "Type"); + m_sizeCol = vm.translateOr("size", "Size"); + m_dirStr = vm.translateOr("directory", "Directory"); + m_fileStr = vm.translateOr("file", "File"); + } + } m_fileListingBind; ViewChild> m_fileListing; diff --git a/specter/include/Specter/IViewManager.hpp b/specter/include/Specter/IViewManager.hpp new file mode 100644 index 000000000..13b3d203c --- /dev/null +++ b/specter/include/Specter/IViewManager.hpp @@ -0,0 +1,24 @@ +#ifndef SPECTER_IVIEWMANAGER_HPP +#define SPECTER_IVIEWMANAGER_HPP + +#include "Translator.hpp" + +namespace Specter +{ + +struct IViewManager +{ +public: + virtual const Translator* getTranslator() const {return nullptr;} + virtual std::string translateOr(const std::string& key, const char* vor) const + { + const Translator* trans = getTranslator(); + if (trans) + return trans->translateOr(key, vor); + return vor; + } +}; + +} + +#endif // SPECTER_IVIEWMANAGER_HPP diff --git a/specter/include/Specter/RootView.hpp b/specter/include/Specter/RootView.hpp index 1d09b1986..03f149f96 100644 --- a/specter/include/Specter/RootView.hpp +++ b/specter/include/Specter/RootView.hpp @@ -9,15 +9,12 @@ #include "Tooltip.hpp" #include "FontCache.hpp" #include "DeferredWindowEvents.hpp" +#include "IViewManager.hpp" #include namespace Specter { -struct IViewManager -{ -}; - class RootView : public View { boo::IWindow* m_window = nullptr; diff --git a/specter/include/Specter/Translator.hpp b/specter/include/Specter/Translator.hpp index 400e32eef..a7f23b83b 100644 --- a/specter/include/Specter/Translator.hpp +++ b/specter/include/Specter/Translator.hpp @@ -12,12 +12,13 @@ class Locale std::string m_name; std::string m_fullName; std::unique_ptr m_rootNode; + const Athena::io::YAMLNode* m_langNode; public: Locale(const std::string& name, const std::string& fullName, const unsigned char* yamlSource, size_t yamlLength); const std::string& name() const {return m_name;} const std::string& fullName() const {return m_fullName;} - const Athena::io::YAMLNode& rootNode() const {return *m_rootNode;} + const Athena::io::YAMLNode& rootNode() const {return *m_langNode;} }; class Translator @@ -26,7 +27,8 @@ class Translator public: Translator(const Locale* targetLocale) {setLocale(targetLocale);} void setLocale(const Locale* targetLocale); - const std::string* translate(const std::string& key); + const std::string* translate(const std::string& key) const; + std::string translateOr(const std::string& key, const char* vor) const; }; } diff --git a/specter/lib/FileBrowser.cpp b/specter/lib/FileBrowser.cpp index 6f3671a42..c8f131f5b 100644 --- a/specter/lib/FileBrowser.cpp +++ b/specter/lib/FileBrowser.cpp @@ -49,23 +49,25 @@ FileBrowser::FileBrowser(ViewResources& res, View& parentView, const std::string m_left(*this, res), m_right(*this, res), m_ok(*this, res, title), - m_cancel(*this, res), - m_fileFieldBind(*this) + m_cancel(*this, res, rootView().viewManager().translateOr("cancel", "Cancel")), + m_fileFieldBind(*this, rootView().viewManager()), + m_fileListingBind(rootView().viewManager()) { commitResources(res); setBackground({0,0,0,0.5}); + IViewManager& vm = rootView().viewManager(); m_fileField.m_view.reset(new TextField(res, *this, &m_fileFieldBind)); m_fileListing.m_view.reset(new Table(res, *this, &m_fileListingBind)); m_systemBookmarks.m_view.reset(new Table(res, *this, &m_systemBookmarkBind)); m_systemBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont)); - m_systemBookmarksLabel->typesetGlyphs("System Locations:", res.themeData().uiText()); + m_systemBookmarksLabel->typesetGlyphs(vm.translateOr("system_locations", "System Locations"), res.themeData().uiText()); m_projectBookmarks.m_view.reset(new Table(res, *this, &m_projectBookmarkBind)); m_projectBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont)); - m_projectBookmarksLabel->typesetGlyphs("Recent Projects:", res.themeData().uiText()); + m_projectBookmarksLabel->typesetGlyphs(vm.translateOr("recent_projects", "Recent Projects"), res.themeData().uiText()); m_recentBookmarks.m_view.reset(new Table(res, *this, &m_recentBookmarkBind)); m_recentBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont)); - m_recentBookmarksLabel->typesetGlyphs("Recent Files:", res.themeData().uiText()); + m_recentBookmarksLabel->typesetGlyphs(vm.translateOr("recent_files", "Recent Files"), res.themeData().uiText()); navigateToPath(initialPath); diff --git a/specter/lib/Translator.cpp b/specter/lib/Translator.cpp index 6a335619b..76e4ee921 100644 --- a/specter/lib/Translator.cpp +++ b/specter/lib/Translator.cpp @@ -15,6 +15,9 @@ Locale::Locale(const std::string& name, const std::string& fullName, yaml_parser_set_input_string(&parser, yamlSource, yamlLength); reader.read(&parser); m_rootNode = std::move(reader.releaseRootNode()); + m_langNode = m_rootNode->findMapChild(name.c_str()); + if (!m_langNode) + Log.report(LogVisor::FatalError, "no root node '%s' found in locale", name.c_str()); } void Translator::setLocale(const Locale* targetLocale) @@ -44,9 +47,17 @@ static const std::string* RecursiveLookup(const Athena::io::YAMLNode& node, return &ch->m_scalarString; } -const std::string* Translator::translate(const std::string& key) +const std::string* Translator::translate(const std::string& key) const { return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend()); } +std::string Translator::translateOr(const std::string& key, const char* vor) const +{ + const std::string* find = RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend()); + if (find) + return *find; + return vor; +} + }