[core] new way of bookmark, search results and api points store

This commit is contained in:
ExMix 2014-05-13 13:31:41 +03:00 committed by Alex Zolotarev
parent 6b4563e0d0
commit 369d5da247
17 changed files with 1113 additions and 544 deletions

View file

@ -71,14 +71,6 @@ extern "C"
}
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_getBookmark(
JNIEnv * env, jobject thiz, jdouble px, jdouble py)
{
BookmarkAndCategory const bac = frm()->GetBookmark(m2::PointD(px, py));
return jni::GetNewPoint(env, m2::PointI(bac.first, bac.second));
}
JNIEXPORT jstring JNICALL
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_saveToKMZFile(
JNIEnv * env, jobject thiz, jint catID, jstring tmpPath)

View file

@ -87,8 +87,6 @@ public class BookmarkManager
return new ArrayList<Icon>(BookmarkIconManager.getAll().values());
}
public static native Point getBookmark(double px, double py);
public Bookmark getBookmark(Pair<Integer, Integer> catAndBmk)
{
return getBookmark(catAndBmk.first, catAndBmk.second);

View file

@ -139,6 +139,12 @@ GetRangeDeletor(TContainer & cont, TDeletor const & deletor)
return impl::DeleteRangeFunctor<TContainer, TDeletor>(cont, deletor);
}
template <class TContainer, class TDeletor>
void DeleteRange(TContainer & cont, TDeletor const & deletor)
{
(void)GetRangeDeletor(cont, deletor)();
}
struct NoopFunctor
{
template <typename T> void operator () (T const &) const

View file

@ -18,7 +18,8 @@ namespace graphics
static const int balloonBaseDepth = countryStatusDepth - (balloonContentInc + 10);
static const int locationDepth = balloonBaseDepth - 10;
static const int activePinDepth = locationDepth - 10;
static const int poiAndBookmarkDepth = activePinDepth - 10;
static const int tracksDepth = poiAndBookmarkDepth - 10;
static const int poiDepth = locationDepth - 10;
static const int bookmarkDepth = poiDepth;
static const int tracksDepth = bookmarkDepth - 10;
static const int activePinDepth = tracksDepth - 10;
}

View file

