[core] customize user mark drawing.

This commit is contained in:
ExMix 2014-05-16 12:30:16 +03:00 committed by Alex Zolotarev
parent bd1c2ce569
commit bf8badaa32
11 changed files with 264 additions and 186 deletions

View file

@ -35,7 +35,7 @@ void PinClickManager::OnClick(m2::PointD const & pxPoint, bool isLongTouch)
void PinClickManager::OnBookmarkClick(BookmarkAndCategory const & bnc)
{
Bookmark * mark = m_f.GetBmCategory(bnc.first)->GetBookmark(bnc.second);
m_f.GetBookmarkManager().ActivateMark(mark);
m_f.GetBookmarkManager ().ActivateMark(mark);
SetBalloonVisible(true);
}

View file

@ -741,6 +741,11 @@ string BookmarkCategory::GenerateUniqueFileName(const string & path, string name
return (path + name + suffix + kmlExt);
}
UserMark * BookmarkCategory::AllocateUserMark(m2::PointD const & ptOrg)
{
return new Bookmark(ptOrg, this);
}
bool BookmarkCategory::SaveToKMLFile()
{
string oldFile;

View file

@ -56,11 +56,11 @@ private:
time_t m_timeStamp;
};
class Bookmark : public UserMark
class Bookmark : public ICustomDrawable
{
public:
Bookmark(UserMarkContainer * container)
: UserMark(m2::PointD(0.0, 0.0), container)
Bookmark(m2::PointD const & ptOrg, UserMarkContainer * container)
: ICustomDrawable(ptOrg, container)
{
Inject();
}
@ -83,6 +83,11 @@ public:
double GetScale() const { return GetData()->GetScale(); }
void SetScale(double scale) { GetData()->SetScale(scale); }
virtual graphics::DisplayList * GetDisplayList(UserMarkDLCache * cache) const
{
return cache->FindUserMark(UserMarkDLCache::Key(GetType(), graphics::EPosAbove, GetContainer()->GetDepth()));
}
private:
void Inject(m2::PointD const & org = m2::PointD(), string const & name = "",
string const & type = "", string const & descr = "",
@ -167,6 +172,9 @@ public:
/// Get unique bookmark file name from path and valid file name.
static string GenerateUniqueFileName(const string & path, string name);
//@}
protected:
virtual UserMark * AllocateUserMark(m2::PointD const & ptOrg);
};
/// <category index, bookmark index>

View file

@ -23,6 +23,7 @@ BookmarkManager::BookmarkManager(Framework & f)
, m_activeMark(NULL)
, m_bmScreen(0)
, m_lastScale(1.0)
, m_cache(NULL)
{
m_userMarkLayers.reserve(2);
m_userMarkLayers.push_back(new UserMarkContainer(UserMarkContainer::SEARCH_MARK, graphics::activePinDepth, m_framework));
@ -125,14 +126,13 @@ public:
}
void BookmarkManager::DrawCategory(BookmarkCategory const * cat, shared_ptr<PaintEvent> const & e) const
void BookmarkManager::DrawCategory(BookmarkCategory const * cat, PaintOverlayEvent 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();
Drawer * pDrawer = e->drawer();
Drawer * pDrawer = e.GetDrawer();
graphics::Screen * pScreen = pDrawer->screen();
LazyMatrixCalc matrix(screen, m_lastScale);
@ -145,16 +145,7 @@ void BookmarkManager::DrawCategory(BookmarkCategory const * cat, shared_ptr<Pain
track->Draw(pScreen, matrix.GetFinalG2P());
}
// Draw bookmarks.
m2::AnyRectD const & glbRect = screen.GlobalRect();
for (size_t j = 0; j < cat->GetBookmarksCount(); ++j)
{
Bookmark const * bm = cat->GetBookmark(j);
m2::PointD const & org = bm->GetOrg();
if (glbRect.IsPointInside(org))
informationDisplay.drawPlacemark(pDrawer, bm->GetType().c_str(), navigator.GtoP(org) + m2::PointD(0.0, 4.0));
}
cat->Draw(e, m_cache);
}
void BookmarkManager::ClearItems()
@ -243,6 +234,7 @@ size_t BookmarkManager::CreateBmCategory(string const & name)
void BookmarkManager::DrawItems(shared_ptr<PaintEvent> const & e) const
{
ASSERT(m_cache != NULL, ());
ScreenBase const & screen = m_framework.GetNavigator().Screen();
m2::RectD const limitRect = screen.ClipRect();
@ -272,13 +264,8 @@ void BookmarkManager::DrawItems(shared_ptr<PaintEvent> const & e) const
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);
}
for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(), bind(&UserMarkContainer::Draw, _1, event, m_cache));
for_each(m_categories.begin(), m_categories.end(), bind(&BookmarkManager::DrawCategory, this, _1, event));
pScreen->endFrame();
}
@ -317,21 +304,6 @@ void BookmarkManager::ActivateMark(UserMark const * mark)
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();
}
@ -397,12 +369,13 @@ void BookmarkManager::SetScreen(graphics::Screen * screen)
{
ResetScreen();
m_bmScreen = screen;
for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(),
bind(&UserMarkContainer::SetScreen, _1, m_bmScreen));
m_cache = new UserMarkDLCache(m_bmScreen);
}
void BookmarkManager::ResetScreen()
{
delete m_cache;
m_cache = NULL;
if (m_bmScreen)
{
// Delete display lists for all tracks
@ -410,9 +383,6 @@ void BookmarkManager::ResetScreen()
for (size_t j = 0; j < m_categories[i]->GetTracksCount(); ++j)
m_categories[i]->GetTrack(j)->DeleteDisplayList();
for (size_t i = 0; i < m_userMarkLayers.size(); ++i)
m_userMarkLayers[i]->SetScreen(0);
m_bmScreen = 0;
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "bookmark.hpp"
#include "user_mark_container.hpp"
#include "user_mark_dl_cache.hpp"
class Framework;
class PaintEvent;
@ -23,7 +24,7 @@ class BookmarkManager : private noncopyable
typedef vector<BookmarkCategory *>::iterator CategoryIter;
void DrawCategory(BookmarkCategory const * cat, shared_ptr<PaintEvent> const & e) const;
void DrawCategory(BookmarkCategory const * cat, PaintOverlayEvent const & e) const;
void SaveState() const;
void LoadState();
@ -74,4 +75,6 @@ public:
private:
UserMarkContainer const * FindUserMarksContainer(UserMarkContainer::Type type) const;
UserMarkContainer * FindUserMarksContainer(UserMarkContainer::Type type);
UserMarkDLCache * m_cache;
};

View file

@ -66,7 +66,8 @@ HEADERS += \
track.hpp \
alfa_animation_task.hpp \
user_mark_container.hpp \
user_mark.hpp
user_mark.hpp \
user_mark_dl_cache.hpp
SOURCES += \
feature_vec_model.cpp \
@ -119,7 +120,8 @@ SOURCES += \
track.cpp \
alfa_animation_task.cpp \
user_mark_container.cpp \
user_mark.cpp
user_mark.cpp \
user_mark_dl_cache.cpp
!iphone*:!tizen*:!android* {
HEADERS += qgl_render_context.hpp

View file

@ -6,6 +6,13 @@
#include "../std/noncopyable.hpp"
class UserMarkContainer;
class PaintOverlayEvent;
class UserMarkDLCache;
namespace graphics
{
class DisplayList;
}
class UserCustomData
{
@ -95,6 +102,7 @@ public:
UserMarkContainer const * GetContainer() const;
m2::PointD const & GetOrg() const;
void GetLatLon(double & lat, double & lon) const;
virtual bool IsCustomDrawable() const { return false;}
// custom data must be allocated in head
// memory where allocated custom data will be deallocated by UserMark
@ -112,3 +120,11 @@ protected:
mutable UserMarkContainer * m_container;
UserCustomData * m_customData;
};
class ICustomDrawable : public UserMark
{
public:
ICustomDrawable(m2::PointD const & ptOrg, UserMarkContainer * container) : UserMark(ptOrg, container) {}
bool IsCustomDrawable() const { return true; }
virtual graphics::DisplayList * GetDisplayList(UserMarkDLCache * cache) const = 0;
};

View file

@ -127,35 +127,40 @@ namespace
m2::PointD m_globalCenter;
};
class DrawFunctor
void DrawUserMarkImpl(double scale,
PaintOverlayEvent const & event,
graphics::DisplayList * dl,
UserMark const * mark)
{
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)
{
}
ScreenBase modelView = event.GetModelView();
graphics::Screen * screen = event.GetDrawer()->screen();
m2::PointD pxPoint = modelView.GtoP(mark->GetOrg());
math::Matrix<double, 3, 3> m = math::Shift(math::Scale(math::Identity<double, 3>(),
scale, scale),
pxPoint.x, pxPoint.y);
dl->draw(screen, m);
}
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);
}
void DefaultDrawUserMark(double scale,
PaintOverlayEvent const & event,
UserMarkDLCache * cache,
UserMarkDLCache::Key const & defaultKey,
UserMark const * mark)
{
DrawUserMarkImpl(scale, event, cache->FindUserMark(defaultKey), mark);
}
private:
double m_scale;
ScreenBase const & m_modelView;
graphics::DisplayList * m_dl;
graphics::Screen * m_screen;
};
void DrawUserMark(double scale,
PaintOverlayEvent const & event,
UserMarkDLCache * cache,
UserMarkDLCache::Key const & defaultKey,
UserMark const * mark)
{
if (mark->IsCustomDrawable())
DrawUserMarkImpl(scale, event, static_cast<ICustomDrawable const *>(mark)->GetDisplayList(cache), mark);
else
DefaultDrawUserMark(scale, event, cache, defaultKey, mark);
}
}
UserMarkContainer::UserMarkContainer(Type type, double layerDepth, Framework & framework)
@ -164,9 +169,6 @@ UserMarkContainer::UserMarkContainer(Type type, double layerDepth, Framework & f
, 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, ());
@ -175,13 +177,6 @@ UserMarkContainer::UserMarkContainer(Type type, double layerDepth, Framework & f
UserMarkContainer::~UserMarkContainer()
{
Clear();
ReleaseScreen();
}
void UserMarkContainer::SetScreen(graphics::Screen * cacheScreen)
{
Purge();
m_cacheScreen = cacheScreen;
}
UserMark const * UserMarkContainer::FindMarkInRect(m2::AnyRectD const & rect, double & d)
@ -193,25 +188,19 @@ UserMark const * UserMarkContainer::FindMarkInRect(m2::AnyRectD const & rect, do
return mark;
}
void UserMarkContainer::Draw(PaintOverlayEvent const & e)
void UserMarkContainer::Draw(PaintOverlayEvent const & e, UserMarkDLCache * cache) const
{
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)
{
LOG(LINFO, ("Scale for active mark = ", GetActiveMarkScale()));
(void)DrawFunctor(GetActiveMarkScale(), modelView, GetActiveDL(), screen)(m_activeMark);
UserMarkDLCache::Key defaultKey(GetActiveTypeName(), graphics::EPosCenter, m_layerDepth);
DefaultDrawUserMark(GetActiveMarkScale(), e, cache, defaultKey, m_activeMark);
}
DrawFunctor f(1.0, modelView, GetDL(), screen);
for_each(m_userMarks.begin(), m_userMarks.end(), f);
UserMarkDLCache::Key defaultKey(GetTypeName(), graphics::EPosCenter, m_layerDepth);
for_each(m_userMarks.begin(), m_userMarks.end(), bind(&DrawUserMark, 1.0, e, cache, defaultKey, _1));
}
void UserMarkContainer::ActivateMark(UserMark const * mark)
@ -229,7 +218,6 @@ void UserMarkContainer::DiactivateMark()
void UserMarkContainer::Clear()
{
Purge();
DeleteRange(m_userMarks, DeleteFunctor());
m_activeMark = NULL;
}
@ -237,15 +225,26 @@ void UserMarkContainer::Clear()
static string s_TypeNames[] =
{
"search-result",
"api-result"
"api-result",
"search-result" // Bookmark active we draw as a search active
};
string const & UserMarkContainer::GetTypeName() const
string UserMarkContainer::GetTypeName() const
{
ASSERT(m_type < ARRAY_SIZE(s_TypeNames), ());
return s_TypeNames[m_type];
}
string UserMarkContainer::GetActiveTypeName() const
{
return GetTypeName() + "-active";
}
UserMark * UserMarkContainer::AllocateUserMark(m2::PointD const & ptOrg)
{
return new UserMark(ptOrg, this);
}
namespace
{
class PoiUserMark : public UserMark
@ -273,9 +272,9 @@ UserMark * UserMarkContainer::UserMarkForPoi(m2::PointD const & ptOrg)
return s_selectionUserMark.get();
}
UserMark * UserMarkContainer::CreateUserMark(m2::PointD ptOrg)
UserMark * UserMarkContainer::CreateUserMark(m2::PointD const & ptOrg)
{
m_userMarks.push_back(new UserMark(ptOrg, this));
m_userMarks.push_back(AllocateUserMark(ptOrg));
return m_userMarks.back();
}
@ -329,79 +328,6 @@ 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)
{
using namespace graphics;
graphics::DisplayList * dl = m_cacheScreen->createDisplayList();
m_cacheScreen->beginFrame();
m_cacheScreen->setDisplayList(dl);
Icon::Info infoKey(symbolName);
Resource const * res = m_cacheScreen->fromID(m_cacheScreen->findInfo(infoKey));
shared_ptr<gl::BaseTexture> texture = m_cacheScreen->pipeline(res->m_pipelineID).texture();
m2::RectU texRect = res->m_texRect;
double halfSizeX = texRect.SizeX() / 2.0;
double halfSizeY = texRect.SizeY() / 2.0;
m2::PointD coords[] =
{
m2::PointD(-halfSizeX, -halfSizeY),
m2::PointD(-halfSizeX, halfSizeY),
m2::PointD(halfSizeX, -halfSizeY),
m2::PointD(halfSizeX, halfSizeY)
};
m2::PointF normal(0.0, 0.0);
m2::PointF texCoords[] =
{
texture->mapPixel(m2::PointF(texRect.minX(), texRect.minY())),
texture->mapPixel(m2::PointF(texRect.minX(), texRect.maxY())),
texture->mapPixel(m2::PointF(texRect.maxX(), texRect.minY())),
texture->mapPixel(m2::PointF(texRect.maxX(), texRect.maxY()))
};
m_cacheScreen->addTexturedStripStrided(coords, sizeof(m2::PointD),
&normal, 0,
texCoords, sizeof(m2::PointF),
4, m_layerDepth, res->m_pipelineID);
m_cacheScreen->setDisplayList(NULL);
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);

