refactored location::State to make it gui::Element.

This commit is contained in:
rachytski 2012-08-20 12:35:59 +03:00 committed by Alex Zolotarev
parent 47b22d3964
commit e00411fd42
6 changed files with 323 additions and 86 deletions

View file

@ -65,12 +65,12 @@ void Framework::RemoveMap(string const & datFile)
void Framework::SkipLocationCentering()
{
m_locationState.SkipLocationCentering();
m_informationDisplay.locationState()->SkipLocationCentering();
}
void Framework::OnLocationStatusChanged(location::TLocationStatus newStatus)
{
m_locationState.OnLocationStatusChanged(newStatus);
m_informationDisplay.locationState()->OnLocationStatusChanged(newStatus);
}
void Framework::OnGpsUpdate(location::GpsInfo const & info)
@ -83,7 +83,7 @@ void Framework::OnGpsUpdate(location::GpsInfo const & info)
location::GpsInfo const & rInfo = info;
#endif
m_locationState.OnGpsUpdate(rInfo);
m_informationDisplay.locationState()->OnGpsUpdate(rInfo);
}
void Framework::OnCompassUpdate(location::CompassInfo const & info)
@ -95,7 +95,7 @@ void Framework::OnCompassUpdate(location::CompassInfo const & info)
location::CompassInfo const & rInfo = info;
#endif
m_locationState.OnCompassUpdate(rInfo);
m_informationDisplay.locationState()->OnCompassUpdate(rInfo);
}
InformationDisplay & Framework::GetInformationDisplay()
@ -130,8 +130,7 @@ Framework::Framework()
#endif
m_width(0),
m_height(0),
m_locationState(this),
m_informationDisplay(&m_storage),
m_informationDisplay(this),
m_lowestMapVersion(-1),
m_benchmarkEngine(0)
{
@ -585,8 +584,6 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
m_informationDisplay.doDraw(pDrawer);
m_locationState.Draw(*pDrawer);
if (m_drawPlacemark)
m_informationDisplay.drawPlacemark(pDrawer, "placemark", m_navigator.GtoP(m_placemark));
@ -785,7 +782,7 @@ void Framework::StartDrag(DragEvent const & e)
if (m_renderPolicy)
m_renderPolicy->StartDrag();
m_dragCompassProcessMode = m_locationState.CompassProcessMode();
m_dragCompassProcessMode = m_informationDisplay.locationState()->CompassProcessMode();
}
void Framework::DoDrag(DragEvent const & e)
@ -798,7 +795,7 @@ void Framework::DoDrag(DragEvent const & e)
m_navigator.DoDrag(pt, ElapsedSeconds());
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
m_informationDisplay.locationState()->SetCompassProcessMode(location::ECompassDoNothing);
if (m_renderPolicy)
m_renderPolicy->DoDrag();
@ -814,17 +811,19 @@ void Framework::StopDrag(DragEvent const & e)
m_informationDisplay.setDebugPoint(0, pt);
#endif
if (m_locationState.LocationProcessMode() != location::ELocationDoNothing)
shared_ptr<location::State> locationState = m_informationDisplay.locationState();
if (locationState->LocationProcessMode() != location::ELocationDoNothing)
{
// reset GPS centering mode if we have dragged far from current location
ScreenBase const & s = m_navigator.Screen();
if (GetPixelCenter().Length(s.GtoP(m_locationState.Position())) >= s.GetMinPixelRectSize() / 2.0)
if (GetPixelCenter().Length(s.GtoP(locationState->Position())) >= s.GetMinPixelRectSize() / 2.0)
{
m_locationState.SetLocationProcessMode(location::ELocationDoNothing);
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
locationState->SetLocationProcessMode(location::ELocationDoNothing);
locationState->SetCompassProcessMode(location::ECompassDoNothing);
}
else
m_locationState.SetCompassProcessMode(m_dragCompassProcessMode);
locationState->SetCompassProcessMode(m_dragCompassProcessMode);
}
if (m_renderPolicy)
@ -870,7 +869,7 @@ void Framework::Move(double azDir, double factor)
//@{
void Framework::ScaleToPoint(ScaleToPointEvent const & e)
{
m2::PointD const pt = (m_locationState.LocationProcessMode() == location::ELocationDoNothing) ?
m2::PointD const pt = (m_informationDisplay.locationState()->LocationProcessMode() == location::ELocationDoNothing) ?
m_navigator.ShiftPoint(e.Pt()) : GetPixelCenter();
m_navigator.ScaleToPoint(pt, e.ScaleFactor(), ElapsedSeconds());
@ -895,7 +894,10 @@ void Framework::CalcScalePoints(ScaleEvent const & e, m2::PointD & pt1, m2::Poin
pt1 = m_navigator.ShiftPoint(e.Pt1());
pt2 = m_navigator.ShiftPoint(e.Pt2());
if (m_locationState.HasPosition() && (m_locationState.LocationProcessMode() == location::ELocationCenterOnly))
shared_ptr<location::State> locationState = m_informationDisplay.locationState();
if (locationState->HasPosition()
&& (locationState->LocationProcessMode() == location::ELocationCenterOnly))
{
m2::PointD const ptC = (pt1 + pt2) / 2;
m2::PointD const ptDiff = GetPixelCenter() - ptC;
@ -928,10 +930,13 @@ void Framework::DoScale(ScaleEvent const & e)
if (m_renderPolicy)
m_renderPolicy->DoScale();
if (m_navigator.IsRotatingDuringScale() && (m_locationState.CompassProcessMode() == location::ECompassFollow))
shared_ptr<location::State> locationState = m_informationDisplay.locationState();
if (m_navigator.IsRotatingDuringScale()
&& (locationState->CompassProcessMode() == location::ECompassFollow))
{
m_locationState.StopAnimation();
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
locationState->StopAnimation();
locationState->SetCompassProcessMode(location::ECompassDoNothing);
}
}
@ -991,9 +996,11 @@ bool Framework::Search(search::SearchParams const & params)
bool Framework::GetCurrentPosition(double & lat, double & lon) const
{
if (m_locationState.HasPosition())
shared_ptr<location::State> locationState = m_informationDisplay.locationState();
if (locationState->HasPosition())
{
m2::PointD const pos = m_locationState.Position();
m2::PointD const pos = locationState->Position();
lat = MercatorBounds::YToLat(pos.y);
lon = MercatorBounds::XToLon(pos.x);
return true;
@ -1060,8 +1067,8 @@ void Framework::SetRenderPolicy(RenderPolicy * renderPolicy)
yg::gl::RenderContext::initParams();
}
m_renderPolicy.reset();
m_guiController->ResetRenderParams();
m_renderPolicy.reset();
m_renderPolicy.reset(renderPolicy);
if (m_renderPolicy)

View file

@ -96,7 +96,6 @@ protected:
int m_width;
int m_height;
location::State m_locationState;
location::ECompassProcessMode m_dragCompassProcessMode;
//mutable threads::Mutex m_modelSyn;

View file

@ -1,6 +1,7 @@
#include "information_display.hpp"
#include "drawer_yg.hpp"
#include "country_status_display.hpp"
#include "framework.hpp"
#include "../indexer/mercator.hpp"
@ -23,7 +24,7 @@
#include "../std/iomanip.hpp"
#include "../std/target_os.hpp"
InformationDisplay::InformationDisplay(storage::Storage * storage)
InformationDisplay::InformationDisplay(Framework * framework)
: m_ruler(Ruler::Params()),
m_bottomShift(0)
{
@ -32,10 +33,23 @@ InformationDisplay::InformationDisplay(storage::Storage * storage)
p.m_pivot = m2::PointD(0, 0);
p.m_position = yg::EPosCenter;
p.m_depth = yg::maxDepth;
p.m_storage = storage;
p.m_storage = &framework->Storage();
m_countryStatusDisplay.reset(new CountryStatusDisplay(p));
location::State::Params lsp;
lsp.m_position = yg::EPosCenter;
lsp.m_depth = yg::maxDepth;
lsp.m_pivot = m2::PointD(0, 0);
lsp.m_compassAreaColor = yg::Color(255, 255, 255, 192);
lsp.m_compassBorderColor = yg::Color(255, 255, 255, 96);
lsp.m_locationAreaColor = yg::Color(0, 0, 255, 32);
lsp.m_locationBorderColor = yg::Color(0, 0, 255, 32);
lsp.m_framework = framework;
m_locationState.reset(new location::State(lsp));
enableDebugPoints(false);
enableRuler(false);
enableCenter(false);
@ -54,6 +68,7 @@ void InformationDisplay::setController(gui::Controller *controller)
{
m_controller = controller;
m_controller->AddElement(m_countryStatusDisplay);
m_controller->AddElement(m_locationState);
}
void InformationDisplay::setScreen(ScreenBase const & screen)
@ -459,3 +474,8 @@ shared_ptr<CountryStatusDisplay> const & InformationDisplay::countryStatusDispla
{
return m_countryStatusDisplay;
}
shared_ptr<location::State> const & InformationDisplay::locationState() const
{
return m_locationState;
}

View file

@ -22,11 +22,7 @@ namespace gui
class Controller;
}
namespace storage
{
class Storage;
}
class Framework;
class CountryStatusDisplay;
/// Class, which displays additional information on the primary layer.
@ -84,10 +80,11 @@ private:
static WindowHandle * s_windowHandle;
*/
shared_ptr<CountryStatusDisplay> m_countryStatusDisplay;
shared_ptr<location::State> m_locationState;
public:
InformationDisplay(storage::Storage * storage);
InformationDisplay(Framework * framework);
void setController(gui::Controller * controller);
@ -129,6 +126,8 @@ public:
void setLogSize(size_t logSize);
void drawLog(DrawerYG * pDrawer);
shared_ptr<location::State> const & locationState() const;
void enableCountryStatusDisplay(bool doEnable);
void setDownloadListener(gui::Button::TOnClickListener l);
void setEmptyCountryName(string const & country);

View file

@ -1,27 +1,37 @@
#include "location_state.hpp"
#include "drawer_yg.hpp"
#include "navigator.hpp"
#include "framework.hpp"
#include "rotate_screen_task.hpp"
#include "../yg/display_list.hpp"
#include "../anim/controller.hpp"
#include "../gui/controller.hpp"
#include "../platform/location.hpp"
#include "../platform/platform.hpp"
#include "../geometry/rect2d.hpp"
#include "../geometry/transformations.hpp"
#include "../indexer/mercator.hpp"
namespace location
{
State::State(Framework * fw)
: m_hasPosition(false),
State::State(Params const & p)
: base_t(p),
m_hasPosition(false),
m_hasCompass(false),
m_locationProcessMode(ELocationDoNothing),
m_compassProcessMode(ECompassDoNothing),
m_fw(fw)
m_compassProcessMode(ECompassDoNothing)
{
m_locationAreaColor = p.m_locationAreaColor;
m_locationBorderColor = p.m_locationBorderColor;
m_compassAreaColor = p.m_compassAreaColor;
m_compassBorderColor = p.m_compassBorderColor;
m_framework = p.m_framework;
m_boundRects.resize(1);
}
bool State::HasPosition() const
@ -38,6 +48,7 @@ namespace location
{
m_hasPosition = false;
m_hasCompass = false;
setIsVisible(false);
}
void State::SkipLocationCentering()
@ -90,7 +101,7 @@ namespace location
TurnOff();
}
m_fw->Invalidate();
m_framework->Invalidate();
}
void State::OnGpsUpdate(location::GpsInfo const & info)
@ -102,6 +113,7 @@ namespace location
m2::PointD const center = rect.Center();
m_hasPosition = true;
setIsVisible(true);
m_position = center;
m_errorRadius = rect.SizeX() / 2;
@ -114,7 +126,7 @@ namespace location
// correct rect scale if country isn't downloaded
int const upperScale = scales::GetUpperWorldScale();
if (rectScale > upperScale && !m_fw->IsCountryLoaded(center))
if (rectScale > upperScale && !m_framework->IsCountryLoaded(center))
setScale = upperScale;
else
{
@ -127,18 +139,18 @@ namespace location
if (setScale != -1)
rect = scales::GetRectForLevel(setScale, center, 1.0);
double a = m_fw->GetNavigator().Screen().GetAngle();
double a = m_framework->GetNavigator().Screen().GetAngle();
double dx = rect.SizeX();
double dy = rect.SizeY();
m_fw->ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));
m_framework->ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));
m_locationProcessMode = ELocationCenterOnly;
break;
}
case ELocationCenterOnly:
m_fw->SetViewportCenter(center);
m_framework->SetViewportCenter(center);
break;
case ELocationSkipCentering:
@ -149,7 +161,7 @@ namespace location
break;
}
m_fw->Invalidate();
m_framework->Invalidate();
}
void State::OnCompassUpdate(location::CompassInfo const & info)
@ -160,66 +172,217 @@ namespace location
// Avoid situations when offset between magnetic north and true north is too small
static double const MIN_SECTOR_RAD = math::pi / 18.0;
double oldHeadingHaldErrorRad = m_headingHalfErrorRad;
m_headingHalfErrorRad = (info.m_accuracy < MIN_SECTOR_RAD ? MIN_SECTOR_RAD : info.m_accuracy);
if (fabs(oldHeadingHaldErrorRad - m_headingHalfErrorRad) > 0.01)
setIsDirtyDrawing(true);
if (m_compassProcessMode == ECompassFollow)
FollowCompass();
m_fw->Invalidate();
m_framework->Invalidate();
}
void State::Draw(DrawerYG & drawer)
vector<m2::AnyRectD> const & State::boundRects() const
{
if (m_hasPosition)
if (isDirtyRect())
{
m2::PointD const pxPosition = m_fw->GetNavigator().GtoP(Position());
double const pxErrorRadius = pxPosition.Length(m_fw->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));
m_boundRects[0] = m2::AnyRectD(m_boundRect);
setIsDirtyRect(false);
}
// my position symbol
drawer.drawSymbol(pxPosition, "current-position", yg::EPosCenter, yg::maxDepth);
return m_boundRects;
}
// my position circle
drawer.screen()->fillSector(pxPosition, 0, 2.0 * math::pi, pxErrorRadius,
yg::Color(0, 0, 255, 32),
yg::maxDepth - 3);
/*
void State::cache()
{
m_cacheRadius = 500 * visualScale();
// display compass only if position is available
double orientationRadius = max(pxErrorRadius, 30.0 * drawer.VisualScale());
yg::gl::Screen * cacheScreen = m_controller->GetCacheScreen();
double screenAngle = m_fw->GetNavigator().Screen().GetAngle();
m_locationDisplayList.reset();
m_locationDisplayList.reset(cacheScreen->createDisplayList());
// 0 angle is for North ("up"), but in our coordinates it's to the right.
double headingRad = m_headingRad - math::pi / 2.0;
m_compassDisplayList.reset();
m_compassDisplayList.reset(cacheScreen->createDisplayList());
if (m_hasCompass)
cacheScreen->beginFrame();
cacheScreen->setDisplayList(m_locationDisplayList.get());
m2::PointD zero(0, 0);
cacheScreen->drawSymbol(zero,
"current_position",
yg::EPosCenter,
depth());
cacheScreen->fillSector(zero,
0, 2.0 * math::pi,
m_cacheRadius,
m_locationAreaColor,
depth() - 3);
cacheScreen->drawArc(zero,
0, 2.0 * math::pi,
m_cacheRadius,
m_locationBorderColor,
depth() - 2);
cacheScreen->setDisplayList(m_compassDisplayList.get());
cacheScreen->drawSector(zero,
-m_headingHalfErrorRad,
m_headingHalfErrorRad,
m_cacheRadius,
m_compassAreaColor,
depth());
cacheScreen->fillSector(zero,
-m_headingHalfErrorRad,
m_headingHalfErrorRad,
m_cacheRadius,
m_compassBorderColor,
depth() - 1);
cacheScreen->setDisplayList(0);
cacheScreen->endFrame();
}
void State::purge()
{
m_locationDisplayList.reset();
m_compassDisplayList.reset();
}
void State::update()
{
m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());
setPivot(pxPosition);
double const pxErrorRadius = pxPosition.Length(m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));
m2::RectD newRect(pxPosition - m2::PointD(pxErrorRadius, pxErrorRadius),
pxPosition + m2::PointD(pxErrorRadius, pxErrorRadius));
if (newRect != m_boundRect)
{
m_boundRect = newRect;
setIsDirtyRect(true);
}
}
void State::draw(yg::gl::OverlayRenderer * r,
math::Matrix<double, 3, 3> const & m) const
{
if (isVisible())
{
checkDirtyDrawing();
if (m_hasPosition)
{
drawer.screen()->drawSector(pxPosition,
screenAngle + headingRad - m_headingHalfErrorRad,
screenAngle + headingRad + m_headingHalfErrorRad,
orientationRadius,
yg::Color(255, 255, 255, 192),
yg::maxDepth);
m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());
double const pxErrorRadius = pxPosition.Length(m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));
double const orientationRadius = max(pxErrorRadius, 30.0 * visualScale());
drawer.screen()->fillSector(pxPosition,
screenAngle + headingRad - m_headingHalfErrorRad,
screenAngle + headingRad + m_headingHalfErrorRad,
orientationRadius,
yg::Color(255, 255, 255, 96),
yg::maxDepth - 1);
double screenAngle = m_framework->GetNavigator().Screen().GetAngle();
double k = pxErrorRadius / m_cacheRadius;
math::Matrix<double, 3, 3> locationDrawM =
math::Shift(
math::Scale(math::Identity<double, 3>(), k, k),
pivot()
);
m_locationDisplayList->draw(locationDrawM * m);
// 0 angle is for North ("up"), but in our coordinates it's to the right.
double headingRad = m_headingRad - math::pi / 2.0;
if (m_hasCompass)
{
k = orientationRadius / m_cacheRadius;
math::Matrix<double, 3, 3> compassDrawM =
math::Shift(
math::Rotate(
math::Scale(math::Identity<double, 3>(), k, k),
screenAngle + headingRad),
pivot());
m_compassDisplayList->draw(compassDrawM * m);
}
}
}
}
*/
void State::draw(yg::gl::OverlayRenderer * r,
math::Matrix<double, 3, 3> const & m) const
{
if (isVisible())
{
checkDirtyDrawing();
if (m_hasPosition)
{
m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());
double const pxErrorRadius = pxPosition.Length(m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));
double const orientationRadius = max(pxErrorRadius, 30.0 * visualScale());
double screenAngle = m_framework->GetNavigator().Screen().GetAngle();
r->drawSymbol(pxPosition,
"current-position",
yg::EPosCenter,
depth());
r->fillSector(pxPosition,
0, 2.0 * math::pi,
pxErrorRadius,
m_locationAreaColor,
depth() - 3);
// 0 angle is for North ("up"), but in our coordinates it's to the right.
double headingRad = m_headingRad - math::pi / 2.0;
if (m_hasCompass)
{
r->drawSector(pxPosition,
screenAngle + headingRad - m_headingHalfErrorRad,
screenAngle + headingRad + m_headingHalfErrorRad,
orientationRadius,
m_compassAreaColor,
depth());
r->fillSector(pxPosition,
screenAngle + headingRad - m_headingHalfErrorRad,
screenAngle + headingRad + m_headingHalfErrorRad,
orientationRadius,
m_compassBorderColor,
depth() - 1);
}
}
}
}
void State::FollowCompass()
{
if (!m_fw->GetNavigator().DoSupportRotation())
if (!m_framework->GetNavigator().DoSupportRotation())
return;
m_fw->GetRenderPolicy()->GetAnimController()->Lock();
m_framework->GetRenderPolicy()->GetAnimController()->Lock();
StopAnimation();
double startAngle = m_fw->GetNavigator().Screen().GetAngle();
double startAngle = m_framework->GetNavigator().Screen().GetAngle();
double endAngle = -m_headingRad;
double period = 2 * math::pi;
@ -232,21 +395,23 @@ namespace location
if (fabs(startAngle - endAngle) > math::pi)
startAngle -= 2 * math::pi;
m_rotateScreenTask.reset(new RotateScreenTask(m_fw,
m_rotateScreenTask.reset(new RotateScreenTask(m_framework,
startAngle,
endAngle,
1));
m_fw->GetRenderPolicy()->GetAnimController()->AddTask(m_rotateScreenTask);
m_framework->GetRenderPolicy()->GetAnimController()->AddTask(m_rotateScreenTask);
}
m_fw->GetRenderPolicy()->GetAnimController()->Unlock();
m_framework->GetRenderPolicy()->GetAnimController()->Unlock();
}
void State::StopAnimation()
{
if (m_rotateScreenTask && !m_rotateScreenTask->IsFinished())
m_rotateScreenTask->Finish();
if (m_rotateScreenTask
&& !m_rotateScreenTask->IsEnded()
&& !m_rotateScreenTask->IsCancelled())
m_rotateScreenTask->Cancel();
m_rotateScreenTask.reset();
}
}