@ -1,6 +1,8 @@
#include "bookmark.hpp"
#include "track.hpp"
#include "../graphics/depth_constants.hpp"
#include "../indexer/mercator.hpp"
#include "../coding/file_reader.hpp"
@ -27,34 +29,24 @@ Track const * BookmarkCategory::GetTrack(size_t index) const
return (index < m_tracks.size() ? m_tracks[index] : 0);
}
void BookmarkCategory::AddBookmark(Bookmark const & bm)
void BookmarkCategory::AddBookmark(m2::PointD const & ptOrg, BookmarkCustomData const & bm)
{
Bookmark * p = new Bookmark(bm);
m_bookmarks.push_back(p);
UserMark * mark = base_t::GetController().CreateUserMark(ptOrg);
mark->InjectCustomData(new BookmarkCustomData(bm));
}
void BookmarkCategory::ReplaceBookmark(size_t index, Bookmark const & bm)
void BookmarkCategory::ReplaceBookmark(size_t index, BookmarkCustomData const & bm)
{
ASSERT_LESS ( index, m_bookmarks.size(), () );
if (index < m_bookmarks.size())
{
Bookmark * p = new Bookmark(bm);
AssignPrivateParams(index, *p);
delete m_bookmarks[index];
m_bookmarks[index] = p;
}
Controller c = base_t::GetController();
ASSERT_LESS (index, c.GetUserMarkCount(), ());
if (index < c.GetUserMarkCount())
base_t::GetController().EditUserMark(index, new BookmarkCustomData(bm));
}
void BookmarkCategory::AssignPrivateParams(size_t index, Bookmark & bm) const
BookmarkCategory::BookmarkCategory(const string & name, Framework & framework)
: base_t(UserMarkContainer::BOOKMARK_MARK, graphics::bookmarkDepth, framework)
, m_name(name)
{
ASSERT_LESS ( index, m_bookmarks.size(), () );
if (index < m_bookmarks.size())
{
Bookmark const * p = m_bookmarks[index];
bm.SetTimeStamp(p->GetTimeStamp());
bm.SetScale(p->GetScale());
}
}
BookmarkCategory::~BookmarkCategory()
@ -65,8 +57,7 @@ BookmarkCategory::~BookmarkCategory()
void BookmarkCategory::ClearBookmarks()
{
for_each(m_bookmarks.begin(), m_bookmarks.end(), DeleteFunctor());
m_bookmarks.clear();
base_t::Clear();
}
void BookmarkCategory::ClearTracks()
@ -95,7 +86,9 @@ template <class T> void DeleteItem(vector<T> & v, size_t i)
void BookmarkCategory::DeleteBookmark(size_t index)
{
DeleteItem(m_bookmarks, index);
base_t::Controller c = base_t::GetController();
ASSERT_LESS(index, c.GetUserMarkCount(), ());
c.DeleteUserMark(index);
}
void BookmarkCategory::DeleteTrack(size_t index)
@ -103,14 +96,21 @@ void BookmarkCategory::DeleteTrack(size_t index)
DeleteItem(m_tracks, index);
}
size_t BookmarkCategory::GetBookmarksCount() const
{
return base_t::GetController().GetUserMarkCount();
}
Bookmark const * BookmarkCategory::GetBookmark(size_t index) const
{
return (index < m_bookmarks.size() ? m_bookmarks[index] : 0);
base_t::Controller const & c = base_t::GetController();
return (Bookmark *)(index < c.GetUserMarkCount() ? c.GetUserMark(index) : 0);
}
Bookmark * BookmarkCategory::GetBookmark(size_t index)
{
return (index < m_bookmarks.size() ? m_bookmarks[index] : 0);
base_t::Controller & c = base_t::GetController();
return (Bookmark *)(index < c.GetUserMarkCount() ? c.GetUserMark(index) : 0);
}
namespace
@ -344,13 +344,7 @@ namespace
if (MakeValid())
{
if (POINT == m_geometryType)
{
Bookmark bm(m_org, m_name, m_type);
bm.SetTimeStamp(m_timeStamp);
bm.SetDescription(m_description);
bm.SetScale(m_scale);
m_category.AddBookmark(bm);
}
m_category.AddBookmark(m_org, BookmarkCustomData(m_name, m_type, m_description, m_scale, m_timeStamp));
else if (LINE == m_geometryType)
{
Track track(m_points);
@ -509,9 +503,9 @@ bool BookmarkCategory::LoadFromKML(ReaderPtr<Reader> const & reader)
}
}
BookmarkCategory * BookmarkCategory::CreateFromKMLFile(string const & file)
BookmarkCategory * BookmarkCategory::CreateFromKMLFile(string const & file, Framework & framework)
{
auto_ptr<BookmarkCategory> cat(new BookmarkCategory(""));
auto_ptr<BookmarkCategory> cat(new BookmarkCategory("", framework));
try
{
if (cat->LoadFromKML(new FileReader(file)))
@ -620,9 +614,9 @@ void BookmarkCategory::SaveToKML(ostream & s)
s << " <visibility>" << (IsVisible() ? "1" : "0") <<"</visibility>\n";
for (size_t i = 0; i < m_bookmarks.size(); ++i)
for (size_t i = 0; i < GetBookmarksCount(); ++i)
{
Bookmark const * bm = m_bookmarks[i];
Bookmark const * bm = GetBookmark(i);
s << " <Placemark>\n";
s << " <name>";
SaveStringWithCDATA(s, bm->GetName());

View file

@ -1,5 +1,8 @@
#pragma once
#include "user_mark.hpp"
#include "user_mark_container.hpp"
#include "../coding/reader.hpp"
#include "../geometry/point2d.hpp"
@ -14,61 +17,106 @@
class Track;
class Bookmark
class BookmarkCustomData : public UserCustomData
{
m2::PointD m_org;
string m_name;
string m_description;
string m_type; ///< Now it stores bookmark color (category style).
double m_scale; ///< Viewport scale. -1.0 - is a default value (no scale set).
time_t m_timeStamp;
public:
Bookmark() : m_scale(-1.0), m_timeStamp(my::INVALID_TIME_STAMP) {}
Bookmark(m2::PointD const & org, string const & name, string const & type)
: m_org(org), m_name(name), m_type(type), m_scale(-1.0), m_timeStamp(my::INVALID_TIME_STAMP)
BookmarkCustomData(string const & name, string const & type,
string const & description = "", double scale = -1.0,
time_t timeStamp = my::INVALID_TIME_STAMP)
: m_name(name)
, m_description(description)
, m_type(type)
, m_scale(scale)
, m_timeStamp(timeStamp)
{
}
m2::PointD const & GetOrg() const { return m_org; }
virtual Type GetType() const { return BOOKMARK; }
string const & GetName() const { return m_name; }
//void SetName(string const & name) { m_name = name; }
/// @return Now its a bookmark color - name of icon file
string const & GetType() const { return m_type; }
//void SetType(string const & type) { m_type = type; }
m2::RectD GetViewport() const { return m2::RectD(m_org, m_org); }
void SetName(const string & name) { m_name = name; }
string const & GetDescription() const { return m_description; }
void SetDescription(string const & description) { m_description = description; }
void SetDescription(const string & description) { m_description = description; }
/// @return my::INVALID_TIME_STAMP if bookmark has no timestamp
time_t GetTimeStamp() const { return m_timeStamp; }
void SetTimeStamp(time_t timeStamp) { m_timeStamp = timeStamp; }
string const & GetTypeName() const { return m_type; }
void SetTypeName(const string & type) { m_type = type; }
double GetScale() const { return m_scale; }
double const & GetScale() const { return m_scale; }
void SetScale(double scale) { m_scale = scale; }
time_t const & GetTimeStamp() const { return m_timeStamp; }
void SetTimeStamp(const time_t & timeStamp) { m_timeStamp = timeStamp; }
private:
string m_name;
string m_description;
string m_type; ///< Now it stores bookmark color (category style).
double m_scale; ///< Viewport scale. -1.0 - is a default value (no scale set).
time_t m_timeStamp;
};
class BookmarkCategory : private noncopyable
class Bookmark : public UserMark
{
public:
Bookmark(UserMarkContainer * container)
: UserMark(m2::PointD(0.0, 0.0), container)
{
Inject();
}
m2::PointD const & GetOrg() const { return UserMark::GetOrg(); }
string const & GetName() const { return GetData()->GetName(); }
//void SetName(string const & name) { m_name = name; }
/// @return Now its a bookmark color - name of icon file
string const & GetType() const { return GetData()->GetTypeName(); }
//void SetType(string const & type) { m_type = type; }
m2::RectD GetViewport() const { return m2::RectD(GetOrg(), GetOrg()); }
string const & GetDescription() const { return GetData()->GetDescription(); }
void SetDescription(string const & description) { GetData()->SetDescription(description); }
/// @return my::INVALID_TIME_STAMP if bookmark has no timestamp
time_t GetTimeStamp() const { return GetData()->GetTimeStamp(); }
void SetTimeStamp(time_t timeStamp) { GetData()->SetTimeStamp(timeStamp); }
double GetScale() const { return GetData()->GetScale(); }
void SetScale(double scale) { GetData()->SetScale(scale); }
private:
void Inject(m2::PointD const & org = m2::PointD(), string const & name = "",
string const & type = "", string const & descr = "",
double scale = -1, time_t timeStamp = my::INVALID_TIME_STAMP)
{
InjectCustomData(new BookmarkCustomData(name, descr, type, scale, timeStamp));
}
BookmarkCustomData * GetData()
{
return static_cast<BookmarkCustomData *>(&GetCustomData());
}
BookmarkCustomData const * GetData() const
{
return static_cast<BookmarkCustomData const *>(&GetCustomData());
}
};
class BookmarkCategory : public UserMarkContainer
{
typedef UserMarkContainer base_t;
/// @name Data
//@{
vector<Bookmark *> m_bookmarks;
/// TODO move track into UserMarkContainer as a IDrawable custom data
vector<Track *> m_tracks;
//@}
string m_name;
bool m_visible;
/// Stores file name from which category was loaded
string m_file;
/// This function is called when bookmark is editing or replacing.
/// We need to assign private params to the newly created bookmark from the old one.
void AssignPrivateParams(size_t index, Bookmark & bm) const;
public:
BookmarkCategory(string const & name) : m_name(name), m_visible(true) {}
BookmarkCategory(string const & name, Framework & framework);
~BookmarkCategory();
void ClearBookmarks();
@ -78,8 +126,8 @@ public:
/// @name Theese functions are called from Framework only.
//@{
void AddBookmark(Bookmark const & bm);
void ReplaceBookmark(size_t index, Bookmark const & bm);
void AddBookmark(m2::PointD const & ptOrg, BookmarkCustomData const & bm);
void ReplaceBookmark(size_t index, BookmarkCustomData const & bm);
//@}
/// @name Tracks routine.
@ -91,18 +139,14 @@ public:
void DeleteTrack(size_t index);
//@}
void SetVisible(bool isVisible) { m_visible = isVisible; }
bool IsVisible() const { return m_visible; }
void SetName(string const & name) { m_name = name; }
string const & GetName() const { return m_name; }
string const & GetFileName() const { return m_file; }
inline size_t GetBookmarksCount() const { return m_bookmarks.size(); }
size_t GetBookmarksCount() const;
Bookmark const * GetBookmark(size_t index) const;
Bookmark * GetBookmark(size_t index);
void DeleteBookmark(size_t index);
/// @name Theese fuctions are public for unit tests only.
@ -116,7 +160,7 @@ public:
bool SaveToKMLFile();
/// @return 0 in the case of error
static BookmarkCategory * CreateFromKMLFile(string const & file);
static BookmarkCategory * CreateFromKMLFile(string const & file, Framework & framework);
/// Get valid file name from input (remove illegal symbols).
static string RemoveInvalidSymbols(string const & name);

View file

@ -1,5 +1,8 @@
#include "bookmark_manager.hpp"
#include "framework.hpp"
#include "user_mark.hpp"
#include "../graphics/depth_constants.hpp"
#include "../platform/platform.hpp"
#include "../platform/settings.hpp"
@ -16,16 +19,24 @@
BookmarkManager::BookmarkManager(Framework & f)
: m_framework(f), m_bmScreen(0), m_lastScale(1.0)
: m_framework(f)
, m_activeMark(NULL)
, m_bmScreen(0)
, m_lastScale(1.0)
{
m_additionalPoiLayer = new BookmarkCategory("");
m_userMarkLayers.reserve(2);
m_userMarkLayers.push_back(new UserMarkContainer(UserMarkContainer::SEARCH_MARK, graphics::activePinDepth, m_framework));
m_userMarkLayers.push_back(new UserMarkContainer(UserMarkContainer::API_MARK, graphics::activePinDepth, m_framework));
UserMarkContainer::InitPoiSelectionMark(FindUserMarksContainer(UserMarkContainer::SEARCH_MARK));
}
BookmarkManager::~BookmarkManager()
{
delete m_additionalPoiLayer;
for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(), DeleteFunctor());
m_userMarkLayers.clear();
ClearItems();
DeleteScreen();
ResetScreen();
}
namespace
@ -116,6 +127,7 @@ public:
void BookmarkManager::DrawCategory(BookmarkCategory const * cat, shared_ptr<PaintEvent> const & e) const
{
/// TODO cutomize draw in UserMarkContainer for user Draw method
Navigator const & navigator = m_framework.GetNavigator();
InformationDisplay & informationDisplay = m_framework.GetInformationDisplay();
ScreenBase const & screen = navigator.Screen();
@ -141,7 +153,7 @@ void BookmarkManager::DrawCategory(BookmarkCategory const * cat, shared_ptr<Pain
m2::PointD const & org = bm->GetOrg();
if (glbRect.IsPointInside(org))
informationDisplay.drawPlacemark(pDrawer, bm->GetType().c_str(), navigator.GtoP(org));
informationDisplay.drawPlacemark(pDrawer, bm->GetType().c_str(), navigator.GtoP(org) + m2::PointD(0.0, 4.0));
}
}
@ -167,18 +179,18 @@ void BookmarkManager::LoadBookmarks()
void BookmarkManager::LoadBookmark(string const & filePath)
{
BookmarkCategory * cat = BookmarkCategory::CreateFromKMLFile(filePath);
BookmarkCategory * cat = BookmarkCategory::CreateFromKMLFile(filePath, m_framework);
if (cat)
m_categories.push_back(cat);
}
size_t BookmarkManager::AddBookmark(size_t categoryIndex, Bookmark & bm)
size_t BookmarkManager::AddBookmark(size_t categoryIndex, const m2::PointD & ptOrg, BookmarkCustomData & bm)
{
bm.SetTimeStamp(time(0));
bm.SetScale(m_framework.GetDrawScale());
BookmarkCategory * pCat = m_categories[categoryIndex];
pCat->AddBookmark(bm);
pCat->AddBookmark(ptOrg, bm);
pCat->SetVisible(true);
pCat->SaveToKMLFile();
@ -189,7 +201,7 @@ size_t BookmarkManager::AddBookmark(size_t categoryIndex, Bookmark & bm)
return (pCat->GetBookmarksCount() - 1);
}
void BookmarkManager::ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm)
void BookmarkManager::ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm)
{
BookmarkCategory * pCat = m_categories[catIndex];
pCat->ReplaceBookmark(bmIndex, bm);
@ -208,7 +220,7 @@ size_t BookmarkManager::LastEditedBMCategory()
}
if (m_categories.empty())
m_categories.push_back(new BookmarkCategory(m_framework.GetStringsBundle().GetString("my_places")));
m_categories.push_back(new BookmarkCategory(m_framework.GetStringsBundle().GetString("my_places"), m_framework));
return 0;
}
@ -225,7 +237,7 @@ BookmarkCategory * BookmarkManager::GetBmCategory(size_t index) const
size_t BookmarkManager::CreateBmCategory(string const & name)
{
m_categories.push_back(new BookmarkCategory(name));
m_categories.push_back(new BookmarkCategory(name, m_framework));
return (m_categories.size()-1);
}
@ -259,15 +271,15 @@ void BookmarkManager::DrawItems(shared_ptr<PaintEvent> const & e) const
graphics::Screen * pScreen = e->drawer()->screen();
pScreen->beginFrame();
PaintOverlayEvent event(e->drawer(), screen);
for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(), bind(&UserMarkContainer::Draw, _1, event));
for (size_t i = 0; i < m_categories.size(); ++i)
{
if (m_categories[i]->IsVisible())
DrawCategory(m_categories[i], e);
}
if (m_additionalPoiLayer->IsVisible())
DrawCategory(m_additionalPoiLayer, e);
pScreen->endFrame();
}
@ -293,48 +305,103 @@ bool BookmarkManager::DeleteBmCategory(size_t index)
return false;
}
void BookmarkManager::AdditionalPoiLayerSetInvisible()
void BookmarkManager::ActivateMark(UserMark const * mark)
{
m_additionalPoiLayer->SetVisible(false);
if (m_activeMark != NULL)
{
m_activeMark->Diactivate();
m_activeMark = NULL;
}
if (mark == NULL)
return;
m_activeMark = mark;
/// TODO remove this hack when resctuct Bookmark drawing code.
/// now it's need to activate bookmark element
UserCustomData const & data = m_activeMark->GetCustomData();
if (data.GetType() == UserCustomData::BOOKMARK)
{
m_activeMark = UserMarkContainer::UserMarkForPoi(mark->GetOrg());
BookmarkCustomData const & bookmarkData = static_cast<BookmarkCustomData const &>(data);
search::AddressInfo addrInfo;
m_framework.GetAddressInfoForGlobalPoint(mark->GetOrg(), addrInfo);
UserMark * hackMark = const_cast<UserMark *>(m_activeMark);
hackMark->InjectCustomData(new PoiCustomData(bookmarkData.GetName(),
bookmarkData.GetTypeName(),
addrInfo.FormatNameAndAddress()));
}
m_activeMark->Activate();
}
void BookmarkManager::AdditionalPoiLayerSetVisible()
UserMark const * BookmarkManager::FindNearestUserMark(const m2::AnyRectD & rect)
{
m_additionalPoiLayer->SetVisible(true);
double d = numeric_limits<double>::max();
UserMark const * mark = FindUserMarksContainer(UserMarkContainer::API_MARK)->FindMarkInRect(rect, d);
if (mark != NULL)
return mark;
mark = FindUserMarksContainer(UserMarkContainer::SEARCH_MARK)->FindMarkInRect(rect, d);
for (size_t i = 0; i < GetBmCategoriesCount(); ++i)
{
BookmarkCategory * category = GetBmCategory(i);
if (!category->IsVisible())
continue;
for (size_t j = 0; j < category->GetBookmarksCount(); ++ j)
{
Bookmark const * bookmark = category->GetBookmark(j);
m2::PointD bmOrg = bookmark->GetOrg();
if (rect.IsPointInside(bmOrg))
{
double currentD = rect.GetGlobalRect().Center().SquareLength(bmOrg);
if (currentD < d)
{
mark = bookmark;
d = currentD;
}
}
}
}
return mark;
}
void BookmarkManager::AdditionalPoiLayerAddPoi(Bookmark const & bm)
void BookmarkManager::UserMarksSetVisible(UserMarkContainer::Type type, bool isVisible)
{
m_additionalPoiLayer->AddBookmark(bm);
FindUserMarksContainer(type)->SetVisible(isVisible);
}
Bookmark const * BookmarkManager::AdditionalPoiLayerGetBookmark(size_t index) const
bool BookmarkManager::UserMarksIsVisible(UserMarkContainer::Type type) const
{
return m_additionalPoiLayer->GetBookmark(index);
return FindUserMarksContainer(type)->IsVisible();
}
Bookmark * BookmarkManager::AdditionalPoiLayerGetBookmark(size_t index)
UserMark * BookmarkManager::UserMarksAddMark(UserMarkContainer::Type type, const m2::PointD & ptOrg)
{
return m_additionalPoiLayer->GetBookmark(index);
return FindUserMarksContainer(type)->GetController().CreateUserMark(ptOrg);
}
void BookmarkManager::AdditionalPoiLayerClear()
void BookmarkManager::UserMarksClear(UserMarkContainer::Type type)
{
m_additionalPoiLayer->ClearBookmarks();
FindUserMarksContainer(type)->Clear();
}
bool BookmarkManager::IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const
UserMarkContainer::Controller & BookmarkManager::UserMarksGetController(UserMarkContainer::Type type)
{
return (bm.first == additionalLayerCategory && bm.second >= 0);
return FindUserMarksContainer(type)->GetController();
}
void BookmarkManager::SetScreen(graphics::Screen * screen)
{
DeleteScreen();
ResetScreen();
m_bmScreen = screen;
for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(),
bind(&UserMarkContainer::SetScreen, _1, m_bmScreen));
}
void BookmarkManager::DeleteScreen()
void BookmarkManager::ResetScreen()
{
if (m_bmScreen)
{
@ -343,7 +410,23 @@ void BookmarkManager::DeleteScreen()
for (size_t j = 0; j < m_categories[i]->GetTracksCount(); ++j)
m_categories[i]->GetTrack(j)->DeleteDisplayList();
delete m_bmScreen;
for (size_t i = 0; i < m_userMarkLayers.size(); ++i)
m_userMarkLayers[i]->SetScreen(0);
m_bmScreen = 0;
}
}
UserMarkContainer const * BookmarkManager::FindUserMarksContainer(UserMarkContainer::Type type) const
{
ASSERT(type >= 0 && type < m_userMarkLayers.size(), ());
ASSERT(m_userMarkLayers[(size_t)type]->GetType() == type, ());
return m_userMarkLayers[(size_t)type];
}
UserMarkContainer * BookmarkManager::FindUserMarksContainer(UserMarkContainer::Type type)
{
ASSERT(type >= 0 && type < m_userMarkLayers.size(), ());
ASSERT(m_userMarkLayers[(size_t)type]->GetType() == type, ());
return m_userMarkLayers[(size_t)type];
}

