forked from organicmaps/organicmaps
added strings localization mechanism and used it in CountryStatusDisplay.
This commit is contained in:
parent
1bd70241ca
commit
966d2a6f62
12 changed files with 293 additions and 36 deletions
|
@ -26,6 +26,8 @@ SOURCES += \
|
|||
threaded_container.cpp \
|
||||
resource_pool.cpp \
|
||||
fence_manager.cpp \
|
||||
strings_bundle.cpp \
|
||||
string_format.cpp \
|
||||
|
||||
HEADERS += \
|
||||
SRC_FIRST.hpp \
|
||||
|
@ -73,3 +75,5 @@ HEADERS += \
|
|||
threaded_priority_queue.hpp \
|
||||
std_serialization.hpp \
|
||||
fence_manager.hpp \
|
||||
strings_bundle.hpp \
|
||||
string_format.hpp \
|
||||
|
|
|
@ -33,9 +33,10 @@ SOURCES += \
|
|||
threaded_list_test.cpp \
|
||||
condition_test.cpp \
|
||||
containers_test.cpp \
|
||||
fence_manager_test.cpp
|
||||
|
||||
fence_manager_test.cpp \
|
||||
string_format_test.cpp \
|
||||
|
||||
HEADERS +=
|
||||
|
||||
|
||||
|
||||
|
|
11
base/base_tests/string_format_test.cpp
Normal file
11
base/base_tests/string_format_test.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "../../testing/testing.hpp"
|
||||
#include "../string_format.hpp"
|
||||
|
||||
UNIT_TEST(StringFormat_Smoke)
|
||||
{
|
||||
TEST_EQUAL(strings::Format("this is % % % %", "a", "very", "simple", "test"), "this is a very simple test", ());
|
||||
|
||||
TEST_EQUAL(strings::Format("this", "a"), "this", ());
|
||||
|
||||
TEST_EQUAL(strings::Format("this % %", "is"), "this is %", ());
|
||||
}
|
53
base/string_format.cpp
Normal file
53
base/string_format.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "string_format.hpp"
|
||||
#include "logging.hpp"
|
||||
|
||||
namespace strings
|
||||
{
|
||||
string const FormatImpl(string const & s, list<string> const & l)
|
||||
{
|
||||
size_t offs = 0;
|
||||
list<size_t> fieldOffs;
|
||||
|
||||
string temp = s;
|
||||
|
||||
LOG(LINFO, (s));
|
||||
|
||||
while (true)
|
||||
{
|
||||
offs = temp.find("%", offs);
|
||||
if (offs == string::npos)
|
||||
break;
|
||||
else
|
||||
{
|
||||
if ((offs != 0) && (temp[offs - 1] == '\\'))
|
||||
{
|
||||
temp = temp.erase(offs - 1, 1);
|
||||
--offs;
|
||||
}
|
||||
else
|
||||
fieldOffs.push_back(offs);
|
||||
|
||||
++offs;
|
||||
}
|
||||
}
|
||||
|
||||
offs = 0;
|
||||
|
||||
string res = temp;
|
||||
|
||||
list<size_t>::const_iterator offsIt;
|
||||
list<string>::const_iterator strIt;
|
||||
|
||||
for (offsIt = fieldOffs.begin(), strIt = l.begin();
|
||||
(offsIt != fieldOffs.end()) && (strIt != l.end());
|
||||
++offsIt, ++strIt)
|
||||
{
|
||||
res.replace(*offsIt + offs, 1, *strIt);
|
||||
offs += strIt->size() - 1;
|
||||
}
|
||||
|
||||
LOG(LINFO, (res));
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
73
base/string_format.hpp
Normal file
73
base/string_format.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
#include "../std/string.hpp"
|
||||
#include "../std/sstream.hpp"
|
||||
#include "../std/list.hpp"
|
||||
|
||||
namespace strings
|
||||
{
|
||||
template <typename T>
|
||||
string ToString(T t)
|
||||
{
|
||||
ostringstream out;
|
||||
out << t;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
string const FormatImpl(string const & s, list<string> const & l);
|
||||
|
||||
template <typename T1>
|
||||
string const Format(string const & s, T1 const & t1)
|
||||
{
|
||||
list<string> l;
|
||||
l.push_back(ToString(t1));
|
||||
|
||||
return FormatImpl(s, l);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
string const Format(string const & s, T1 const & t1, T2 const & t2)
|
||||
{
|
||||
list<string> l;
|
||||
l.push_back(ToString(t1));
|
||||
l.push_back(ToString(t2));
|
||||
|
||||
return FormatImpl(s, l);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
string const Format(string const & s, T1 const & t1, T2 const & t2, T3 const & t3)
|
||||
{
|
||||
list<string> l;
|
||||
l.push_back(ToString(t1));
|
||||
l.push_back(ToString(t2));
|
||||
l.push_back(ToString(t3));
|
||||
|
||||
return FormatImpl(s, l);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
string const Format(string const & s, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4)
|
||||
{
|
||||
list<string> l;
|
||||
l.push_back(ToString(t1));
|
||||
l.push_back(ToString(t2));
|
||||
l.push_back(ToString(t3));
|
||||
l.push_back(ToString(t4));
|
||||
|
||||
return FormatImpl(s, l);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
string const Format(string const & s, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5)
|
||||
{
|
||||
list<string> l;
|
||||
l.push_back(ToString(t1));
|
||||
l.push_back(ToString(t2));
|
||||
l.push_back(ToString(t3));
|
||||
l.push_back(ToString(t4));
|
||||
l.push_back(ToString(t5));
|
||||
|
||||
return FormatImpl(s, l);
|
||||
}
|
||||
}
|
30
base/strings_bundle.cpp
Normal file
30
base/strings_bundle.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "strings_bundle.hpp"
|
||||
|
||||
void StringsBundle::SetDefaultString(string const & name, string const & value)
|
||||
{
|
||||
m_defValues[name] = value;
|
||||
}
|
||||
|
||||
void StringsBundle::SetString(string const & name, string const & value)
|
||||
{
|
||||
m_values[name] = value;
|
||||
}
|
||||
|
||||
string const StringsBundle::GetString(string const & name) const
|
||||
{
|
||||
TStringMap::const_iterator it = m_values.find(name);
|
||||
if (it != m_values.end())
|
||||
return it->second;
|
||||
else
|
||||
{
|
||||
it = m_defValues.find(name);
|
||||
if (it != m_defValues.end())
|
||||
return it->second;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string const FormatString(char const * msg, ...)
|
||||
{
|
||||
return "";
|
||||
}
|
23
base/strings_bundle.hpp
Normal file
23
base/strings_bundle.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "../std/string.hpp"
|
||||
#include "../std/map.hpp"
|
||||
|
||||
class StringsBundle
|
||||
{
|
||||
private:
|
||||
|
||||
typedef map<string, string> TStringMap;
|
||||
TStringMap m_values;
|
||||
TStringMap m_defValues;
|
||||
|
||||
public:
|
||||
|
||||
void SetDefaultString(string const & name, string const & value);
|
||||
void SetString(string const & name, string const & value);
|
||||
string const GetString(string const & name) const;
|
||||
};
|
||||
|
||||
string const & FormatString(string const & msg);
|
||||
|
||||
|
|
@ -157,4 +157,22 @@ namespace gui
|
|||
{
|
||||
return m_GlyphCache;
|
||||
}
|
||||
|
||||
void Controller::SetStringsBundle(StringsBundle const * bundle)
|
||||
{
|
||||
m_bundle = bundle;
|
||||
|
||||
for (elem_list_t::const_iterator it = m_Elements.begin();
|
||||
it != m_Elements.end();
|
||||
++it)
|
||||
{
|
||||
(*it)->setIsDirtyRect(true);
|
||||
(*it)->setIsDirtyDrawing(true);
|
||||
}
|
||||
}
|
||||
|
||||
StringsBundle const * Controller::GetStringsBundle() const
|
||||
{
|
||||
return m_bundle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,16 @@
|
|||
#include "../std/shared_ptr.hpp"
|
||||
#include "../std/function.hpp"
|
||||
#include "../std/list.hpp"
|
||||
#include "../yg/overlay.hpp"
|
||||
|
||||
#include "../geometry/point2d.hpp"
|
||||
|
||||
#include "../base/strings_bundle.hpp"
|
||||
|
||||
namespace yg
|
||||
{
|
||||
class GlyphCache;
|
||||
class OverlayElement;
|
||||
|
||||
namespace gl
|
||||
{
|
||||
class Screen;
|
||||
|
@ -48,6 +54,9 @@ namespace gui
|
|||
/// GlyphCache for text rendering by GUI elements.
|
||||
yg::GlyphCache * m_GlyphCache;
|
||||
|
||||
/// Localized strings for GUI.
|
||||
StringsBundle const * m_bundle;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor with GestureDetector to route events from.
|
||||
|
@ -76,6 +85,8 @@ namespace gui
|
|||
|
||||
/// Attach GUI Controller to the renderer
|
||||
void SetRenderParams(RenderParams const & p);
|
||||
/// Set the bundle with localized strings
|
||||
void SetStringsBundle(StringsBundle const * bundle);
|
||||
/// Detach GUI Controller from the renderer
|
||||
void ResetRenderParams();
|
||||
/// Invalidate the scene
|
||||
|
@ -86,6 +97,8 @@ namespace gui
|
|||
void AddElement(shared_ptr<Element> const & e);
|
||||
/// Get VisualScale parameter
|
||||
double GetVisualScale() const;
|
||||
/// Get localized strings bundle
|
||||
StringsBundle const * GetStringsBundle() const;
|
||||
/// Get GLyphCache
|
||||
yg::GlyphCache * GetGlyphCache() const;
|
||||
/// Redraw GUI
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "../std/bind.hpp"
|
||||
#include "../std/sstream.hpp"
|
||||
|
||||
#include "../base/string_format.hpp"
|
||||
|
||||
#include "../storage/storage.hpp"
|
||||
|
||||
#include "../yg/overlay_renderer.hpp"
|
||||
|
@ -23,8 +25,27 @@ void CountryStatusDisplay::cache()
|
|||
|
||||
m_statusMsg->setIsVisible(false);
|
||||
|
||||
string const dn = displayName();
|
||||
strings::UniString s(strings::MakeUniString(dn));
|
||||
string dn = displayName();
|
||||
strings::UniString udn(strings::MakeUniString(dn));
|
||||
|
||||
StringsBundle const * stringsBundle = m_controller->GetStringsBundle();
|
||||
|
||||
string prefixedName;
|
||||
string postfixedName;
|
||||
|
||||
if (udn.size() > 13)
|
||||
{
|
||||
if (strings::MakeUniString(m_mapName).size() > 13)
|
||||
dn = m_mapName + "\n" + "(" + m_mapGroupName + ")";
|
||||
|
||||
prefixedName = "\n" + dn;
|
||||
postfixedName = dn + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
prefixedName = " " + dn;
|
||||
postfixedName = dn + " ";
|
||||
}
|
||||
|
||||
if (m_countryIdx != storage::TIndex())
|
||||
{
|
||||
|
@ -33,15 +54,9 @@ void CountryStatusDisplay::cache()
|
|||
case storage::EInQueue:
|
||||
{
|
||||
m_statusMsg->setIsVisible(true);
|
||||
string countryStatusAddedToQueue = stringsBundle->GetString("country_status_added_to_queue");
|
||||
|
||||
ostringstream out;
|
||||
|
||||
if (s.size() > 13)
|
||||
out << dn << "\nis added to the\ndownloading queue";
|
||||
else
|
||||
out << dn << " is added to the\ndownloading queue";
|
||||
|
||||
m_statusMsg->setText(out.str());
|
||||
m_statusMsg->setText(strings::Format(countryStatusAddedToQueue, postfixedName));
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -49,44 +64,29 @@ void CountryStatusDisplay::cache()
|
|||
{
|
||||
m_statusMsg->setIsVisible(true);
|
||||
|
||||
ostringstream out;
|
||||
int percent = m_countryProgress.first * 100 / m_countryProgress.second;
|
||||
|
||||
if (s.size() > 13)
|
||||
out << "Downloading\n" << dn;
|
||||
else
|
||||
out << "Downloading " << dn;
|
||||
|
||||
out << "(" << m_countryProgress.first * 100 / m_countryProgress.second << "%)";
|
||||
|
||||
m_statusMsg->setText(out.str());
|
||||
string countryStatusDownloading = stringsBundle->GetString("country_status_downloading");
|
||||
m_statusMsg->setText(strings::Format(countryStatusDownloading, prefixedName, percent));
|
||||
}
|
||||
break;
|
||||
case storage::ENotDownloaded:
|
||||
{
|
||||
m_downloadButton->setIsVisible(true);
|
||||
|
||||
if (s.size() > 13)
|
||||
m_downloadButton->setText("Download\n" + dn);
|
||||
else
|
||||
m_downloadButton->setText("Download " + dn);
|
||||
string countryStatusDownload = stringsBundle->GetString("country_status_download");
|
||||
m_downloadButton->setText(strings::Format(countryStatusDownload, prefixedName));
|
||||
}
|
||||
break;
|
||||
case storage::EDownloadFailed:
|
||||
{
|
||||
m_downloadButton->setIsVisible(true);
|
||||
m_downloadButton->setText("Try again");
|
||||
m_downloadButton->setText(stringsBundle->GetString("try_again"));
|
||||
|
||||
ostringstream out;
|
||||
|
||||
if (s.size() > 13)
|
||||
out << "Downloading\n" << dn;
|
||||
else
|
||||
out << "Downloading " << dn;
|
||||
|
||||
out << "\nhas failed.";
|
||||
string countryStatusDownloadFailed = stringsBundle->GetString("country_status_download_failed");
|
||||
m_statusMsg->setText(strings::Format(countryStatusDownloadFailed, prefixedName));
|
||||
|
||||
m_statusMsg->setIsVisible(true);
|
||||
m_statusMsg->setText(out.str());
|
||||
|
||||
setPivot(pivot());
|
||||
}
|
||||
|
|
|
@ -121,6 +121,10 @@ Framework::Framework()
|
|||
{
|
||||
m_guiController.reset(new gui::Controller());
|
||||
|
||||
SetStringsBundle(GetDefaultStringsBundle());
|
||||
|
||||
m_guiController->SetStringsBundle(&m_stringsBundle);
|
||||
|
||||
m_informationDisplay.setController(m_guiController.get());
|
||||
|
||||
#ifdef DRAW_TOUCH_POINTS
|
||||
|
@ -971,6 +975,25 @@ gui::Controller * Framework::GetGuiController() const
|
|||
return m_guiController.get();
|
||||
}
|
||||
|
||||
StringsBundle const Framework::GetDefaultStringsBundle() const
|
||||
{
|
||||
StringsBundle res;
|
||||
|
||||
res.SetDefaultString("country_status_added_to_queue", "%is added to the\ndownloading queue.");
|
||||
res.SetDefaultString("country_status_downloading", "Downloading%(%\\%)");
|
||||
res.SetDefaultString("country_status_download", "Download%");
|
||||
res.SetDefaultString("country_status_download_failed", "Downloading%\nhas failed");
|
||||
res.SetDefaultString("try_again", "Try Again");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Framework::SetStringsBundle(StringsBundle const & bundle)
|
||||
{
|
||||
m_stringsBundle = bundle;
|
||||
m_guiController->SetStringsBundle(&m_stringsBundle);
|
||||
}
|
||||
|
||||
bool Framework::SetViewportByURL(string const & url)
|
||||
{
|
||||
using namespace url_scheme;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "../base/logging.hpp"
|
||||
//#include "../base/mutex.hpp"
|
||||
#include "../base/timer.hpp"
|
||||
#include "../base/strings_bundle.hpp"
|
||||
|
||||
#include "../std/vector.hpp"
|
||||
#include "../std/shared_ptr.hpp"
|
||||
|
@ -62,6 +63,9 @@ class CountryStatusDisplay;
|
|||
class Framework
|
||||
{
|
||||
protected:
|
||||
|
||||
StringsBundle m_stringsBundle;
|
||||
|
||||
mutable scoped_ptr<search::Engine> m_pSearchEngine;
|
||||
model::FeaturesFetcher m_model;
|
||||
Navigator m_navigator;
|
||||
|
@ -291,6 +295,10 @@ public:
|
|||
|
||||
gui::Controller * GetGuiController() const;
|
||||
|
||||
/// Set the localized strings bundle
|
||||
void SetStringsBundle(StringsBundle const & bundle);
|
||||
StringsBundle const GetDefaultStringsBundle() const;
|
||||
|
||||
private:
|
||||
//bool IsEmptyModel() const;
|
||||
bool IsEmptyModel(m2::PointD const & pt);
|
||||
|
|
Loading…
Add table
Reference in a new issue