View file

@ -6,10 +6,19 @@
#include "../std/shared_ptr.hpp"
class DrawerYG;
#include "../gui/element.hpp"
class Framework;
class RotateScreenTask;
namespace yg
{
namespace gl
{
class DisplayList;
}
}
namespace location
{
class GpsInfo;
@ -32,9 +41,10 @@ namespace location
// Class, that handles position and compass updates,
// centers, scales and rotates map according to this updates
// and draws location and compass marks.
class State
class State : public gui::Element
{
private:
double m_errorRadius; //< error radius in mercator
m2::PointD m_position; //< position in mercator
@ -49,13 +59,48 @@ namespace location
shared_ptr<RotateScreenTask> m_rotateScreenTask;
Framework * m_fw;
void FollowCompass();
/// GUI element related fields.
typedef gui::Element base_t;
yg::Color m_locationAreaColor;
yg::Color m_locationBorderColor;
math::Matrix<double, 3, 3> m_locationDrawM;
yg::Color m_compassAreaColor;
yg::Color m_compassBorderColor;
math::Matrix<double, 3, 3> m_compassDrawM;
Framework * m_framework;
double m_cacheRadius;
shared_ptr<yg::gl::DisplayList> m_locationDisplayList;
shared_ptr<yg::gl::DisplayList> m_compassDisplayList;
/* void cache();
void purge();
void update();*/
mutable vector<m2::AnyRectD> m_boundRects;
m2::RectD m_boundRect;
public:
State(Framework * framework);
struct Params : base_t::Params
{
yg::Color m_locationAreaColor;
yg::Color m_locationBorderColor;
yg::Color m_compassAreaColor;
yg::Color m_compassBorderColor;
Framework * m_framework;
};
State(Params const & p);
/// @return GPS center point in mercator
m2::PointD const & Position() const { return m_position; }
@ -71,7 +116,6 @@ namespace location
void TurnOff();
void Draw(DrawerYG & drawer);
void StopAnimation();
/// @name GPS location updates routine.
@ -81,5 +125,8 @@ namespace location
void OnGpsUpdate(location::GpsInfo const & info);
void OnCompassUpdate(location::CompassInfo const & info);
//@}
vector<m2::AnyRectD> const & boundRects() const;
void draw(yg::gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
};
}