View file

@ -1,9 +1,6 @@
#pragma once
#include "bookmark.hpp"
/// Special number for additional layer category.
const int additionalLayerCategory = -2;
#include "user_mark_container.hpp"
class Framework;
class PaintEvent;
@ -18,7 +15,8 @@ class BookmarkManager : private noncopyable
Framework & m_framework;
BookmarkCategory * m_additionalPoiLayer;
vector<UserMarkContainer * > m_userMarkLayers;
UserMark const * m_activeMark;
graphics::Screen * m_bmScreen;
mutable double m_lastScale;
@ -41,8 +39,8 @@ public:
void LoadBookmark(string const & filePath);
/// Client should know where it adds bookmark
size_t AddBookmark(size_t categoryIndex, Bookmark & bm);
void ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm);
size_t AddBookmark(size_t categoryIndex, m2::PointD const & ptOrg, BookmarkCustomData & bm);
void ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm);
size_t LastEditedBMCategory();
string LastEditedBMType() const;
@ -60,17 +58,20 @@ public:
void DeleteBmCategory(CategoryIter i);
bool DeleteBmCategory(size_t index);
void ActivateMark(UserMark const * mark);
UserMark const * FindNearestUserMark(m2::AnyRectD const & rect);
/// Additional layer methods
void AdditionalPoiLayerSetInvisible();
void AdditionalPoiLayerSetVisible();
void AdditionalPoiLayerAddPoi(Bookmark const & bm);
Bookmark const * AdditionalPoiLayerGetBookmark(size_t index) const;
Bookmark * AdditionalPoiLayerGetBookmark(size_t index);
void AdditionalPoiLayerClear();
bool IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const;
bool AdditionalLayerIsVisible() const { return m_additionalPoiLayer->IsVisible(); }
size_t AdditionalLayerNumberOfPoi() const { return m_additionalPoiLayer->GetBookmarksCount(); }
void UserMarksSetVisible(UserMarkContainer::Type type, bool isVisible);
bool UserMarksIsVisible(UserMarkContainer::Type type) const;
UserMark * UserMarksAddMark(UserMarkContainer::Type type, m2::PointD const & ptOrg);
void UserMarksClear(UserMarkContainer::Type type);
UserMarkContainer::Controller & UserMarksGetController(UserMarkContainer::Type type);
void SetScreen(graphics::Screen * screen);
void DeleteScreen();
void ResetScreen();
private:
UserMarkContainer const * FindUserMarksContainer(UserMarkContainer::Type type) const;
UserMarkContainer * FindUserMarksContainer(UserMarkContainer::Type type);
};

View file

@ -1,6 +1,7 @@
#pragma once
#include "../base/commands_queue.hpp"
#include "../geometry/screenbase.hpp"
#include "../geometry/point2d.hpp"
@ -61,3 +62,17 @@ public:
bool isEmptyDrawing() const;
void setIsEmptyDrawing(bool flag);
};
class PaintOverlayEvent
{
public:
PaintOverlayEvent(Drawer * drawer, ScreenBase const & modelView)
: m_drawer(drawer), m_modelView(modelView) {}
ScreenBase const & GetModelView() const { return m_modelView; }
Drawer * GetDrawer() const { return m_drawer; }
private:
Drawer * m_drawer;
ScreenBase m_modelView;
};

View file

