diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 4b0206d002..98dcd0bea7 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -44,7 +44,7 @@ LOCAL_SRC_FILES := \ nv_time/nv_time.cpp LOCAL_LDLIBS := -llog -lGLESv2 \ - -lmap -lversion -lsearch -lstorage -lindexer -lyg -lplatform \ + -lmap -lgui -lversion -lsearch -lstorage -lindexer -lyg -lplatform \ -lgeometry -lcoding -lbase -lexpat -lfreetype -lfribidi -lzlib -lbzip2 \ -ljansson -ltomcrypt -lprotobuf ./obj/local/$(TARGET_ARCH_ABI)/libgnustl_static.a diff --git a/gui/button.cpp b/gui/button.cpp new file mode 100644 index 0000000000..c25fd5155c --- /dev/null +++ b/gui/button.cpp @@ -0,0 +1,123 @@ +#include "button.hpp" +#include "../yg/overlay_renderer.hpp" + +namespace gui +{ + Button::Button(Params const & p) : Element(p) + { + setWidth(p.m_width); + setHeight(p.m_height); + setText(p.m_text); + + setFont(EActive, yg::FontDesc(12, yg::Color(0, 0, 0, 255))); + setFont(EPressed, yg::FontDesc(12, yg::Color(0, 0, 0, 255))); + + setColor(EActive, yg::Color(yg::Color(192, 192, 192, 255))); + setColor(EPressed, yg::Color(yg::Color(64, 64, 64, 255))); + } + + void Button::setOnClickListener(TOnClickListener const & l) + { + m_OnClickListener = l; + } + + bool Button::onTapStarted(m2::PointD const & pt) + { + setState(EPressed); + invalidate(); + return false; + } + + bool Button::onTapCancelled(m2::PointD const & pt) + { + setState(EActive); + invalidate(); + return false; + } + + bool Button::onTapEnded(m2::PointD const & pt) + { + setState(EActive); + if (m_OnClickListener) + m_OnClickListener(this); + invalidate(); + return false; + } + + bool Button::onTapMoved(m2::PointD const & pt) + { + invalidate(); + return false; + } + + void Button::setText(string const & text) + { + m_text = text; + } + + string const & Button::text() const + { + return m_text; + } + + void Button::setWidth(unsigned widthInDIP) + { + m_widthInDIP = widthInDIP; + invalidate(); + } + + unsigned Button::width() const + { + return m_widthInDIP; + } + + void Button::setHeight(unsigned heightInDIP) + { + m_heightInDIP = heightInDIP; + invalidate(); + } + + unsigned Button::height() const + { + return m_heightInDIP; + } + + yg::OverlayElement * Button::clone(math::Matrix const & m) const + { + return new Button(*this); + } + + vector const & Button::boundRects() const + { + if (isDirtyRect()) + { + m_boundRects.clear(); + m2::RectD rc(0, 0, width() * visualScale(), height() * visualScale()); + rc.Offset(tieRect(rc, math::Identity())); + m_boundRects.push_back(m2::AnyRectD(m2::RectD(rc))); + setIsDirtyRect(false); + } + + return m_boundRects; + } + + void Button::draw(yg::gl::OverlayRenderer * r, math::Matrix const & m) const + { + if (!isVisible()) + return; + + m2::RectD rc(0, 0, width() * visualScale(), height() * visualScale()); + rc.Offset(tieRect(rc, m)); + r->drawRoundedRectangle(rc, 10 * visualScale(), color(state()), depth()); + + yg::FontDesc desc = font(state()); + desc.m_size *= visualScale(); + + r->drawText(desc, pivot(), position(), text(), depth(), false, false); + } + + int Button::visualRank() const + { + return 0; + } +} diff --git a/gui/button.hpp b/gui/button.hpp new file mode 100644 index 0000000000..55a956c32c --- /dev/null +++ b/gui/button.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "element.hpp" + +#include "../std/function.hpp" +#include "../std/shared_ptr.hpp" +#include "../std/string.hpp" + +namespace yg +{ + class OverlayElement; + + namespace gl + { + class OverlayRenderer; + } +} + +namespace gui +{ + class Button : public Element + { + public: + + typedef function TOnClickListener; + + private: + + TOnClickListener m_OnClickListener; + + unsigned m_widthInDIP; + unsigned m_heightInDIP; + + string m_text; + mutable vector m_boundRects; + + public: + + struct Params : Element::Params + { + unsigned m_width; + unsigned m_height; + string m_text; + }; + + Button(Params const & p); + + bool onTapStarted(m2::PointD const & pt); + bool onTapMoved(m2::PointD const & pt); + bool onTapEnded(m2::PointD const & pt); + bool onTapCancelled(m2::PointD const & pt); + + void setOnClickListener(TOnClickListener const & l); + + void setText(string const & text); + string const & text() const; + + void setWidth(unsigned widthInDIP); + unsigned width() const; + + void setHeight(unsigned heightInDIP); + unsigned height() const; + + /// Inherited from OverlayElement + /// @{ + + yg::OverlayElement * clone(math::Matrix const & m) const; + vector const & boundRects() const; + void draw(yg::gl::OverlayRenderer * r, math::Matrix const & m) const; + int visualRank() const; + + /// @} + }; +} diff --git a/gui/controller.cpp b/gui/controller.cpp new file mode 100644 index 0000000000..90c8baf5f9 --- /dev/null +++ b/gui/controller.cpp @@ -0,0 +1,133 @@ +#include "controller.hpp" +#include "element.hpp" + +#include "../map/drawer_yg.hpp" + +#include "../yg/overlay.hpp" + +#include "../std/bind.hpp" + +namespace gui +{ + Controller::Controller() : m_VisualScale(1.0) + {} + + Controller::~Controller() + {} + + void Controller::SelectElements(m2::PointD const & pt, elem_list_t & l) + { + base_list_t ll; + m_Overlay.selectOverlayElements(pt, ll); + for (base_list_t::const_iterator it = ll.begin(); it != ll.end(); ++it) + if ((*it)->roughHitTest(pt) && (*it)->hitTest(pt)) + l.push_back(boost::static_pointer_cast(*it)); + } + + bool Controller::OnTapStarted(m2::PointD const & pt) + { + elem_list_t l; + + SelectElements(pt, l); + + /// selecting first hit-tested element from the list + if (!l.empty()) + { + m_focusedElement = l.front(); + m_focusedElement->onTapStarted(pt); + return true; + } + + return false; + } + + bool Controller::OnTapMoved(m2::PointD const & pt) + { + if (m_focusedElement) + { + if (!m_focusedElement->roughHitTest(pt) || !m_focusedElement->hitTest(pt)) + m_focusedElement->onTapCancelled(pt); + else + m_focusedElement->onTapMoved(pt); + + /// event handled + return true; + } + + return false; + } + + bool Controller::OnTapEnded(m2::PointD const & pt) + { + if (m_focusedElement) + { + m_focusedElement->onTapEnded(pt); + m_focusedElement.reset(); + + return true; + } + + return false; + } + + bool Controller::OnTapCancelled(m2::PointD const & pt) + { + if (m_focusedElement) + { + m_focusedElement->onTapCancelled(pt); + m_focusedElement.reset(); + return true; + } + + return false; + } + + void Controller::AddElement(shared_ptr const & e) + { + m_Overlay.processOverlayElement(e); + e->m_controller = this; + } + + void Controller::UpdateElement(Element * e) + { + m_Overlay.updateOverlayElement(e); + } + + double Controller::VisualScale() const + { + return m_VisualScale; + } + + void Controller::SetVisualScale(double val) + { + m_VisualScale = val; + m_Overlay.forEach(bind(&yg::OverlayElement::setIsDirtyRect, _1, true)); + } + + void Controller::DrawFrame(yg::gl::Screen * screen) + { + screen->beginFrame(); + + math::Matrix m = math::Identity(); + + m_Overlay.draw(screen, m); + + screen->endFrame(); + } + + void Controller::SetInvalidateFn(TInvalidateFn fn) + { + m_InvalidateFn = fn; + } + + void Controller::ResetInvalidateFn() + { + m_InvalidateFn.clear(); + } + + void Controller::Invalidate() + { + if (m_InvalidateFn) + m_InvalidateFn(); + } +} diff --git a/gui/controller.hpp b/gui/controller.hpp new file mode 100644 index 0000000000..bab382efc3 --- /dev/null +++ b/gui/controller.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "../std/shared_ptr.hpp" +#include "../std/function.hpp" +#include "../yg/overlay.hpp" + +namespace yg +{ + namespace gl + { + class Screen; + } +} + +namespace gui +{ + class Element; + + /// Controller for GUI elements, which tracks mouse, keyboard and + /// touch user interactions into interactions with GUI elements. + class Controller + { + public: + + /// Invalidate functor type + typedef function TInvalidateFn; + + private: + + /// element that has focus. + shared_ptr m_focusedElement; + + typedef list > base_list_t; + + /// Overlay, which holds all GUI elements. + yg::Overlay m_Overlay; + + /// container for gui::Element's + typedef list > elem_list_t; + + /// select elements under specified point + void SelectElements(m2::PointD const & pt, elem_list_t & l); + + /// Invalidate GUI function + TInvalidateFn m_InvalidateFn; + + /// VisualScale to multiply all Device-Independent-Pixels dimensions. + double m_VisualScale; + + public: + + /// Constructor with GestureDetector to route events from. + Controller(); + /// Destructor + virtual ~Controller(); + /// Handlers to be called from the client code to power up the GUI. + /// @{ + bool OnTapStarted(m2::PointD const & pt); + bool OnTapMoved(m2::PointD const & pt); + 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); + /// Invalidate the scene + void Invalidate(); + /// Add GUI element to the controller + void AddElement(shared_ptr const & e); + /// Update element position in the Overlay, as it's coordinates might have changed. + void UpdateElement(Element * e); + /// Get VisualScale parameter + double VisualScale() const; + /// Redraw GUI + void DrawFrame(yg::gl::Screen * screen); + }; +} diff --git a/gui/element.cpp b/gui/element.cpp new file mode 100644 index 0000000000..e6b19c5363 --- /dev/null +++ b/gui/element.cpp @@ -0,0 +1,72 @@ +#include "element.hpp" +#include "controller.hpp" + +#include "../base/logging.hpp" + +namespace gui +{ + Element::Element(Params const & p) + : OverlayElement(p), + m_controller(0), + m_state(EActive) + { + } + + void Element::setState(EState state) + { + m_state = state; + } + + Element::EState Element::state() const + { + return m_state; + } + + void Element::setFont(EState state, yg::FontDesc const & font) + { + m_fonts[state] = font; + } + + yg::FontDesc const & Element::font(EState state) const + { + return m_fonts[state]; + } + + void Element::setColor(EState state, yg::Color const & c) + { + m_colors[state] = c; + } + + yg::Color const & Element::color(EState state) const + { + return m_colors[state]; + } + + void Element::invalidate() + { + if (m_controller) + m_controller->Invalidate(); + else + LOG(LWARNING, ("unattached gui::Element couldn't be invalidated!")); + } + + double Element::visualScale() const + { + if (m_controller) + return m_controller->VisualScale(); + else + return 1.0; + } + + void Element::setPivot(m2::PointD const & pv) + { + OverlayElement::setPivot(pv); + m_controller->UpdateElement(this); + } + + void Element::offset(m2::PointD const & offs) + { + OverlayElement::offset(offs); + m_controller->UpdateElement(this); + } +} diff --git a/gui/element.hpp b/gui/element.hpp new file mode 100644 index 0000000000..c1265dc8c3 --- /dev/null +++ b/gui/element.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "../geometry/point2d.hpp" + +#include "../yg/overlay_element.hpp" +#include "../yg/color.hpp" +#include "../yg/font_desc.hpp" + +#include "../std/map.hpp" + +namespace gui +{ + class Controller; + + class Element : public yg::OverlayElement + { + public: + + enum EState + { + EInactive, + EActive, + EPressed, + ESelected + }; + + protected: + + Controller * m_controller; + + private: + + friend class Controller; + + EState m_state; + + mutable map m_fonts; + mutable map m_colors; + + public: + + typedef OverlayElement::Params Params; + + Element(Params const & p); + + void setState(EState state); + EState state() const; + + void setFont(EState state, yg::FontDesc const & font); + yg::FontDesc const & font(EState state) const; + + void setColor(EState state, yg::Color const & c); + yg::Color const & color(EState state) const; + + /// Implement this method to handle single tap on the GUI element. + virtual bool onTapStarted(m2::PointD const & pt) = 0; + virtual bool onTapMoved(m2::PointD const & pt) = 0; + virtual bool onTapEnded(m2::PointD const & pt) = 0; + virtual bool onTapCancelled(m2::PointD const & pt) = 0; + + void invalidate(); + double visualScale() const; + + void offset(m2::PointD const & offs); + void setPivot(m2::PointD const & pv); + }; +} diff --git a/gui/gui.pro b/gui/gui.pro new file mode 100644 index 0000000000..c70b2d7b79 --- /dev/null +++ b/gui/gui.pro @@ -0,0 +1,26 @@ +# GUI library on top of YG + +TARGET = gui +TEMPLATE = lib +CONFIG += staticlib + +ROOT_DIR = .. +DEPENDENCIES = yg geometry coding base expat + +include($$ROOT_DIR/common.pri) + +HEADERS += \ + controller.hpp\ + element.hpp \ + button.hpp \ + +SOURCES += \ + controller.cpp \ + element.cpp \ + button.cpp \ + + + + + + diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 68e2da587e..4cd2becd3c 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -32,6 +32,8 @@ EE12021211CD464100ABDD5D /* libyg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE12020811CD464100ABDD5D /* libyg.a */; }; EE164811135CEE4A003B8A3E /* 06_code2000.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EE164810135CEE49003B8A3E /* 06_code2000.ttf */; }; EE583CBB12F773F00042CBE3 /* unicode_blocks.txt in Resources */ = {isa = PBXBuildFile; fileRef = EE583CBA12F773F00042CBE3 /* unicode_blocks.txt */; }; + EE5A34E6156FCB9500E34FFE /* libgui.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE5A34E5156FCB9500E34FFE /* libgui.a */; }; + EE5A34E7156FCBD800E34FFE /* libgui.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE5A34E5156FCB9500E34FFE /* libgui.a */; }; EE7F29811219ECA300EB67A9 /* RenderBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */; }; EE7F29821219ECA300EB67A9 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297E1219ECA300EB67A9 /* RenderContext.mm */; }; EEA61601134C496A003A9827 /* 01_dejavusans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EEA615E5134C4968003A9827 /* 01_dejavusans.ttf */; }; @@ -1335,6 +1337,7 @@ EE16192B126E374500622BD0 /* RenderContext.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = RenderContext.hpp; path = Classes/RenderContext.hpp; sourceTree = SOURCE_ROOT; }; EE164810135CEE49003B8A3E /* 06_code2000.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = 06_code2000.ttf; path = ../../data/06_code2000.ttf; sourceTree = SOURCE_ROOT; }; EE583CBA12F773F00042CBE3 /* unicode_blocks.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = unicode_blocks.txt; path = ../../data/unicode_blocks.txt; sourceTree = ""; }; + EE5A34E5156FCB9500E34FFE /* libgui.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libgui.a"; sourceTree = SOURCE_ROOT; }; EE7F297C1219ECA300EB67A9 /* RenderBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = RenderBuffer.hpp; path = Classes/RenderBuffer.hpp; sourceTree = SOURCE_ROOT; }; EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = RenderBuffer.mm; path = Classes/RenderBuffer.mm; sourceTree = SOURCE_ROOT; }; EE7F297E1219ECA300EB67A9 /* RenderContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = RenderContext.mm; path = Classes/RenderContext.mm; sourceTree = SOURCE_ROOT; }; @@ -2024,6 +2027,7 @@ FAAFD699139D9C6B000AE70C /* libsearch.a in Frameworks */, FAEA8B2A1437CA80002A6737 /* libjansson.a in Frameworks */, FAF29847146EEF4A00FF0057 /* libprotobuf.a in Frameworks */, + EE5A34E6156FCB9500E34FFE /* libgui.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2054,6 +2058,7 @@ FAFB090F151215EE0041901D /* libsearch.a in Frameworks */, FAFB0910151215EE0041901D /* libjansson.a in Frameworks */, FAFB0911151215EE0041901D /* libprotobuf.a in Frameworks */, + EE5A34E7156FCBD800E34FFE /* libgui.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2239,6 +2244,7 @@ FA1DE68411E15D4E00C6D69A /* Static Libraries */ = { isa = PBXGroup; children = ( + EE5A34E5156FCB9500E34FFE /* libgui.a */, FAF29846146EEF4A00FF0057 /* libprotobuf.a */, FAEA8B291437CA80002A6737 /* libjansson.a */, FAAFD698139D9C6B000AE70C /* libsearch.a */, diff --git a/map/map.pro b/map/map.pro index d14b032cb8..2117110227 100644 --- a/map/map.pro +++ b/map/map.pro @@ -6,7 +6,7 @@ CONFIG += staticlib INCLUDEPATH += ../3party/protobuf/src ROOT_DIR = .. -DEPENDENCIES = search yg indexer geometry coding base expat +DEPENDENCIES = search gui yg indexer geometry coding base expat include($$ROOT_DIR/common.pri) diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index db221a3b1d..edd80de6e9 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -6,7 +6,7 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = map search storage yg indexer platform geometry coding base \ +DEPENDENCIES = map gui search storage yg indexer platform geometry coding base \ freetype fribidi expat protobuf tomcrypt jansson include($$ROOT_DIR/common.pri) diff --git a/omim.pro b/omim.pro index d3852a1031..44f2fc767f 100644 --- a/omim.pro +++ b/omim.pro @@ -17,6 +17,7 @@ SUBDIRS = 3party \ geometry/geometry_tests \ platform/platform_tests \ yg \ + gui \ storage storage/storage_tests \ search search/search_tests \ map map/map_tests map/benchmark_tool \ @@ -37,6 +38,7 @@ SUBDIRS = 3party \ indexer \ storage \ yg \ + gui \ search \ - map + map \ } diff --git a/qt/qt.pro b/qt/qt.pro index 0eca15be33..ed89f5e440 100644 --- a/qt/qt.pro +++ b/qt/qt.pro @@ -1,6 +1,6 @@ # Main application in qt. ROOT_DIR = .. -DEPENDENCIES = map search storage indexer yg platform geometry coding base \ +DEPENDENCIES = map gui search storage indexer yg platform geometry coding base \ bzip2 freetype expat fribidi tomcrypt jansson version protobuf include($$ROOT_DIR/common.pri) diff --git a/yg/overlay.cpp b/yg/overlay.cpp index 5a04f9508c..6e5df8c411 100644 --- a/yg/overlay.cpp +++ b/yg/overlay.cpp @@ -153,6 +153,22 @@ namespace yg m_tree.Add(oe); } + struct DoPreciseSelect + { + m2::PointD m_pt; + list > * m_elements; + + DoPreciseSelect(m2::PointD const & pt, list > * elements) + : m_pt(pt), m_elements(elements) + {} + + void operator()(shared_ptr const & e) + { + if (e->hitTest(m_pt)) + m_elements->push_back(e); + } + }; + struct DoPreciseIntersect { shared_ptr m_oe; @@ -183,6 +199,12 @@ namespace yg } }; + void Overlay::selectOverlayElements(m2::PointD const & pt, list > & res) + { + DoPreciseSelect fn(pt, &res); + m_tree.ForEachInRect(m2::RectD(pt - m2::PointD(1, 1), pt + m2::PointD(1, 1)), fn); + } + void Overlay::replaceOverlayElement(shared_ptr const & oe) { bool isIntersect = false; @@ -194,6 +216,39 @@ namespace yg m_tree.Add(oe); } + void Overlay::removeOverlayElement(shared_ptr const & oe) + { + m_tree.Erase(oe); + } + + struct FindByPointer + { + OverlayElement * m_e; + shared_ptr * m_res; + FindByPointer(OverlayElement * e, shared_ptr * res) : m_e(e), m_res(res) + {} + + void operator()(shared_ptr const & oe) + { + if (m_e == oe.get()) + *m_res = oe; + } + }; + + void Overlay::updateOverlayElement(OverlayElement *oe) + { + shared_ptr res; + FindByPointer fn(oe, &res); + + m_tree.ForEach(fn); + + if (res) + { + m_tree.Erase(res); + m_tree.Add(res); + } + } + void Overlay::processOverlayElement(shared_ptr const & oe, math::Matrix const & m) { if (m != math::Identity()) @@ -204,13 +259,10 @@ namespace yg void Overlay::processOverlayElement(shared_ptr const & oe) { - if (oe->isVisible()) - { - if (m_couldOverlap) - addOverlayElement(oe); - else - replaceOverlayElement(oe); - } + if (m_couldOverlap) + addOverlayElement(oe); + else + replaceOverlayElement(oe); } bool greater_priority(shared_ptr const & l, diff --git a/yg/overlay.hpp b/yg/overlay.hpp index e092fc1ba5..fef884bb75 100644 --- a/yg/overlay.hpp +++ b/yg/overlay.hpp @@ -37,6 +37,12 @@ namespace yg void draw(gl::OverlayRenderer * r, math::Matrix const & m); + void selectOverlayElements(m2::PointD const & pt, list > & res); + + void removeOverlayElement(shared_ptr const & oe); + + void updateOverlayElement(OverlayElement * oe); + void processOverlayElement(shared_ptr const & oe); void processOverlayElement(shared_ptr const & oe, math::Matrix const & m); @@ -53,6 +59,12 @@ namespace yg bool checkHasEquals(Overlay const * l) const; + template + void forEach(Fn fn) + { + m_tree.ForEach(fn); + } + Overlay * clone() const; }; } diff --git a/yg/overlay_element.hpp b/yg/overlay_element.hpp index c956bd2824..4bf1d606d1 100644 --- a/yg/overlay_element.hpp +++ b/yg/overlay_element.hpp @@ -29,12 +29,10 @@ namespace yg mutable bool m_isDirtyRoughRect; mutable m2::RectD m_roughBoundRect; - protected: + public: m2::PointD const tieRect(m2::RectD const & r, math::Matrix const & m) const; - public: - struct Params { m2::PointD m_pivot; @@ -54,10 +52,9 @@ namespace yg virtual int visualRank() const = 0; m2::PointD const & pivot() const; - void setPivot(m2::PointD const & pv); + virtual void setPivot(m2::PointD const & pv); - m2::PointD const & offset() const; - void setOffset(m2::PointD const & offs); + virtual void offset(m2::PointD const & offs); yg::EPosition position() const; void setPosition(yg::EPosition pos); @@ -77,11 +74,10 @@ namespace yg bool isVisible() const; void setIsVisible(bool flag); - m2::RectD const & roughBoundRect() const; bool hitTest(m2::PointD const & pt) const; bool roughHitTest(m2::PointD const & pt) const; - virtual void offset(m2::PointD const & offs); + m2::RectD const & roughBoundRect() const; }; }