diff --git a/geometry/tree4d.hpp b/geometry/tree4d.hpp index 6df5ae9589..c4ec54fbdf 100644 --- a/geometry/tree4d.hpp +++ b/geometry/tree4d.hpp @@ -171,9 +171,9 @@ namespace m4 Add(obj, rect); } - void Erase(T const & obj) + void Erase(T const & obj, m2::RectD const & r) { - value_t val(obj, Traits::LimitRect(obj)); + value_t val(obj, r); m_tree.erase_exact(val); } diff --git a/gui/controller.cpp b/gui/controller.cpp index 00f5d7f2bc..2cd0eed8ea 100644 --- a/gui/controller.cpp +++ b/gui/controller.cpp @@ -9,7 +9,20 @@ namespace gui { - Controller::Controller() : m_VisualScale(1.0) + Controller::RenderParams::RenderParams() + : m_VisualScale(0), m_GlyphCache(0) + {} + + Controller::Controller() + : m_VisualScale(0), m_GlyphCache(0), m_IsAttached(false) + {} + + Controller::RenderParams::RenderParams(double visualScale, + TInvalidateFn invalidateFn, + yg::GlyphCache * glyphCache) + : m_VisualScale(visualScale), + m_InvalidateFn(invalidateFn), + m_GlyphCache(glyphCache) {} Controller::~Controller() @@ -113,38 +126,78 @@ namespace gui void Controller::RemoveElement(shared_ptr const & e) { - m_Overlay.removeOverlayElement(e); - e->m_controller = 0; + TElementRects::const_iterator it = m_ElementRects.find(e); + + if (it != m_ElementRects.end()) + m_Overlay.removeOverlayElement(e, it->second); + + e->setController(0); } void Controller::AddElement(shared_ptr const & e) { - m_Overlay.processOverlayElement(e); - e->m_controller = this; + e->setController(this); + + if (m_IsAttached) + { + m_ElementRects[e] = e->roughBoundRect(); + m_Overlay.processOverlayElement(e); + } + else + m_RawElements.push_back(e); } - double Controller::VisualScale() const + double Controller::GetVisualScale() const { return m_VisualScale; } - void Controller::SetVisualScale(double val) + void Controller::SetRenderParams(RenderParams const & p) { - m_VisualScale = val; - vector > v; - m_Overlay.forEach(MakeBackInsertFunctor(v)); + m_GlyphCache = p.m_GlyphCache; + m_InvalidateFn = p.m_InvalidateFn; + m_VisualScale = p.m_VisualScale; + + m_IsAttached = true; + + base_list_t l; + m_Overlay.forEach(MakeBackInsertFunctor(l)); + + copy(m_RawElements.begin(), m_RawElements.end(), back_inserter(l)); + m_RawElements.clear(); m_Overlay.clear(); - for (vector >::const_iterator it = v.begin(); - it != v.end(); + for (base_list_t::const_iterator it = l.begin(); + it != l.end(); ++it) { (*it)->setIsDirtyRect(true); + m_ElementRects[*it] = (*it)->roughBoundRect(); m_Overlay.processOverlayElement(*it); } } + void Controller::ResetRenderParams() + { + m_GlyphCache = 0; + m_VisualScale = 0; + m_InvalidateFn.clear(); + m_IsAttached = false; + + base_list_t l; + + m_Overlay.forEach(MakeBackInsertFunctor(l)); + + for (base_list_t::const_iterator it = l.begin(); + it != l.end(); + ++it) + m_RawElements.push_back(boost::static_pointer_cast(*it)); + + m_Overlay.clear(); + m_ElementRects.clear(); + } + void Controller::DrawFrame(yg::gl::Screen * screen) { screen->beginFrame(); @@ -156,19 +209,14 @@ namespace gui screen->endFrame(); } - void Controller::SetInvalidateFn(TInvalidateFn fn) - { - m_InvalidateFn = fn; - } - - void Controller::ResetInvalidateFn() - { - m_InvalidateFn.clear(); - } - void Controller::Invalidate() { if (m_InvalidateFn) m_InvalidateFn(); } + + yg::GlyphCache * Controller::GetGlyphCache() const + { + return m_GlyphCache; + } } diff --git a/gui/controller.hpp b/gui/controller.hpp index dfa44bd273..84d2871afe 100644 --- a/gui/controller.hpp +++ b/gui/controller.hpp @@ -35,9 +35,17 @@ namespace gui /// Overlay, which holds all GUI elements. yg::Overlay m_Overlay; - /// container for gui::Element's typedef list > elem_list_t; + /// Temporary list to store gui::Element's before the AttachRenderer call. + /// As the gui::Elements could use the Controller::RendererParams in the bounding + /// rects calculation (for example GlyphCache for gui::TextView or VisualScale + /// for almost every element), we shouldn't call boundRects() function + /// before AttachRenderer. This implies that we couldn't add gui::Element to the + /// yg::Overlay correctly, as the m4::Tree::Add function use gui::Element::roughBoundRect + /// We'll add this elements into yg::Overlay in AttachRenderer function. + elem_list_t m_RawElements; + /// select elements under specified point void SelectElements(m2::PointD const & pt, elem_list_t & l); @@ -47,6 +55,16 @@ namespace gui /// VisualScale to multiply all Device-Independent-Pixels dimensions. double m_VisualScale; + /// GlyphCache for text rendering by GUI elements. + yg::GlyphCache * m_GlyphCache; + + /// Is this controller attached to the renderer? + bool m_IsAttached; + + /// For fast removing of gui::Element's upon element geometry change + typedef map, m2::RectD> TElementRects; + TElementRects m_ElementRects; + public: /// Constructor with GestureDetector to route events from. @@ -60,12 +78,30 @@ namespace gui bool OnTapEnded(m2::PointD const & pt); bool OnTapCancelled(m2::PointD const & pt); /// @} - /// Set Invalidate functor - void SetInvalidateFn(TInvalidateFn fn); - /// Reset Invalidate functor - void ResetInvalidateFn(); - /// Set VisualScale - void SetVisualScale(double val); + + /// Controller should be attached to the renderer before + /// rendering GUI elements. Usually it's done after + /// Framework::SetRenderPolicy + void AttachToRenderer(); + /// Controller should be detached from the renderer + /// when we are about to finish all rendering. + void DetachFromRenderer(); + + struct RenderParams + { + double m_VisualScale; + TInvalidateFn m_InvalidateFn; + yg::GlyphCache * m_GlyphCache; + RenderParams(); + RenderParams(double visualScale, + TInvalidateFn invalidateFn, + yg::GlyphCache * glyphCache); + }; + + /// Attach GUI Controller to the renderer + void SetRenderParams(RenderParams const & p); + /// Detach GUI Controller from the renderer + void ResetRenderParams(); /// Invalidate the scene void Invalidate(); /// Find shared_ptr from the pointer in m_Overlay @@ -75,7 +111,9 @@ namespace gui /// Add GUI element to the controller void AddElement(shared_ptr const & e); /// Get VisualScale parameter - double VisualScale() const; + double GetVisualScale() const; + /// Get GLyphCache + yg::GlyphCache * GetGlyphCache() const; /// Redraw GUI void DrawFrame(yg::gl::Screen * screen); }; diff --git a/gui/element.cpp b/gui/element.cpp index 5924aa5d0e..0ea209436c 100644 --- a/gui/element.cpp +++ b/gui/element.cpp @@ -55,19 +55,30 @@ namespace gui double Element::visualScale() const { if (m_controller) - return m_controller->VisualScale(); + return m_controller->GetVisualScale(); else - return 1.0; + { + LOG(LWARNING, ("unattached gui::Elements shouldn't call gui::Element::visualScale function")); + return 0.0; + } } void Element::setPivot(m2::PointD const & pv) { shared_ptr e = m_controller->FindElement(this); + Controller * controller = m_controller; - controller->RemoveElement(e); - m_controller = controller; + + if (e) + { + controller->RemoveElement(e); + m_controller = controller; + } + OverlayElement::setPivot(pv); - controller->AddElement(e); + + if (e) + controller->AddElement(e); } void Element::draw(yg::gl::OverlayRenderer *r, const math::Matrix & m) const diff --git a/gui/element.hpp b/gui/element.hpp index 1596db6abb..f6d5f1e38f 100644 --- a/gui/element.hpp +++ b/gui/element.hpp @@ -38,8 +38,6 @@ namespace gui private: - friend class Controller; - EState m_state; mutable map m_fonts; @@ -74,5 +72,7 @@ namespace gui void draw(yg::gl::OverlayRenderer * r, math::Matrix const & m) const; int visualRank() const; + + virtual void setController(Controller * controller); }; } diff --git a/map/framework.cpp b/map/framework.cpp index 84b3343df1..0d12bd6a5d 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -890,13 +890,16 @@ void Framework::SetRenderPolicy(RenderPolicy * renderPolicy) } m_renderPolicy.reset(); - m_guiController->ResetInvalidateFn(); + m_guiController->ResetRenderParams(); m_renderPolicy.reset(renderPolicy); if (m_renderPolicy.get()) { - m_guiController->SetVisualScale(renderPolicy->VisualScale()); - m_guiController->SetInvalidateFn(bind(&WindowHandle::invalidate, renderPolicy->GetWindowHandle().get())); + gui::Controller::RenderParams rp(renderPolicy->VisualScale(), + bind(&WindowHandle::invalidate, renderPolicy->GetWindowHandle().get()), + renderPolicy->GetGlyphCache()); + + m_guiController->SetRenderParams(rp); m_renderPolicy->SetEmptyModelFn(bind(&Framework::IsEmptyModel, this, _1)); m_renderPolicy->SetCountryNameFn(bind(&Framework::GetCountryName, this, _1)); diff --git a/map/framework.hpp b/map/framework.hpp index f9e3a533d9..9b5645c936 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -64,8 +64,6 @@ protected: model::FeaturesFetcher m_model; Navigator m_navigator; - scoped_ptr m_guiController; - vector m_bookmarks; scoped_ptr m_renderPolicy; @@ -96,6 +94,7 @@ protected: //mutable threads::Mutex m_modelSyn; storage::Storage m_storage; + scoped_ptr m_guiController; //my::Timer m_timer; inline double ElapsedSeconds() const diff --git a/map/render_policy.cpp b/map/render_policy.cpp index eef644455f..2d285007bd 100644 --- a/map/render_policy.cpp +++ b/map/render_policy.cpp @@ -129,6 +129,11 @@ shared_ptr const & RenderPolicy::GetWindowHandle() const return m_windowHandle; } +yg::GlyphCache * RenderPolicy::GetGlyphCache() const +{ + return m_resourceManager->glyphCache(m_resourceManager->guiThreadGlyphCacheID()); +} + void RenderPolicy::SetRenderFn(TRenderFn renderFn) { m_renderFn = renderFn; diff --git a/map/render_policy.hpp b/map/render_policy.hpp index eca60a3e5d..05d85d501d 100644 --- a/map/render_policy.hpp +++ b/map/render_policy.hpp @@ -20,6 +20,7 @@ namespace yg class RenderContext; } + class GlyphCache; class ResourceManager; } @@ -119,6 +120,7 @@ public: shared_ptr const & GetDrawer() const; shared_ptr const & GetWindowHandle() const; + yg::GlyphCache * GetGlyphCache() const; virtual size_t ScaleEtalonSize() const; diff --git a/yg/overlay.cpp b/yg/overlay.cpp index 36dce7d0ab..da49510e5d 100644 --- a/yg/overlay.cpp +++ b/yg/overlay.cpp @@ -216,9 +216,9 @@ namespace yg m_tree.Add(oe); } - void Overlay::removeOverlayElement(shared_ptr const & oe) + void Overlay::removeOverlayElement(shared_ptr const & oe, m2::RectD const & r) { - m_tree.Erase(oe); + m_tree.Erase(oe, r); } void Overlay::processOverlayElement(shared_ptr const & oe, math::Matrix const & m) diff --git a/yg/overlay.hpp b/yg/overlay.hpp index 189632f576..987da747dc 100644 --- a/yg/overlay.hpp +++ b/yg/overlay.hpp @@ -39,7 +39,7 @@ namespace yg void selectOverlayElements(m2::PointD const & pt, list > & res); - void removeOverlayElement(shared_ptr const & oe); + void removeOverlayElement(shared_ptr const & oe, m2::RectD const & r); void processOverlayElement(shared_ptr const & oe);