@ -193,6 +193,8 @@ Framework::Framework()
if (isBenchmarkingEnabled)
m_benchmarkEngine = new BenchmarkEngine(this);
m_ParsedMapApi.SetController(&m_bmManager.UserMarksGetController(UserMarkContainer::API_MARK));
// Init strings bundle.
m_stringsBundle.SetDefaultString("country_status_added_to_queue", "^is added to the downloading queue");
m_stringsBundle.SetDefaultString("country_status_downloading", "Downloading^^%");
@ -334,12 +336,12 @@ void Framework::LoadBookmarks()
m_bmManager.LoadBookmarks();
}
size_t Framework::AddBookmark(size_t categoryIndex, Bookmark & bm)
size_t Framework::AddBookmark(size_t categoryIndex, const m2::PointD & ptOrg, BookmarkCustomData & bm)
{
return m_bmManager.AddBookmark(categoryIndex, bm);
return m_bmManager.AddBookmark(categoryIndex, ptOrg, bm);
}
void Framework::ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm)
void Framework::ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm)
{
m_bmManager.ReplaceBookmark(catIndex, bmIndex, bm);
}
@ -373,71 +375,6 @@ bool Framework::DeleteBmCategory(size_t index)
return m_bmManager.DeleteBmCategory(index);
}
BookmarkAndCategory Framework::GetBookmark(m2::PointD const & pxPoint) const
{
return GetBookmark(pxPoint, GetVisualScale());
}
BookmarkAndCategory Framework::GetBookmark(m2::PointD const & pxPoint, double visualScale) const
{
// Get the global rect of touching area.
m2::AnyRectD rect;
m_navigator.GetTouchRect(pxPoint, TOUCH_PIXEL_RADIUS * visualScale, rect);
m2::PointD const center = rect.GlobalCenter();
int retBookmarkCategory = -1;
int retBookmark = -1;
double minD = numeric_limits<double>::max();
bool returnBookmarkIsVisible = false;
if (m_bmManager.AdditionalLayerIsVisible())
{
for (size_t i = 0; i < m_bmManager.AdditionalLayerNumberOfPoi(); ++i)
{
m2::PointD const pt = m_bmManager.AdditionalPoiLayerGetBookmark(i)->GetOrg();
if (rect.IsPointInside(pt))
{
double const d = center.SquareLength(pt);
if (d < minD)
{
retBookmarkCategory = static_cast<int>(additionalLayerCategory);
retBookmark = static_cast<int>(i);
minD = d;
}
}
}
}
for (size_t i = 0; i < m_bmManager.GetBmCategoriesCount(); ++i)
{
bool const currentCategoryIsVisible = m_bmManager.GetBmCategory(i)->IsVisible();
if (!currentCategoryIsVisible && returnBookmarkIsVisible)
continue;
size_t const count = m_bmManager.GetBmCategory(i)->GetBookmarksCount();
for (size_t j = 0; j < count; ++j)
{
Bookmark const * bm = m_bmManager.GetBmCategory(i)->GetBookmark(j);
m2::PointD const pt = bm->GetOrg();
if (rect.IsPointInside(pt))
{
double const d = center.SquareLength(pt);
if ((currentCategoryIsVisible && !returnBookmarkIsVisible) ||
(d < minD))
{
retBookmarkCategory = static_cast<int>(i);
retBookmark = static_cast<int>(j);
minD = d;
returnBookmarkIsVisible = m_bmManager.GetBmCategory(i)->IsVisible();
}
}
}
}
return make_pair(retBookmarkCategory, retBookmark);
}
void Framework::ShowBookmark(BookmarkAndCategory const & bnc)
{
StopLocationFollow();
@ -541,51 +478,6 @@ bool Framework::AddBookmarksFile(string const & filePath)
return true;
}
void Framework::AdditionalPoiLayerSetInvisible()
{
m_bmManager.AdditionalPoiLayerSetInvisible();
}
void Framework::AdditionalPoiLayerSetVisible()
{
m_bmManager.AdditionalPoiLayerSetVisible();
}
void Framework::AdditionalPoiLayerAddPoi(Bookmark const & bm)
{
m_bmManager.AdditionalPoiLayerAddPoi(bm);
}
Bookmark const * Framework::AdditionalPoiLayerGetBookmark(size_t index) const
{
return m_bmManager.AdditionalPoiLayerGetBookmark(index);
}
Bookmark * Framework::AdditionalPoiLayerGetBookmark(size_t index)
{
return m_bmManager.AdditionalPoiLayerGetBookmark(index);
}
void Framework::AdditionalPoiLayerClear()
{
m_bmManager.AdditionalPoiLayerClear();
}
bool Framework::IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const
{
return m_bmManager.IsAdditionalLayerPoi(bm);
}
bool Framework::AdditionalLayerIsVisible()
{
return m_bmManager.AdditionalLayerIsVisible();
}
size_t Framework::AdditionalLayerNumberOfPoi()
{
return m_bmManager.AdditionalLayerNumberOfPoi();
}
void Framework::GetLocalMaps(vector<string> & outMaps) const
{
Platform & pl = GetPlatform();
@ -639,14 +531,6 @@ void Framework::InvalidateRect(m2::RectD const & rect, bool doForceUpdate)
m_renderPolicy->SetInvalidRect(m2::AnyRectD(rect));
m_renderPolicy->GetWindowHandle()->invalidate();
}
/*
else
{
m_hasPendingInvalidate = true;
m_doForceUpdate = doForceUpdate;
m_invalidRect = m2::AnyRectD(rect);
}
*/
}
void Framework::SaveState()
@ -786,16 +670,10 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
#endif
m_informationDisplay.doDraw(pDrawer);
DrawMapApiPoints(e);
pScreen->endFrame();
m_bmManager.DrawItems(e);
// somewhere here I can add current place mark
m_balloonManager.DrawPin(e);
m_guiController->UpdateElements();
m_guiController->DrawFrame(pScreen);
}
@ -1222,12 +1100,14 @@ bool Framework::GetCurrentPosition(double & lat, double & lon) const
void Framework::ShowSearchResult(search::Result const & res)
{
m_bmManager.AdditionalPoiLayerSetVisible();
m_bmManager.AdditionalPoiLayerClear();
Bookmark bmk(res.GetFeatureCenter(), res.GetString(), "search-result");
bmk.SetDescription(res.GetFeatureType());
m_bmManager.AdditionalPoiLayerAddPoi(bmk);
UserMarkContainer::Type type = UserMarkContainer::SEARCH_MARK;
m_bmManager.UserMarksSetVisible(type, true);
m_bmManager.UserMarksClear(type);
UserMark * mark = m_bmManager.UserMarksAddMark(type, res.GetFeatureCenter());
search::AddressInfo info;
GetAddressInfoForGlobalPoint(mark->GetOrg(), info);
mark->InjectCustomData(new SearchCustomData(res.GetString(), res.GetFeatureType(),
info.FormatNameAndAddress()));
int scale;
m2::PointD center;
@ -1268,9 +1148,6 @@ void Framework::ShowAllSearchResults()
{
using namespace search;
m_bmManager.AdditionalPoiLayerSetVisible();
m_bmManager.AdditionalPoiLayerClear();
Results searchRes;
GetSearchEngine()->GetResults(searchRes);
@ -1281,6 +1158,10 @@ void Framework::ShowAllSearchResults()
case 0: return;
}
UserMarkContainer::Type type = UserMarkContainer::SEARCH_MARK;
m_bmManager.UserMarksSetVisible(type, true);
m_bmManager.UserMarksClear(type);
m2::RectD rect;
for (size_t i = 0; i < count; ++i)
{
@ -1288,9 +1169,11 @@ void Framework::ShowAllSearchResults()
search::Result const & r = searchRes.GetResult(i);
if (r.GetResultType() != Result::RESULT_SUGGESTION)
{
Bookmark bmk(r.GetFeatureCenter(), r.GetString(), "search-result");
bmk.SetDescription(r.GetFeatureType());
m_bmManager.AdditionalPoiLayerAddPoi(bmk);
UserMark * mark = m_bmManager.UserMarksAddMark(type, r.GetFeatureCenter());
AddressInfo info;
GetAddressInfoForGlobalPoint(mark->GetOrg(), info);
mark->InjectCustomData(new SearchCustomData(r.GetString(), r.GetFeatureType(),
info.FormatNameAndAddress()));
rect.Add(r.GetFeatureCenter());
}
@ -1339,8 +1222,7 @@ bool Framework::GetDistanceAndAzimut(m2::PointD const & point,
void Framework::SetRenderPolicy(RenderPolicy * renderPolicy)
{
m_balloonManager.Shutdown();
m_bmManager.DeleteScreen();
m_bmManager.ResetScreen();
m_guiController->ResetRenderParams();
m_renderPolicy.reset();
m_renderPolicy.reset(renderPolicy);
@ -1387,7 +1269,7 @@ void Framework::InitGuiSubsystem()
pr.m_storageType = graphics::EMediumStorage;
pr.m_textureType = graphics::ESmallTexture;
m_bmManager.SetScreen(m_renderPolicy->CreateScreenWithParams(pr));
m_bmManager.SetScreen(m_renderPolicy->GetCacheScreen().get());
//@}
// Do full invalidate instead of any "pending" stuff.
@ -1421,34 +1303,12 @@ anim::Controller * Framework::GetAnimController() const
return m_animController.get();
}
/*
void Framework::AddBookmarkAndSetViewport(Bookmark & bm, m2::RectD const & viewPort)
{
bm.SetType(LastEditedBMType());
m_bmManager.AddBookmark(LastEditedBMCategory(), bm);
ShowRectExVisibleScale(viewPort);
}
*/
namespace
{
void CheckPointName(url_scheme::ResultPoint & point, StringsBundle const & bundle)
{
string & name = point.GetName();
if (name.empty())
name = bundle.GetString("dropped_pin");
}
}
bool Framework::ShowMapForURL(string const & url)
{
url_scheme::ResultPoint point;
m2::PointD clickPoint;
m2::RectD rect;
enum ResultT { FAILED, NO_BALLOON, BALLOON, BALLOON_PADDING };
enum ResultT { FAILED, NEED_CLICK, NO_NEED_CLICK };
ResultT result = FAILED;
// always hide current balloon here
@ -1463,11 +1323,10 @@ bool Framework::ShowMapForURL(string const & url)
ParseGeoURL(url, info);
if (info.IsValid())
{
point.MakeFrom(info.m_lat, info.m_lon);
CheckPointName(point, m_stringsBundle);
rect = m_scales.GetRectForDrawScale(info.m_zoom, point.GetOrg());
result = BALLOON;
clickPoint = m2::PointD(MercatorBounds::LonToX(info.m_lon),
MercatorBounds::LatToY(info.m_lat));
rect = m_scales.GetRectForDrawScale(info.m_zoom, clickPoint);
result = NEED_CLICK;
}
}
else if (StartsWith(url, "ge0"))
@ -1478,29 +1337,23 @@ bool Framework::ShowMapForURL(string const & url)
if (parser.Parse(url, pt, zoom))
{
point.MakeFrom(pt);
CheckPointName(point, m_stringsBundle);
rect = m_scales.GetRectForDrawScale(zoom, point.GetOrg());
result = BALLOON;
clickPoint = m2::PointD(MercatorBounds::LonToX(pt.m_lon),
MercatorBounds::LatToY(pt.m_lat));
rect = m_scales.GetRectForDrawScale(zoom, clickPoint);
result = NEED_CLICK;
}
}
else if (StartsWith(url, "mapswithme://") || StartsWith(url, "mwm://"))
{
if (m_ParsedMapApi.SetUriAndParse(url))
{
rect = GetMapApiViewportRect();
if (!m_ParsedMapApi.GetViewportRect(m_scales, rect))
rect = ScalesProcessor::GetWorldRect();
if (m_ParsedMapApi.GetPoints().size() == 1)
{
point.MakeFrom(m_ParsedMapApi.GetPoints().front());
result = BALLOON_PADDING;
}
if (m_ParsedMapApi.GetSinglePoint(clickPoint))
result = NEED_CLICK;
else
{
// show world rect without balloon
result = NO_BALLOON;
}
result = NO_NEED_CLICK;
}
}
@ -1510,8 +1363,8 @@ bool Framework::ShowMapForURL(string const & url)
StopLocationFollow();
SetViewPortASync(rect);
if (result != NO_BALLOON)
m_balloonManager.OnClick(GtoP(point.GetOrg()), true);
if (result != NO_NEED_CLICK)
m_balloonManager.OnClick(GtoP(clickPoint), true);
return true;
}
else
@ -1609,29 +1462,6 @@ bool Framework::GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot,
return false;
}
Framework::BookmarkOrPoi Framework::GetBookmarkOrPoi(m2::PointD const & pxPoint, m2::PointD & pxPivot,
search::AddressInfo & info, BookmarkAndCategory & bmCat)
{
bmCat = GetBookmark(pxPoint);
bool const isCorrectBookmark = IsValid(bmCat) && m_bmManager.GetBmCategory(bmCat.first)->IsVisible();
if (isCorrectBookmark)
return Framework::BOOKMARK;
else if (m_bmManager.IsAdditionalLayerPoi(bmCat))
return Framework::ADDTIONAL_LAYER;
if (GetVisiblePOI(pxPoint, pxPivot, info))
{
// We need almost the exact position of the bookmark, parameter 0.1 resolves the error in 2 pixels
bmCat = GetBookmark(pxPivot, 0.1);
if (isCorrectBookmark)
return Framework::BOOKMARK;
else
return Framework::POI;
}
return Framework::NOTHING_FOUND;
}
Animator & Framework::GetAnimator()
{
return m_animator;
@ -1647,6 +1477,41 @@ shared_ptr<location::State> const & Framework::GetLocationState() const
return m_informationDisplay.locationState();
}
UserMark const * Framework::ActivateUserMark(m2::PointD const & pxPoint, bool isLongPress)
{
m2::AnyRectD rect;
m_navigator.GetTouchRect(pxPoint, TOUCH_PIXEL_RADIUS * GetVisualScale(), rect);
UserMark const * mark = m_bmManager.FindNearestUserMark(rect);
if (mark == NULL)
{
bool needMark = false;
m2::PointD pxPivot;
search::AddressInfo info;
if (GetVisiblePOI(pxPoint, pxPivot, info))
needMark = true;
else if (isLongPress)
{
GetAddressInfoForPixelPoint(pxPoint, info);
pxPivot = pxPoint;
needMark = true;
}
if (needMark)
{
UserMark * poiMark = UserMarkContainer::UserMarkForPoi(m_navigator.PtoG(pxPivot));
poiMark->InjectCustomData(new PoiCustomData(info.GetPinName(), info.GetPinType(),
info.FormatAddress()));
mark = poiMark;
}
}
if (mark)
m_bmManager.ActivateMark(mark);
return mark;
}
StringsBundle const & Framework::GetStringsBundle()
{
return m_stringsBundle;
@ -1672,75 +1537,6 @@ string Framework::CodeGe0url(double lat, double lon, double zoomLevel, string co
return res;
}
void Framework::DrawMapApiPoints(shared_ptr<PaintEvent> const & e)
{
// get viewport limit rect
m2::AnyRectD const & glbRect = m_navigator.Screen().GlobalRect();
Drawer * pDrawer = e->drawer();
vector<url_scheme::ApiPoint> const & v = GetMapApiPoints();
for (size_t i = 0; i < v.size(); ++i)
{
m2::PointD const & org = m2::PointD(MercatorBounds::LonToX(v[i].m_lon),
MercatorBounds::LatToY(v[i].m_lat));
if (glbRect.IsPointInside(org))
{
/// @todo Use custom pins from 3-party app
m_informationDisplay.drawPlacemark(pDrawer, "search-result", m_navigator.GtoP(org));
}
}
}
/// @todo Create method that will run all layers without copy/past
bool Framework::GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ResultPoint & point)
{
m2::AnyRectD rect;
m_navigator.GetTouchRect(pxPoint, TOUCH_PIXEL_RADIUS * GetVisualScale(), rect);
m2::PointD const center = rect.GlobalCenter();
double minD = numeric_limits<double>::max();
bool result = false;
vector<url_scheme::ApiPoint> const & v = m_ParsedMapApi.GetPoints();
for (size_t i = 0; i < v.size(); ++i)
{
url_scheme::ResultPoint pt;
pt.MakeFrom(v[i]);
if (rect.IsPointInside(pt.GetOrg()))
{
double const d = center.SquareLength(pt.GetOrg());
if (d < minD)
{
point = pt;
minD = d;
result = true;
}
}
}
return result;
}
m2::RectD Framework::GetMapApiViewportRect() const
{
double zoom;
m2::PointD center;
if (m_ParsedMapApi.GetViewport(center, zoom))
{
return m_scales.GetRectForDrawScale(zoom, center);
}
else
{
m2::RectD rect;
if (m_ParsedMapApi.GetViewportRect(rect))
return rect;
return ScalesProcessor::GetWorldRect();
}
}
string Framework::GenerateApiBackUrl(url_scheme::ApiPoint const & point)
{
string res = m_ParsedMapApi.GetGlobalBackUrl();

View file

@ -179,8 +179,8 @@ public:
void LoadBookmarks();
/// @return Created bookmark index in category.
size_t AddBookmark(size_t categoryIndex, Bookmark & bm);
void ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm);
size_t AddBookmark(size_t categoryIndex, m2::PointD const & ptOrg, BookmarkCustomData & bm);
void ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm);
/// @return Created bookmark category index.
size_t AddCategory(string const & categoryName);
@ -195,14 +195,6 @@ public:
/// @return true if category was deleted
bool DeleteBmCategory(size_t index);
/// @name Get bookmark by touch.
/// @param[in] pixPt Coordinates of touch point in pixels.
/// @return NULL If there is no bookmark found
//@{
BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint) const;
BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint, double visualScale) const;
//@}
void ShowBookmark(BookmarkAndCategory const & bnc);
void ShowTrack(Track const & track);
@ -210,19 +202,6 @@ public:
bool AddBookmarksFile(string const & filePath);
/// @name Additional Layer methods.
//@{
void AdditionalPoiLayerSetInvisible();
void AdditionalPoiLayerSetVisible();
void AdditionalPoiLayerAddPoi(Bookmark const & bm);
Bookmark const * AdditionalPoiLayerGetBookmark(size_t index) const;
Bookmark * AdditionalPoiLayerGetBookmark(size_t index);
void AdditionalPoiLayerClear();
bool IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const;
bool AdditionalLayerIsVisible();
size_t AdditionalLayerNumberOfPoi();
//@}
inline m2::PointD PtoG(m2::PointD const & p) const { return m_navigator.PtoG(p); }
inline m2::PointD GtoP(m2::PointD const & p) const { return m_navigator.GtoP(p); }
@ -356,17 +335,6 @@ private:
public:
bool GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, search::AddressInfo & info) const;
enum BookmarkOrPoi
{
NOTHING_FOUND = 0,
BOOKMARK = 1,
POI = 2,
ADDTIONAL_LAYER = 3
};
BookmarkOrPoi GetBookmarkOrPoi(m2::PointD const & pxPoint, m2::PointD & pxPivot,
search::AddressInfo & info, BookmarkAndCategory & bmCat);
virtual void BeginPaint(shared_ptr<PaintEvent> const & e);
/// Function for calling from platform dependent-paint function.
virtual void DoPaint(shared_ptr<PaintEvent> const & e);
@ -457,6 +425,7 @@ public:
bool IsCountryLoaded(m2::PointD const & pt) const;
shared_ptr<location::State> const & GetLocationState() const;
const UserMark * ActivateUserMark(m2::PointD const & pxPoint, bool isLongPress);
public:
string CodeGe0url(Bookmark const * bmk, bool addName);
@ -464,23 +433,14 @@ public:
/// @name Api
//@{
string GenerateApiBackUrl(url_scheme::ApiPoint const & point);
url_scheme::ParsedMapApi const & GetApiDataHolder() const { return m_ParsedMapApi; }
private:
url_scheme::ParsedMapApi m_ParsedMapApi;
void DrawMapApiPoints(shared_ptr<PaintEvent> const & e);
void SetViewPortASync(m2::RectD const & rect);
public:
bool GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ResultPoint & point);
vector<url_scheme::ApiPoint> const & GetMapApiPoints() { return m_ParsedMapApi.GetPoints(); }
void ClearMapApiPoints() { m_ParsedMapApi.Reset(); }
int GetMapApiVersion() const { return m_ParsedMapApi.GetApiVersion(); }
string const & GetMapApiAppTitle() const { return m_ParsedMapApi.GetAppTitle(); }
string const & GetMapApiBackUrl() const { return m_ParsedMapApi.GetGlobalBackUrl(); }
m2::RectD GetMapApiViewportRect() const;
bool IsValidMapApi() const { return m_ParsedMapApi.IsValid(); }
string GenerateApiBackUrl(url_scheme::ApiPoint const & point);
bool GoBackOnBalloonClick() const { return m_ParsedMapApi.GoBackOnBalloonClick(); }
//@}
/// @name Map updates