View file

@ -2,6 +2,7 @@
#include "events.hpp"
#include "user_mark.hpp"
#include "user_mark_dl_cache.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/rect2d.hpp"
@ -49,7 +50,7 @@ public:
};
UserMarkContainer(Type type, double layerDepth, Framework & framework);
~UserMarkContainer();
virtual ~UserMarkContainer();
void SetScreen(graphics::Screen * cacheScreen);
@ -61,14 +62,14 @@ public:
// In multiple select choose mark with min(d)
UserMark const * FindMarkInRect(m2::AnyRectD const & rect, double & d);
void Draw(PaintOverlayEvent const & e);
void Draw(PaintOverlayEvent const & e, UserMarkDLCache * cache) const;
void ActivateMark(UserMark const * mark);
void DiactivateMark();
void Clear();
Type const & GetType() const { return m_type; }
string const & GetTypeName() const;
double GetDepth() const { return m_layerDepth; }
static void InitPoiSelectionMark(UserMarkContainer * container);
static UserMark * UserMarkForPoi(m2::PointD const & ptOrg);
@ -76,22 +77,20 @@ public:
Controller const & GetController() const { return m_controller; }
Controller & GetController() { return m_controller; }
protected:
virtual string GetTypeName() const;
virtual string GetActiveTypeName() const;
virtual UserMark * AllocateUserMark(m2::PointD const & ptOrg);
private:
friend class Controller;
UserMark * CreateUserMark(m2::PointD ptOrg);
UserMark * CreateUserMark(m2::PointD const & 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;
@ -99,9 +98,6 @@ private:
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

102
map/user_mark_dl_cache.cpp Normal file
View file

@ -0,0 +1,102 @@
#include "user_mark_dl_cache.hpp"
#include "../base/stl_add.hpp"
#include "../graphics/display_list.hpp"
#include "../graphics/screen.hpp"
namespace
{
struct Deleter
{
void operator()(pair<UserMarkDLCache::Key, graphics::DisplayList *> const & node)
{
delete node.second;
}
};
}
UserMarkDLCache::UserMarkDLCache(graphics::Screen * cacheScreen)
: m_cacheScreen(cacheScreen)
{
}
UserMarkDLCache::~UserMarkDLCache()
{
DeleteRange(m_dls, Deleter());
m_cacheScreen = NULL;
}
graphics::DisplayList * UserMarkDLCache::FindUserMark(UserMarkDLCache::Key const & key)
{
node_t node = m_dls.find(key);
if (node != m_dls.end())
return node->second;
return CreateDL(key);
}
namespace
{
m2::RectD CalcCoords(double const & halfSizeX, double const & halfSizeY, graphics::EPosition anchor)
{
m2::RectD result(-halfSizeX, -halfSizeY, halfSizeX, halfSizeY);
if (anchor & graphics::EPosAbove)
result.Offset(0.0, -halfSizeY);
else if (anchor & graphics::EPosUnder)
result.Offset(0.0, halfSizeY);
if (anchor & graphics::EPosLeft)
result.Offset(halfSizeX, 0.0);
else if (anchor & graphics::EPosRight)
result.Offset(-halfSizeX, 0.0);
return result;
}
}
graphics::DisplayList * UserMarkDLCache::CreateDL(UserMarkDLCache::Key const & key)
{
using namespace graphics;
graphics::DisplayList * dl = m_cacheScreen->createDisplayList();
m_cacheScreen->beginFrame();
m_cacheScreen->setDisplayList(dl);
Icon::Info infoKey(key.m_name);
Resource const * res = m_cacheScreen->fromID(m_cacheScreen->findInfo(infoKey));
shared_ptr<gl::BaseTexture> texture = m_cacheScreen->pipeline(res->m_pipelineID).texture();
m2::RectU texRect = res->m_texRect;
m2::RectD coord = CalcCoords(texRect.SizeX() / 2.0, texRect.SizeY() / 2.0, key.m_anchor);
m2::PointD coords[] =
{
coord.LeftBottom(),
coord.LeftTop(),
coord.RightBottom(),
coord.RightTop()
};
m2::PointF normal(0.0, 0.0);
m2::PointF texCoords[] =
{
texture->mapPixel(m2::PointF(texRect.minX(), texRect.minY())),
texture->mapPixel(m2::PointF(texRect.minX(), texRect.maxY())),
texture->mapPixel(m2::PointF(texRect.maxX(), texRect.minY())),
texture->mapPixel(m2::PointF(texRect.maxX(), texRect.maxY()))
};
m_cacheScreen->addTexturedStripStrided(coords, sizeof(m2::PointD),
&normal, 0,
texCoords, sizeof(m2::PointF),
4, key.m_depthLayer, res->m_pipelineID);
m_cacheScreen->setDisplayList(NULL);
m_cacheScreen->endFrame();
m_dls.insert(make_pair(key, dl));
return dl;
}

View file

@ -0,0 +1,50 @@
#pragma once
#include "../base/math.hpp"
#include "../graphics/defines.hpp"
#include "../std/map.hpp"
namespace graphics
{
class Screen;
class DisplayList;
}
class UserMarkDLCache
{
public:
struct Key
{
Key(string const & name, graphics::EPosition anchor, double depthLayer)
: m_name(name), m_anchor(anchor), m_depthLayer(depthLayer) {}
string m_name;
graphics::EPosition m_anchor;
double m_depthLayer;
bool operator < (Key const & other) const
{
if (m_name != other.m_name)
return m_name < other.m_name;
if (!my::AlmostEqual(m_depthLayer, other.m_depthLayer))
return m_depthLayer < other.m_depthLayer;
return m_anchor < other.m_anchor;
}
};
UserMarkDLCache(graphics::Screen * cacheScreen);
~UserMarkDLCache();
graphics::DisplayList * FindUserMark(Key const & key);
private:
graphics::DisplayList * CreateDL(Key const & key);
private:
graphics::Screen * m_cacheScreen;
typedef map<Key, graphics::DisplayList *> cache_t;
typedef cache_t::iterator node_t;
cache_t m_dls;
};