added strings localization mechanism and used it in CountryStatusDisplay.

This commit is contained in:
rachytski 2012-06-05 21:38:15 +04:00 committed by Alex Zolotarev
parent 1bd70241ca
commit 966d2a6f62
12 changed files with 293 additions and 36 deletions

View file

@ -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 \

View file

@ -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 +=

View 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
View 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
View 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
View 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
View 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);

View file

@ -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;
}
}

View file

@ -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

View file

@ -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());
}

View file

@ -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;

View file

@ -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);