View file

@ -1,4 +1,5 @@
#include "mwm_url.hpp"
#include "scales_processor.hpp"
#include "../indexer/mercator.hpp"
#include "../indexer/scales.hpp"
@ -15,12 +16,6 @@
namespace url_scheme
{
void ResultPoint::Init()
{
m_org = m2::PointD(MercatorBounds::LonToX(m_point.m_lon),
MercatorBounds::LatToY(m_point.m_lat));
}
namespace
{
@ -30,14 +25,17 @@ bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE
} // unnames namespace
ParsedMapApi::ParsedMapApi() : m_version(0), m_zoomLevel(0.0), m_goBackOnBalloonClick(false)
ParsedMapApi::ParsedMapApi()
: m_controller(NULL)
, m_version(0)
, m_zoomLevel(0.0)
, m_goBackOnBalloonClick(false)
{
}
ParsedMapApi::ParsedMapApi(Uri const & uri) : m_version(0), m_zoomLevel(0.0), m_goBackOnBalloonClick(false)
void ParsedMapApi::SetController(UserMarkContainer::Controller * controller)
{
if (!Parse(uri))
Reset();
m_controller = controller;
}
bool ParsedMapApi::SetUriAndParse(string const & url)
@ -48,29 +46,42 @@ bool ParsedMapApi::SetUriAndParse(string const & url)
bool ParsedMapApi::IsValid() const
{
return !m_points.empty();
ASSERT(m_controller != NULL, ());
return m_controller->GetUserMarkCount() > 0;
}
bool ParsedMapApi::Parse(Uri const & uri)
{
ASSERT(m_controller != NULL, ());
string const & scheme = uri.GetScheme();
if ((scheme != "mapswithme" && scheme != "mwm") || uri.GetPath() != "map")
return false;
uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2));
m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end());
vector<ApiPoint> points;
uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2, ref(points)));
points.erase(remove_if(points.begin(), points.end(), &IsInvalidApiPoint), points.end());
for (size_t i = 0; i < points.size(); ++i)
{
ApiPoint const & p = points[i];
m2::PointD glPoint(MercatorBounds::LonToX(p.m_lon),
MercatorBounds::LatToY(p.m_lat));
UserMark * mark = m_controller->CreateUserMark(glPoint);
mark->InjectCustomData(new ApiCustomData(p.m_name, p.m_id));
}
return true;
}
void ParsedMapApi::AddKeyValue(string key, string const & value)
void ParsedMapApi::AddKeyValue(string key, string const & value, vector<ApiPoint> & points)
{
strings::AsciiToLower(key);
if (key == "ll")
{
m_points.push_back(ApiPoint());
m_points.back().m_lat = INVALID_LAT_VALUE;
points.push_back(ApiPoint());
points.back().m_lat = INVALID_LAT_VALUE;
size_t const firstComma = value.find(',');
if (firstComma == string::npos)
@ -99,9 +110,8 @@ void ParsedMapApi::AddKeyValue(string key, string const & value)
return;
}
m_points.back().m_lat = lat;
m_points.back().m_lon = lon;
m_showRect = m2::Add(m_showRect, m2::PointD(lon, lat));
points.back().m_lat = lat;
points.back().m_lon = lon;
}
else if (key == "z")
{
@ -110,15 +120,15 @@ void ParsedMapApi::AddKeyValue(string key, string const & value)
}
else if (key == "n")
{
if (!m_points.empty())
m_points.back().m_name = value;
if (!points.empty())
points.back().m_name = value;
else
LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!"));
}
else if (key == "id")
{
if (!m_points.empty())
m_points.back().m_id = value;
if (!points.empty())
points.back().m_id = value;
else
LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!"));
}
@ -147,37 +157,47 @@ void ParsedMapApi::AddKeyValue(string key, string const & value)
void ParsedMapApi::Reset()
{
m_points.clear();
m_globalBackUrl.clear();
m_appTitle.clear();
m_version = 0;
m_showRect = m2::RectD();
m_zoomLevel = 0.0;
m_goBackOnBalloonClick = false;
}
bool ParsedMapApi::GetViewport(m2::PointD & pt, double & zoom) const
bool ParsedMapApi::GetViewportRect(ScalesProcessor const & scales, m2::RectD & rect) const
{
if (m_zoomLevel >= 1.0 && m_points.size() == 1)
ASSERT(m_controller != NULL, ());
size_t markCount = m_controller->GetUserMarkCount();
if (markCount == 1 && m_zoomLevel >= 1)
{
zoom = min(static_cast<double>(scales::GetUpperComfortScale()), m_zoomLevel);
pt.x = MercatorBounds::LonToX(m_points.front().m_lon);
pt.y = MercatorBounds::LatToY(m_points.front().m_lat);
return true;
}
return false;
}
bool ParsedMapApi::GetViewportRect(m2::RectD & rect) const
{
if (m_showRect.IsValid())
{
rect = MercatorBounds::FromLatLonRect(m_showRect);
double zoom = min(static_cast<double>(scales::GetUpperComfortScale()), m_zoomLevel);
rect = scales.GetRectForDrawScale(zoom, m_controller->GetUserMark(0)->GetOrg());
return true;
}
else
{
m2::RectD result;
for (size_t i = 0; i < m_controller->GetUserMarkCount(); ++i)
result.Add(m_controller->GetUserMark(i)->GetOrg());
if (result.IsValid())
{
rect = result;
return true;
}
return false;
}
}
bool ParsedMapApi::GetSinglePoint(m2::PointD & point) const
{
ASSERT(m_controller != NULL, ());
if (m_controller->GetUserMarkCount() != 1)
return false;
point = m_controller->GetUserMark(0)->GetOrg();
return true;
}
}

