diff --git a/data/resources-hdpi/balloon_arrow.png b/data/resources-hdpi/balloon_arrow.png new file mode 100644 index 0000000000..39b35c6a04 Binary files /dev/null and b/data/resources-hdpi/balloon_arrow.png differ diff --git a/data/resources-hdpi/balloon_body.png b/data/resources-hdpi/balloon_body.png new file mode 100644 index 0000000000..204d08085a Binary files /dev/null and b/data/resources-hdpi/balloon_body.png differ diff --git a/data/resources-hdpi/balloon_border.png b/data/resources-hdpi/balloon_border.png new file mode 100644 index 0000000000..d698b01244 Binary files /dev/null and b/data/resources-hdpi/balloon_border.png differ diff --git a/data/resources-hdpi/plus.png b/data/resources-hdpi/plus.png index fa93b8a85b..f41267cec3 100644 Binary files a/data/resources-hdpi/plus.png and b/data/resources-hdpi/plus.png differ diff --git a/data/resources-ldpi/balloon_arrow.png b/data/resources-ldpi/balloon_arrow.png new file mode 100644 index 0000000000..39b35c6a04 Binary files /dev/null and b/data/resources-ldpi/balloon_arrow.png differ diff --git a/data/resources-ldpi/balloon_body.png b/data/resources-ldpi/balloon_body.png new file mode 100644 index 0000000000..204d08085a Binary files /dev/null and b/data/resources-ldpi/balloon_body.png differ diff --git a/data/resources-ldpi/balloon_border.png b/data/resources-ldpi/balloon_border.png new file mode 100644 index 0000000000..d698b01244 Binary files /dev/null and b/data/resources-ldpi/balloon_border.png differ diff --git a/data/resources-ldpi/plus.png b/data/resources-ldpi/plus.png index 4cd51ecdec..f41267cec3 100644 Binary files a/data/resources-ldpi/plus.png and b/data/resources-ldpi/plus.png differ diff --git a/data/resources-mdpi/balloon_arrow.png b/data/resources-mdpi/balloon_arrow.png new file mode 100644 index 0000000000..178f32d342 Binary files /dev/null and b/data/resources-mdpi/balloon_arrow.png differ diff --git a/data/resources-mdpi/balloon_body.png b/data/resources-mdpi/balloon_body.png new file mode 100644 index 0000000000..204d08085a Binary files /dev/null and b/data/resources-mdpi/balloon_body.png differ diff --git a/data/resources-mdpi/balloon_border.png b/data/resources-mdpi/balloon_border.png new file mode 100644 index 0000000000..d698b01244 Binary files /dev/null and b/data/resources-mdpi/balloon_border.png differ diff --git a/data/resources-mdpi/plus.png b/data/resources-mdpi/plus.png index 307566cee3..f41267cec3 100644 Binary files a/data/resources-mdpi/plus.png and b/data/resources-mdpi/plus.png differ diff --git a/data/resources-xhdpi/balloon_arrow.png b/data/resources-xhdpi/balloon_arrow.png new file mode 100644 index 0000000000..39b35c6a04 Binary files /dev/null and b/data/resources-xhdpi/balloon_arrow.png differ diff --git a/data/resources-xhdpi/balloon_body.png b/data/resources-xhdpi/balloon_body.png new file mode 100644 index 0000000000..204d08085a Binary files /dev/null and b/data/resources-xhdpi/balloon_body.png differ diff --git a/data/resources-xhdpi/balloon_border.png b/data/resources-xhdpi/balloon_border.png new file mode 100644 index 0000000000..d698b01244 Binary files /dev/null and b/data/resources-xhdpi/balloon_border.png differ diff --git a/data/resources-xhdpi/plus.png b/data/resources-xhdpi/plus.png index 731c3e3824..f41267cec3 100644 Binary files a/data/resources-xhdpi/plus.png and b/data/resources-xhdpi/plus.png differ diff --git a/gui/balloon.cpp b/gui/balloon.cpp index 1681c7345c..bd203fb6d0 100644 --- a/gui/balloon.cpp +++ b/gui/balloon.cpp @@ -8,44 +8,41 @@ #include "../graphics/screen.hpp" #include "../graphics/path.hpp" +#define TEXT_LEFT_MARGIN 1 +#define TEXT_RIGHT_MARGIN 25 + namespace gui { Balloon::Params::Params() - : m_image(), - m_textMarginLeft(10), - m_textMarginTop(10), - m_textMarginRight(10), - m_textMarginBottom(10), - m_imageMarginLeft(10), - m_imageMarginTop(10), - m_imageMarginRight(10), - m_imageMarginBottom(10) + : m_image() {} Balloon::Balloon(Params const & p) : Element(p), + m_balloonScale(1.0), + m_textImageOffsetH(0.0), + m_textImageOffsetV(0.0), m_boundRects(1) { - m_textMarginLeft = p.m_textMarginLeft; - m_textMarginRight = p.m_textMarginRight; - m_textMarginTop = p.m_textMarginTop; - m_textMarginBottom = p.m_textMarginBottom; - - m_imageMarginLeft = p.m_imageMarginLeft; - m_imageMarginRight = p.m_imageMarginRight; - m_imageMarginTop = p.m_imageMarginTop; - m_imageMarginBottom = p.m_imageMarginBottom; - TextView::Params tp; - tp.m_text = p.m_text; - tp.m_position = graphics::EPosRight; + tp.m_position = graphics::EPosAboveRight; tp.m_pivot = m2::PointD(0, 0); tp.m_depth = depth() + 1; - m_textView.reset(new TextView(tp)); + m_mainTextView.reset(new TextView(tp)); + m_mainTextView->setFont(Element::EActive, graphics::FontDesc(17, graphics::Color(0, 0, 0, 255))); - m_textView->setFont(Element::EActive, graphics::FontDesc(20, graphics::Color(255, 255, 255, 255))); + TextView::Params auxTp; + auxTp.m_text = p.m_auxText; + auxTp.m_position = graphics::EPosAboveRight; + auxTp.m_pivot = m2::PointD(0, 0); + auxTp.m_depth = depth() + 1; + + m_auxTextView.reset(new TextView(auxTp)); + m_auxTextView->setFont(Element::EActive, graphics::FontDesc(12, graphics::Color(51, 51, 51, 255))); + + updateTextMode(p.m_mainText, p.m_auxText); ImageView::Params ip; @@ -55,44 +52,46 @@ namespace gui ip.m_image = p.m_image; m_imageView.reset(new ImageView(ip)); + } - m_arrowHeight = 10; - m_arrowAngle = ang::DegreeToRad(90); - m_arrowWidth = 2 * tan(m_arrowAngle / 2) * m_arrowHeight; + void Balloon::updateTextMode(string const & main, string const & aux) + { + m_textMode = NoText; + if (!main.empty()) + m_textMode = (ETextMode)(m_textMode | SingleMainText); + if (!aux.empty()) + m_textMode = (ETextMode)(m_textMode | SingleAuxText); } vector const & Balloon::boundRects() const { if (isDirtyRect()) { - m2::RectD tr = m_textView->roughBoundRect(); + m2::RectD tr = m_mainTextView->roughBoundRect(); + m2::RectD auxTr = m_auxTextView->roughBoundRect(); m2::RectD ir = m_imageView->roughBoundRect(); double k = visualScale(); - tr.setMinX(tr.minX() - m_textMarginLeft * k); - tr.setMinY(tr.minY() - m_textMarginTop * k); - tr.setMaxX(tr.maxX() + m_textMarginRight * k); - tr.setMaxY(tr.maxY() + m_textMarginBottom * k); + tr.setMinX(tr.minX() - (m_borderImg.m_size.x + TEXT_LEFT_MARGIN) * k); + tr.setMaxX(tr.maxX() + TEXT_RIGHT_MARGIN * k); - ir.setMinX(ir.minX() - m_imageMarginLeft * k); - ir.setMinY(ir.minY() - m_imageMarginTop * k); - ir.setMaxX(ir.maxX() + m_imageMarginRight * k); - ir.setMaxY(ir.maxY() + m_imageMarginBottom * k); + auxTr.setMinX(auxTr.minX() - (m_borderImg.m_size.x + TEXT_LEFT_MARGIN) * k); + auxTr.setMaxX(auxTr.maxX() - TEXT_RIGHT_MARGIN * k); - m2::RectD r(tr); - r.Add(ir); + ir.setMaxX(ir.maxX() + m_borderImg.m_size.x * k); - graphics::EPosition pos = position(); + m2::RectD r(ir); + if (m_textMode & SingleMainText) + r.Add(tr); + if (m_textMode & SingleAuxText) + r.Add(auxTr); - if (pos == graphics::EPosAbove) - r.setMaxY(r.maxY() + m_arrowHeight * k); - else if (pos == graphics::EPosUnder) - r.setMinY(r.minY() - m_arrowHeight * k); - else if (pos == graphics::EPosRight) - r.setMinX(r.minX() - m_arrowHeight * k); - else if (pos == graphics::EPosLeft) - r.setMaxX(r.maxX() + m_arrowHeight * k); + double diff = m_bodyImg.m_size.y + m_arrowImg.m_size.y - r.SizeY(); + double halfDiff = diff / 2.0; + + r.setMaxY(r.maxY() + halfDiff); + r.setMinY(r.minY() - halfDiff); m_boundRects[0] = m2::AnyRectD(r); @@ -104,74 +103,148 @@ namespace gui void Balloon::layout() { - m_textView->setIsDirtyLayout(true); + m_mainTextView->setIsDirtyLayout(true); + m_auxTextView->setIsDirtyLayout(true); m_imageView->setIsDirtyLayout(true); - m2::RectD tr = m_textView->roughBoundRect(); - m2::RectD ir = m_imageView->roughBoundRect(); + + m2::RectD mainTextRect = m_mainTextView->roughBoundRect(); + m2::RectD auxTextRect = m_auxTextView->roughBoundRect(); + m2::RectD imageRect = m_imageView->roughBoundRect(); double k = visualScale(); - double tml = m_textMarginLeft * k; - double tmr = m_textMarginRight * k; - double tmt = m_textMarginTop * k; - double tmb = m_textMarginBottom * k; + double leftMargin = (m_borderImg.m_size.x + TEXT_LEFT_MARGIN) * k; + double rightMargin = TEXT_RIGHT_MARGIN * k; - double iml = m_imageMarginLeft * k; - double imr = m_imageMarginRight * k; - double imt = m_imageMarginTop * k; - double imb = m_imageMarginBottom * k; + double imageMargin = m_borderImg.m_size.x * k; - double arrowHeight = m_arrowHeight * k; + double mainWidth = leftMargin + mainTextRect.SizeX() + rightMargin; + double auxWidth = leftMargin + auxTextRect.SizeX() + rightMargin; + double imageWidth = imageRect.SizeX() + imageMargin; - double w = tml + tr.SizeX() + tmr - + iml + ir.SizeX() + imr; + double maxWidth = max(mainWidth, auxWidth) + imageWidth; - double h = max(ir.SizeY() + imb + imt, - tr.SizeY() + tmb + tmt); + if (m_textMode & SingleMainText) + layoutMainText(maxWidth, leftMargin); - m2::PointD const & pv = pivot(); - graphics::EPosition pos = position(); + if (m_textMode & SingleAuxText) + layoutAuxText(maxWidth, leftMargin); - if (pos == graphics::EPosAbove) - { - m_textView->setPivot(m2::PointD(pv.x - w / 2 + tml, - pv.y - h / 2 - arrowHeight)); - m_imageView->setPivot(m2::PointD(pv.x + w / 2 - imr - ir.SizeX(), - pv.y - h / 2 - arrowHeight)); - } - else if (pos == graphics::EPosUnder) - { - m_textView->setPivot(m2::PointD(pv.x - w / 2 + tml, - pv.y + h / 2 + arrowHeight)); - m_imageView->setPivot(m2::PointD(pv.x + w / 2 - imr - ir.SizeX(), - pv.y + h / 2 + arrowHeight)); - } - else if (pos == graphics::EPosLeft) - { - m_textView->setPivot(m2::PointD(pv.x - w - arrowHeight + tml, - pv.y)); - m_imageView->setPivot(m2::PointD(pv.x - arrowHeight - imr - ir.SizeX(), - pv.y)); - } - else if (pos == graphics::EPosRight) - { - m_textView->setPivot(m2::PointD(pv.x + arrowHeight + tml, - pv.y)); - m_imageView->setPivot(m2::PointD(pv.x + arrowHeight + tml + tr.SizeX() + tmr + imr, - pv.y)); - } + m2::PointD pv = pivot(); + pv.x = pv.x + maxWidth / 2.0 - imageMargin - imageRect.SizeX(); + pv.y -= (m_arrowImg.m_size.y + m_borderImg.m_size.y / 2.0); + + m_imageView->setPivot(pv); - m_textView->setPosition(graphics::EPosRight); m_imageView->setPosition(graphics::EPosRight); } + void Balloon::layoutMainText(double balloonWidth, + double leftMargin) + { + m2::PointD pv = pivot(); + graphics::EPosition newPosition = graphics::EPosRight; + + pv.x = pv.x - balloonWidth / 2.0 + leftMargin; + + if (m_textMode == DualText) + { + pv.y = pv.y - (m_bodyImg.m_size.y / 2.0 + m_arrowImg.m_size.y - 2) ; + newPosition = graphics::EPosAboveRight; + } + else + pv.y = pv.y - (m_bodyImg.m_size.y / 2.0 + m_arrowImg.m_size.y - 2); + + m_mainTextView->setPivot(pv); + m_mainTextView->setPosition(newPosition); + } + + void Balloon::layoutAuxText(double balloonWidth, + double leftMargin) + { + m2::PointD pv = pivot(); + graphics::EPosition newPosition = graphics::EPosRight; + + pv.x = pv.x - balloonWidth / 2.0 + leftMargin; + if (m_textMode == DualText) + { + double textHeight = m_auxTextView->roughBoundRect().SizeY(); + pv.y = pv.y - (m_bodyImg.m_size.y / 2.0 + m_arrowImg.m_size.y) + 1.5 * textHeight; + newPosition = graphics::EPosAboveRight; + } + else + pv.y -= (m_bodyImg.m_size.y / 2.0 + m_arrowImg.m_size.y); + + m_auxTextView->setPivot(pv); + m_auxTextView->setPosition(newPosition); + } + void Balloon::setPivot(m2::PointD const & pv) { Element::setPivot(pv); layout(); } + void Balloon::cacheBorders(graphics::Screen * cs, + graphics::Image::Info &borderImg, + uint32_t balloonWidth, + uint32_t arrowHeight) + { + uint32_t borderID = cs->mapInfo(borderImg); + + double offsetX = balloonWidth / 2.0; + double offsetY = borderImg.m_size.y + arrowHeight; + + math::Matrix identity = math::Identity(); + math::Matrix leftM = math::Shift(identity, + -offsetX, -offsetY); + + cs->drawImage(leftM, borderID, depth()); + + math::Matrix rightM = math::Shift( + math::Scale(identity, -1.0, 1.0), + offsetX, -offsetY); + + cs->drawImage(rightM, borderID, depth()); + } + + void Balloon::cacheBody(graphics::Screen * cs, + graphics::Image::Info & bodyImg, + double offsetX, + double bodyWidth, + uint32_t arrowHeight) + { + uint32_t bodyID = cs->mapInfo(bodyImg); + int32_t bodyCount = (bodyWidth + bodyImg.m_size.x - 1) / (double)(bodyImg.m_size.x); + double offsetY = bodyImg.m_size.y + arrowHeight; + offsetY = -offsetY; + double currentOffsetX = -offsetX; + + math::Matrix m = math::Shift(math::Identity(), + currentOffsetX, offsetY); + + for (int32_t i = 0; i < bodyCount - 1; ++i) + { + cs->drawImage(m, bodyID, depth()); + + m = math::Shift(m, m2::PointF(bodyImg.m_size.x, 0)); + currentOffsetX += bodyImg.m_size.x; + } + + int32_t lastTileWidth = bodyWidth - (bodyImg.m_size.x) * (bodyCount - 1); + double scaleFactor = (double(lastTileWidth) + 2.5)/ (double)(bodyImg.m_size.x); + + math::Matrix lastBodyM = math::Shift( + math::Scale(math::Identity(), scaleFactor, 1.0), + currentOffsetX, offsetY); + cs->drawImage(lastBodyM, bodyID, depth() + 1); + } + void Balloon::cache() { + m2::RectD const & r = roughBoundRect(); + + double bw = r.SizeX(); + graphics::Screen * cs = m_controller->GetCacheScreen(); m_displayList.reset(); @@ -180,50 +253,14 @@ namespace gui cs->beginFrame(); cs->setDisplayList(m_displayList.get()); - m2::RectD const & r = roughBoundRect(); + cacheBorders(cs, m_borderImg, bw, m_arrowImg.m_size.y - 2); + cacheBody(cs, m_bodyImg, bw / 2.0 - (double)m_borderImg.m_size.x, bw - 2.0 * m_borderImg.m_size.x, m_arrowImg.m_size.y - 2); - double k = visualScale(); + uint32_t arrowID = cs->mapInfo(m_arrowImg); - double bw = r.SizeX(); - double bh = r.SizeY(); - double aw = m_arrowWidth * k; - double ah = m_arrowHeight * k; - - graphics::EPosition pos = position(); - graphics::Path p; - - if (pos & graphics::EPosAbove) - { - bh -= ah; - - p.reset(m2::PointF(-aw / 2, -ah)); - p.lineRel(m2::PointF(-bw / 2 + aw / 2, 0)); - p.lineRel(m2::PointF(0, -bh)); - p.lineRel(m2::PointF(bw, 0)); - p.lineRel(m2::PointF(0, bh)); - p.lineRel(m2::PointF(-bw / 2 + aw / 2, 0)); - p.lineRel(m2::PointF(-aw / 2, ah)); - p.lineRel(m2::PointF(-aw / 2, -ah)); - } - else if (pos & graphics::EPosUnder) - { - bh -= ah; - - p.reset(m2::PointF(aw / 2, ah)); - p.lineRel(m2::PointF(bw / 2 - aw / 2, 0)); - p.lineRel(m2::PointF(0, bh)); - p.lineRel(m2::PointF(-bw, 0)); - p.lineRel(m2::PointF(0, -bh)); - p.lineRel(m2::PointF(bw / 2 - aw / 2, 0)); - p.lineRel(m2::PointF(aw / 2, -ah)); - p.lineRel(m2::PointF(aw / 2, ah)); - } - - graphics::Color c(0, 0, 0, 128); - - uint32_t colorID = cs->mapInfo(graphics::Brush::Info(c)); - - cs->drawTrianglesFan(p.points(), p.size(), colorID, depth()); + math::Matrix arrowM = math::Shift(math::Identity(), + -(m_arrowImg.m_size.x / 2.0), -((double)m_arrowImg.m_size.y + 1)); + cs->drawImage(arrowM, arrowID, depth() + 10); cs->setDisplayList(0); cs->endFrame(); @@ -231,16 +268,28 @@ namespace gui void Balloon::purge() { - m_textView->purge(); + m_mainTextView->purge(); + m_auxTextView->purge(); m_imageView->purge(); m_displayList.reset(); } + void Balloon::initBgImages() + { + graphics::EDensity density = m_controller->GetDensity(); + m_borderImg = graphics::Image::Info("balloon_border.png", density); + m_bodyImg = graphics::Image::Info("balloon_body.png", density); + m_arrowImg = graphics::Image::Info("balloon_arrow.png", density); + } + void Balloon::setController(Controller * controller) { Element::setController(controller); - m_textView->setController(controller); + m_mainTextView->setController(controller); + m_auxTextView->setController(controller); m_imageView->setController(controller); + + initBgImages(); } void Balloon::draw(graphics::OverlayRenderer * r, @@ -250,18 +299,23 @@ namespace gui { checkDirtyLayout(); -// r->drawRectangle(roughBoundRect(), graphics::Color(0, 0, 255, 128), depth() + 1); -// r->drawRectangle(m_textView->roughBoundRect(), graphics::Color(0, 255, 255, 128), depth() + 1); -// r->drawRectangle(m_imageView->roughBoundRect(), graphics::Color(0, 255, 0, 128), depth() + 1); - math::Matrix drawM = math::Shift( math::Identity(), pivot() * m); - r->drawDisplayList(m_displayList.get(), drawM); + math::Matrix scaleM = math::Scale(math::Identity(), + m_balloonScale, m_balloonScale); - m_textView->draw(r, m); - m_imageView->draw(r, m); + r->drawDisplayList(m_displayList.get(), scaleM * drawM); + + math::Matrix offsetM = math::Shift(math::Identity(), + m_textImageOffsetV, m_textImageOffsetH); + + if (m_textMode | SingleMainText) + m_mainTextView->draw(r, offsetM * m); + if (m_textMode | SingleAuxText) + m_auxTextView->draw(r, offsetM * m); + m_imageView->draw(r, offsetM * m); } } @@ -299,10 +353,13 @@ namespace gui return false; } - void Balloon::setText(string const & s) + void Balloon::setText(string const & main, string const & aux) { - m_textView->setText(s); + updateTextMode(main, aux); + m_mainTextView->setText(main); + m_auxTextView->setText(aux); setIsDirtyLayout(true); + calcMaxTextWidth(); invalidate(); } @@ -312,4 +369,25 @@ namespace gui setIsDirtyLayout(true); invalidate(); } + + void Balloon::onScreenSize(int w, int h) + { + int minEdge = min(w, h); + m_maxWidth = minEdge - 64; + setIsDirtyLayout(true); + calcMaxTextWidth(); + invalidate(); + } + + void Balloon::calcMaxTextWidth() + { + double k = visualScale(); + double textMargin = (m_borderImg.m_size.x + TEXT_LEFT_MARGIN) * k + + TEXT_RIGHT_MARGIN * k; + + double imageWidth = m_borderImg.m_size.x * k; + unsigned maxTextWidth = ceil(m_maxWidth - (textMargin + imageWidth)); + m_mainTextView->setMaxWidth(maxTextWidth); + m_auxTextView->setMaxWidth(maxTextWidth); + } } diff --git a/gui/balloon.hpp b/gui/balloon.hpp index 41b70fc989..d12b00a8e1 100644 --- a/gui/balloon.hpp +++ b/gui/balloon.hpp @@ -16,6 +16,7 @@ namespace graphics { class OverlayRenderer; + class Screen; } namespace gui @@ -23,33 +24,61 @@ namespace gui class Balloon : public Element { protected: - scoped_ptr m_textView; + scoped_ptr m_mainTextView; + scoped_ptr m_auxTextView; + scoped_ptr m_imageView; + + double m_balloonScale; + double m_textImageOffsetH; + double m_textImageOffsetV; private: - scoped_ptr m_imageView; + enum ETextMode + { + NoText = 0, + SingleMainText = 0x1, + SingleAuxText = 0x2, + DualText = SingleMainText | SingleAuxText + }; + + ETextMode m_textMode; + + uint32_t m_maxWidth; + + void updateTextMode(string const & main, string const & aux); + scoped_ptr m_displayList; typedef function TOnClickListener; mutable vector m_boundRects; + void cacheBorders(graphics::Screen * cs, + graphics::Image::Info & borderImg, + uint32_t balloonWidth, + uint32_t arrowHeight); + void cacheBody(graphics::Screen * cs, + graphics::Image::Info & bodyImg, + double offsetX, + double bodyWidth, + uint32_t arrowHeight); + + void initBgImages(); + void cache(); void purge(); void layout(); - double m_textMarginLeft; - double m_textMarginTop; - double m_textMarginRight; - double m_textMarginBottom; + void layoutMainText(double balloonWidth, + double leftMargin); + void layoutAuxText(double balloonWidth, + double leftMargin); - double m_imageMarginLeft; - double m_imageMarginTop; - double m_imageMarginRight; - double m_imageMarginBottom; + void calcMaxTextWidth(); - double m_arrowHeight; - double m_arrowWidth; - double m_arrowAngle; + graphics::Image::Info m_borderImg; + graphics::Image::Info m_bodyImg; + graphics::Image::Info m_arrowImg; TOnClickListener m_onClickListener; @@ -59,16 +88,9 @@ namespace gui struct Params : public base_t::Params { - string m_text; + string m_mainText; + string m_auxText; graphics::Image::Info m_image; - double m_textMarginLeft; - double m_textMarginTop; - double m_textMarginRight; - double m_textMarginBottom; - double m_imageMarginLeft; - double m_imageMarginTop; - double m_imageMarginRight; - double m_imageMarginBottom; Params(); }; @@ -82,12 +104,14 @@ namespace gui void setOnClickListener(TOnClickListener const & fn); - void setText(string const & s); + void setText(string const & main, string const & aux); void setImage(graphics::Image::Info const & info); 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 onScreenSize(int w, int h); }; } diff --git a/map/bookmark_balloon.cpp b/map/bookmark_balloon.cpp index 41973c19df..62db7d2963 100644 --- a/map/bookmark_balloon.cpp +++ b/map/bookmark_balloon.cpp @@ -1,8 +1,88 @@ #include "bookmark_balloon.hpp" #include "framework.hpp" +#include "../geometry/transformations.hpp" + +#include "../anim/controller.hpp" +#include "../anim/value_interpolation.hpp" + #define POPUP_PADDING 23 +class BookmarkBalloon::BalloonAnimTask : public anim::Task +{ +public: + BalloonAnimTask(double startScale, double endScale, + double startOffset, double endOffset, + double interval) + : m_scaleAnim(startScale, endScale, interval, m_scale), + m_offsetAnim(startOffset, endOffset, interval, m_offset) + { + m_scale = startScale; + m_offset = startOffset; + } + + void OnStart(double ts) + { + m_scaleAnim.Start(); + m_scaleAnim.OnStart(ts); + + m_offsetAnim.Start(); + m_offsetAnim.OnStart(ts); + anim::Task::OnStart(ts); + } + + void OnStep(double ts) + { + m_scaleAnim.OnStep(ts); + m_offsetAnim.OnStep(ts); + UpdateState(); + anim::Task::OnStep(ts); + } + + void OnEnd(double ts) + { + m_scaleAnim.OnEnd(ts); + m_offsetAnim.OnEnd(ts); + UpdateState(); + anim::Task::OnEnd(ts); + } + + void OnCancel(double ts) + { + m_scaleAnim.OnCancel(ts); + m_offsetAnim.OnCancel(ts); + UpdateState(); + anim::Task::OnCancel(ts); + } + + double GetScale() const + { + return m_scale; + } + + double GetOffset() const + { + return m_offset; + } + + bool IsVisual() const + { + return true; + } + +private: + void UpdateState() + { + SetState(m_scaleAnim.State()); + } + +private: + anim::ValueInterpolation m_scaleAnim; + anim::ValueInterpolation m_offsetAnim; + double m_scale; + double m_offset; +}; + BookmarkBalloon::BookmarkBalloon(Params const & p) : Balloon(p), m_framework(p.m_framework) @@ -17,9 +97,72 @@ void BookmarkBalloon::update() m2::PointD newPivot(m_framework->GtoP(m_glbPivot)); newPivot.y -= POPUP_PADDING * visualScale(); setPivot(newPivot); + + if (m_currentAnimTask) + { + m_balloonScale = m_currentAnimTask->GetScale(); + m_textImageOffsetH = m_currentAnimTask->GetOffset(); + } } } +void BookmarkBalloon::createTask(double startScale, double endScale, double startOffset, double endOffset, double interval, int index) +{ + m_currentAnimTask.reset(new BalloonAnimTask(startScale, endScale, startOffset, endOffset, interval)); + m_currentAnimTask->AddCallback(anim::Task::EEnded, bind(&BookmarkBalloon::animTaskEnded, this, index)); + m_currentAnimTask->AddCallback(anim::Task::ECancelled, bind(&BookmarkBalloon::cancelTask, this)); + m_framework->GetAnimController()->AddTask(m_currentAnimTask); +} + +void BookmarkBalloon::animTaskEnded(int animIndex) +{ + bool isVisibleTextAndImage = true; + switch(animIndex) + { + case 0: + createTask(0.1, 1.05, 0.0, 0.0, 0.1, 1); + isVisibleTextAndImage = false; + break; + case 1: + createTask(1.05, 0.95, -2.0, 5.0, 0.05, 2); + break; + case 2: + createTask(0.95, 1.0, 5.0, 0.0, 0.02, 3); + break; + } + + m_mainTextView->setIsVisible(isVisibleTextAndImage); + m_imageView->setIsVisible(isVisibleTextAndImage); +} + +void BookmarkBalloon::cancelTask() +{ + if (m_currentAnimTask) + { + m_currentAnimTask->Lock(); + if (!m_currentAnimTask->IsEnded() && + !m_currentAnimTask->IsCancelled()) + { + m_currentAnimTask->Cancel(); + } + + m_currentAnimTask->Unlock(); + m_currentAnimTask.reset(); + } +} + +void BookmarkBalloon::showAnimated() +{ + animTaskEnded(0); + setIsVisible(true); +} + +void BookmarkBalloon::hide() +{ + cancelTask(); + setIsVisible(false); +} + void BookmarkBalloon::setGlbPivot(m2::PointD const & pivot) { m_glbPivot = pivot; @@ -30,22 +173,29 @@ m2::PointD const BookmarkBalloon::glbPivot() return m_glbPivot; } -void BookmarkBalloon::setBookmarkName(string const & name) +void BookmarkBalloon::setBookmarkCaption(string const & name, + string const & type) { m_bmkName = name; + m_bmkType = type; - strings::UniString s = strings::MakeUniString(name); + /*strings::UniString uniName = strings::MakeUniString(name); + strings::UniString uniType = strings::MakeUniString(type); // 15 is going from straight_text_element.cpp, visSplit. - if (s.size() > 15) + if (uniName.size() > 15) { - s.resize(18); - s[17] = s[16] = s[15] = '.'; - - setText(strings::ToUtf8(s)); + uniName.resize(18); + uniName[17] = uniName[16] = uniName[15] = '.'; } - else - setText(name); + + if (uniType.size() > 15) + { + uniType.resize(18); + uniType[17] = uniType[16] = uniType[15] = '.'; + }*/ + + setText(name, type); } string const & BookmarkBalloon::bookmarkName() diff --git a/map/bookmark_balloon.hpp b/map/bookmark_balloon.hpp index 16a1aa82e0..2a08a9c19d 100644 --- a/map/bookmark_balloon.hpp +++ b/map/bookmark_balloon.hpp @@ -10,9 +10,19 @@ class BookmarkBalloon : public gui::Balloon { private: + class BalloonAnimTask; + shared_ptr m_currentAnimTask; + m2::PointD m_glbPivot; Framework const * m_framework; string m_bmkName; + string m_bmkType; + + void createTask(double startScale, double endScale, + double startOffset, double endOffset, + double interval, int index); + void animTaskEnded(int animIndex); + void cancelTask(); void update(); @@ -27,9 +37,12 @@ public: BookmarkBalloon(Params const & p); + void showAnimated(); + void hide(); + void setGlbPivot(m2::PointD const & pivot); m2::PointD const glbPivot(); - void setBookmarkName(string const & name); + void setBookmarkCaption(string const & name, string const & type); string const & bookmarkName(); };