View file

@ -1,13 +1,16 @@
#pragma once
#include "user_mark_container.hpp"
#include "../geometry/rect2d.hpp"
#include "../std/string.hpp"
class ScalesProcessor;
namespace url_scheme
{
class Uri;
struct ApiPoint
{
double m_lat;
@ -16,67 +19,36 @@ struct ApiPoint
string m_id;
};
class ResultPoint
{
ApiPoint m_point;
m2::PointD m_org;
void Init();
public:
void MakeFrom(double lat, double lon)
{
m_point.m_lat = lat;
m_point.m_lon = lon;
Init();
}
void MakeFrom(url_scheme::ApiPoint const & pt)
{
m_point = pt;
Init();
}
/// Need to fix default name using "dropped_pin" in Framework.
string & GetName() { return m_point.m_name; }
m2::PointD const & GetOrg() const { return m_org; }
string const & GetName() const { return m_point.m_name; }
ApiPoint const & GetPoint() const { return m_point; }
};
class Uri;
/// Handles [mapswithme|mwm]://map?params - everything related to displaying info on a map
class ParsedMapApi
{
public:
ParsedMapApi(Uri const & uri);
ParsedMapApi();
void SetController(UserMarkContainer::Controller * controller);
bool SetUriAndParse(string const & url);
bool IsValid() const;
vector<ApiPoint> const & GetPoints() const { return m_points; }
string const & GetGlobalBackUrl() const { return m_globalBackUrl; }
string const & GetAppTitle() const { return m_appTitle; }
int GetApiVersion() const { return m_version; }
m2::RectD GetLatLonRect() const { return m_showRect; }
void Reset();
bool GoBackOnBalloonClick() const { return m_goBackOnBalloonClick; }
/// @name Used in settings map viewport after invoking API.
//@{
bool GetViewport(m2::PointD & pt, double & zoom) const;
bool GetViewportRect(m2::RectD & rect) const;
//@}
bool GetViewportRect(ScalesProcessor const & scales, m2::RectD & rect) const;
bool GetSinglePoint(m2::PointD & point) const;
private:
bool Parse(Uri const & uri);
void AddKeyValue(string key, string const & value);
void AddKeyValue(string key, string const & value, vector<ApiPoint> & points);
vector<ApiPoint> m_points;
UserMarkContainer::Controller * m_controller;
string m_globalBackUrl;
string m_appTitle;
int m_version;
m2::RectD m_showRect;
/// Zoom level in OSM format (e.g. from 1.0 to 20.0)
/// Taken into an account when calculating viewport rect, but only if points count is == 1
double m_zoomLevel;

69
map/user_mark.cpp Normal file
View file

@ -0,0 +1,69 @@
#include "user_mark.hpp"
#include "user_mark_container.hpp"
#include "../indexer/mercator.hpp"
namespace
{
static EmptyCustomData s_emptyData;
}
UserMark::UserMark(const m2::PointD & ptOrg, UserMarkContainer * container)
: m_ptOrg(ptOrg)
, m_container(container)
, m_customData(NULL)
{
}
UserMark::~UserMark()
{
delete m_customData;
}
UserMarkContainer const * UserMark::GetContainer() const
{
return m_container;
}
m2::PointD const & UserMark::GetOrg() const
{
return m_ptOrg;
}
void UserMark::GetLatLon(double & lat, double & lon) const
{
lon = MercatorBounds::XToLon(m_ptOrg.x);
lat = MercatorBounds::YToLat(m_ptOrg.y);
}
void UserMark::InjectCustomData(UserCustomData * customData)
{
delete m_customData;
m_customData = customData;
}
UserCustomData const & UserMark::GetCustomData() const
{
if (m_customData == NULL)
return s_emptyData;
return *m_customData;
}
void UserMark::Activate() const
{
m_container->ActivateMark(this);
}
void UserMark::Diactivate() const
{
m_container->DiactivateMark();
}
UserCustomData & UserMark::GetCustomData()
{
if (m_customData == NULL)
return s_emptyData;
return *m_customData;
}

114
map/user_mark.hpp Normal file
View file

@ -0,0 +1,114 @@
#pragma once
#include "../geometry/point2d.hpp"
#include "../std/string.hpp"
#include "../std/noncopyable.hpp"
class UserMarkContainer;
class UserCustomData
{
public:
enum Type
{
EMPTY,
POI,
SEARCH,
API,
BOOKMARK
};
virtual ~UserCustomData() {}
virtual Type GetType() const = 0;
};
class EmptyCustomData : public UserCustomData
{
public:
virtual Type GetType() const { return EMPTY; }
};
class BaseCustomData : public UserCustomData
{
public:
BaseCustomData(string const & name, string const & typeName, string address)
: m_name(name)
, m_typeName(typeName)
, m_address(address) {}
string const & GetName() const { return m_name; }
string const & GetTypeName() const { return m_typeName; }
string const & GetAddress() const { return m_address; }
private:
string m_name;
string m_typeName;
string m_address;
};
class PoiCustomData : public BaseCustomData
{
typedef BaseCustomData base_t;
public:
PoiCustomData(string const & name, string const & typeName, string address)
: base_t(name, typeName, address) {}
virtual Type GetType() const { return POI; }
};
class SearchCustomData : public BaseCustomData
{
typedef BaseCustomData base_t;
public:
SearchCustomData(string const & name, string const & typeName, string address)
: base_t(name, typeName, address) {}
virtual Type GetType() const { return SEARCH; }
};
class ApiCustomData : public UserCustomData
{
typedef UserCustomData base_t;
public:
ApiCustomData(string const & name, string const & id)
: m_name(name)
, m_id(id) {}
virtual Type GetType() const { return API; }
string const & GetName() const { return m_name; }
string const & GetID() const {return m_id; }
private:
string m_name;
string m_id;
};
class UserMark : private noncopyable
{
public:
UserMark(m2::PointD const & ptOrg, UserMarkContainer * container);
virtual ~UserMark();
UserMarkContainer const * GetContainer() const;
m2::PointD const & GetOrg() const;
void GetLatLon(double & lat, double & lon) const;
// custom data must be allocated in head
// memory where allocated custom data will be deallocated by UserMark
void InjectCustomData(UserCustomData * customData);
UserCustomData const & GetCustomData() const;
protected:
friend class BookmarkManager;
void Activate() const;
void Diactivate() const;
UserCustomData & GetCustomData();
protected:
m2::PointD m_ptOrg;
mutable UserMarkContainer * m_container;
UserCustomData * m_customData;
};

390
map/user_mark_container.cpp Normal file
View file

@ -0,0 +1,390 @@
#include "user_mark_container.hpp"
#include "drawer.hpp"
#include "framework.hpp"
#include "../graphics/display_list.hpp"
#include "../graphics/screen.hpp"
#include "../geometry/transformations.hpp"
#include "../anim/task.hpp"
#include "../anim/controller.hpp"
#include "../base/macros.hpp"
#include "../base/stl_add.hpp"
#include "../std/scoped_ptr.hpp"
namespace
{
struct AnimPhase
{
AnimPhase(double endScale, double timeInterval)
: m_endScale(endScale)
, m_timeInterval(timeInterval)
{
}
double m_endScale;
double m_timeInterval;
};
class PinAnimation : public anim::Task
{
public:
PinAnimation(Framework & f)
: m_f(f)
, m_scale(0.0)
{
}
void AddAnimPhase(AnimPhase const & phase)
{
m_animPhases.push_back(phase);
}
virtual void OnStart(double ts)
{
m_startTime = ts;
m_startScale = m_scale;
m_phaseIndex = 0;
}
virtual void OnStep(double ts)
{
ASSERT(m_phaseIndex < m_animPhases.size(), ());
AnimPhase const * phase = &m_animPhases[m_phaseIndex];
double elapsedTime = ts - m_startTime;
if (elapsedTime > phase->m_timeInterval)
{
m_startTime = ts;
m_scale = phase->m_endScale;
m_startScale = m_scale;
m_phaseIndex++;
if (m_phaseIndex >= m_animPhases.size())
{
End();
return;
}
}
elapsedTime = ts - m_startTime;
double t = elapsedTime / phase->m_timeInterval;
m_scale = m_startScale + t * (phase->m_endScale - m_startScale);
m_f.Invalidate();
}
double GetScale() const
{
return m_scale;
}
private:
Framework & m_f;
vector<AnimPhase> m_animPhases;
size_t m_phaseIndex;
double m_scale;
double m_startTime;
double m_startScale;
};
}
////////////////////////////////////////////////////////////////////////
namespace
{
class FindMarkFunctor
{
public:
FindMarkFunctor(UserMark ** mark, double & minD, m2::AnyRectD const & rect)
: m_mark(mark)
, m_minD(minD)
, m_rect(rect)
{
m_globalCenter = rect.GlobalCenter();
}
void operator()(UserMark * mark)
{
m2::PointD const & org = mark->GetOrg();
if (m_rect.IsPointInside(org))
{
double minDCandidate = m_globalCenter.SquareLength(org);
if (minDCandidate < m_minD)
{
*m_mark = mark;
m_minD = minDCandidate;
}
}
}
UserMark ** m_mark;
double & m_minD;
m2::AnyRectD const & m_rect;
m2::PointD m_globalCenter;
};
class DrawFunctor
{
public:
DrawFunctor(double scale,
ScreenBase const & modelView,
graphics::DisplayList * dl,
graphics::Screen * screen)
: m_scale(scale)
, m_modelView(modelView)
, m_dl(dl)
, m_screen(screen)
{
}
void operator()(UserMark const * mark)
{
m2::PointD pxPoint = m_modelView.GtoP(mark->GetOrg());
math::Matrix<double, 3, 3> m = math::Shift(math::Scale(math::Identity<double, 3>(),
m_scale, m_scale),
pxPoint.x, pxPoint.y);
m_dl->draw(m_screen, m);
}
private:
double m_scale;
ScreenBase const & m_modelView;
graphics::DisplayList * m_dl;
graphics::Screen * m_screen;
};
}
UserMarkContainer::UserMarkContainer(Type type, double layerDepth, Framework & framework)
: m_controller(this)
, m_type(type)
, m_isVisible(true)
, m_layerDepth(layerDepth)
, m_activeMark(NULL)
, m_symbolDL(NULL)
, m_activeSymbolDL(NULL)
, m_cacheScreen(NULL)
, m_framework(framework)
{
ASSERT(m_type >= 0 && m_type < TERMINANT, ());
}
UserMarkContainer::~UserMarkContainer()
{
Clear();
ReleaseScreen();
}
void UserMarkContainer::SetScreen(graphics::Screen * cacheScreen)
{
Purge();
m_cacheScreen = cacheScreen;
}
UserMark const * UserMarkContainer::FindMarkInRect(m2::AnyRectD const & rect, double & d)
{
UserMark * mark = NULL;
d = numeric_limits<double>::max();
FindMarkFunctor f(&mark, d, rect);
for_each(m_userMarks.begin(), m_userMarks.end(), f);
return mark;
}
void UserMarkContainer::Draw(PaintOverlayEvent const & e)
{
if (m_isVisible == false)
return;
ASSERT(m_cacheScreen != NULL, ());
if (m_cacheScreen == NULL)
return;
graphics::Screen * screen = e.GetDrawer()->screen();
ScreenBase modelView = e.GetModelView();
if (m_activeMark != NULL)
(void)DrawFunctor(GetActiveMarkScale(), modelView, GetActiveDL(), screen)(m_activeMark);
DrawFunctor f(1.0, modelView, GetDL(), screen);
for_each(m_userMarks.begin(), m_userMarks.end(), f);
}
void UserMarkContainer::ActivateMark(UserMark const * mark)
{
ASSERT(mark->GetContainer() == this, ());
m_activeMark = mark;
StartActivationAnim();
}
void UserMarkContainer::DiactivateMark()
{
KillActivationAnim();
m_activeMark = NULL;
}
void UserMarkContainer::Clear()
{
Purge();
DeleteRange(m_userMarks, DeleteFunctor());
m_activeMark = NULL;
}
static string s_TypeNames[] =
{
"search-result",
"api-result"
};
string const & UserMarkContainer::GetTypeName() const
{
ASSERT(m_type < ARRAY_SIZE(s_TypeNames), ());
return s_TypeNames[m_type];
}
namespace
{
class PoiUserMark : public UserMark
{
public:
PoiUserMark(UserMarkContainer * container)
: UserMark(m2::PointD(0.0, 0.0), container) {}
void SetPtOrg(m2::PointD const & ptOrg) { m_ptOrg = ptOrg; }
};
static scoped_ptr<PoiUserMark> s_selectionUserMark;
}
void UserMarkContainer::InitPoiSelectionMark(UserMarkContainer * container)
{
ASSERT(s_selectionUserMark == NULL, ());
s_selectionUserMark.reset(new PoiUserMark(container));
}
UserMark * UserMarkContainer::UserMarkForPoi(m2::PointD const & ptOrg)
{
ASSERT(s_selectionUserMark != NULL, ());
s_selectionUserMark->SetPtOrg(ptOrg);
return s_selectionUserMark.get();
}
UserMark * UserMarkContainer::CreateUserMark(m2::PointD ptOrg)
{
m_userMarks.push_back(new UserMark(ptOrg, this));
return m_userMarks.back();
}
size_t UserMarkContainer::GetUserMarkCount() const
{
return m_userMarks.size();
}
UserMark const * UserMarkContainer::GetUserMark(size_t index) const
{
ASSERT_LESS(index, m_userMarks.size(), ());
return m_userMarks[index];
}
UserMark * UserMarkContainer::GetUserMark(size_t index)
{
ASSERT_LESS(index, m_userMarks.size(), ());
return m_userMarks[index];
}
void UserMarkContainer::EditUserMark(size_t index, UserCustomData * data)
{
UserMark * mark = GetUserMark(index);
mark->InjectCustomData(data);
}
namespace
{
template <class T> void DeleteItem(vector<T> & v, size_t i)
{
if (i < v.size())
{
delete v[i];
v.erase(v.begin() + i);
}
else
{
LOG(LWARNING, ("Trying to delete non-existing item at index", i));
}
}
}
void UserMarkContainer::DeleteUserMark(size_t index)
{
DeleteItem(m_userMarks, index);
}
graphics::DisplayList * UserMarkContainer::GetDL()
{
if (m_symbolDL == NULL)
m_symbolDL = CreateDL(GetTypeName());
return m_symbolDL;
}
graphics::DisplayList * UserMarkContainer::GetActiveDL()
{
if (m_activeSymbolDL == NULL)
m_activeSymbolDL = CreateDL(GetTypeName() + "-active");
return m_activeSymbolDL;
}
graphics::DisplayList * UserMarkContainer::CreateDL(const string & symbolName)
{
graphics::DisplayList * dl = m_cacheScreen->createDisplayList();
m_cacheScreen->beginFrame();
m_cacheScreen->setDisplayList(dl);
m_cacheScreen->drawSymbol(m2::PointD(0.0, 0.0), symbolName, graphics::EPosCenter, m_layerDepth);
m_cacheScreen->setDisplayList(0);
m_cacheScreen->endFrame();
return dl;
}
void UserMarkContainer::Purge()
{
delete m_symbolDL;
m_symbolDL = NULL;
delete m_activeSymbolDL;
m_activeSymbolDL = NULL;
}
void UserMarkContainer::ReleaseScreen()
{
m_cacheScreen = NULL;
}
void UserMarkContainer::StartActivationAnim()
{
PinAnimation * anim = new PinAnimation(m_framework);
anim->AddAnimPhase(AnimPhase(1.2, 0.15));
anim->AddAnimPhase(AnimPhase(0.8, 0.08));
anim->AddAnimPhase(AnimPhase(1, 0.05));
m_animTask.reset(anim);
m_framework.GetAnimController()->AddTask(m_animTask);
}
void UserMarkContainer::KillActivationAnim()
{
m_animTask.reset();
}
double UserMarkContainer::GetActiveMarkScale() const
{
if (m_animTask != NULL)
{
PinAnimation * a = static_cast<PinAnimation *>(m_animTask.get());
return a->GetScale();
}
return 1.0;
}

114
map/user_mark_container.hpp Normal file
View file

@ -0,0 +1,114 @@
#pragma once
#include "events.hpp"
#include "user_mark.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/rect2d.hpp"
#include "../std/noncopyable.hpp"
class Framework;
namespace anim
{
class Task;
}
namespace graphics
{
class DisplayList;
class Screen;
}
class UserMarkContainer : private noncopyable
{
public:
class Controller
{
public:
Controller(UserMarkContainer * container)
: m_container(container) {}
UserMark * CreateUserMark(m2::PointD ptOrg) { return m_container->CreateUserMark(ptOrg); }
size_t GetUserMarkCount() const { return m_container->GetUserMarkCount(); }
UserMark const * GetUserMark(size_t index) const { return m_container->GetUserMark(index); }
void EditUserMark(size_t index, UserCustomData * data) { m_container->EditUserMark(index, data); }
void DeleteUserMark(size_t index) { m_container->DeleteUserMark(index); }
private:
UserMarkContainer * m_container;
};
enum Type
{
SEARCH_MARK,
API_MARK,
BOOKMARK_MARK,
TERMINANT
};
UserMarkContainer(Type type, double layerDepth, Framework & framework);
~UserMarkContainer();
void SetScreen(graphics::Screen * cacheScreen);
bool IsVisible() const { return m_isVisible; }
void SetVisible(bool isVisible) { m_isVisible = isVisible; }
// If not found mark on rect result is NULL
// If mark is found in "d" return distance from rect center
// In multiple select choose mark with min(d)
UserMark const * FindMarkInRect(m2::AnyRectD const & rect, double & d);
void Draw(PaintOverlayEvent const & e);
void ActivateMark(UserMark const * mark);
void DiactivateMark();
void Clear();
Type const & GetType() const { return m_type; }
string const & GetTypeName() const;
static void InitPoiSelectionMark(UserMarkContainer * container);
static UserMark * UserMarkForPoi(m2::PointD const & ptOrg);
Controller const & GetController() const { return m_controller; }
Controller & GetController() { return m_controller; }
private:
friend class Controller;
UserMark * CreateUserMark(m2::PointD ptOrg);
size_t GetUserMarkCount() const;
UserMark const * GetUserMark(size_t index) const;
UserMark * GetUserMark(size_t index);
void EditUserMark(size_t index, UserCustomData * data);
void DeleteUserMark(size_t index);
private:
graphics::DisplayList * GetDL();
graphics::DisplayList * GetActiveDL();
graphics::DisplayList * CreateDL(string const & symbolName);
void Purge();
void ReleaseScreen();
private:
Controller m_controller;
Type m_type;
bool m_isVisible;
double m_layerDepth;
vector<UserMark *> m_userMarks;
UserMark const * m_activeMark;
graphics::DisplayList * m_symbolDL;
graphics::DisplayList * m_activeSymbolDL;
graphics::Screen * m_cacheScreen;
private:
/// animation support
void StartActivationAnim();
void KillActivationAnim();
double GetActiveMarkScale() const;
Framework & m_framework;
shared_ptr<anim::Task> m_animTask;
};