forked from organicmaps/organicmaps
Merge pull request #2709 from rokuz/drape-double-tap-and-hold
Added "double tap and hold" zooming
This commit is contained in:
commit
8a0c4803d2
3 changed files with 81 additions and 10 deletions
|
@ -74,7 +74,7 @@ public:
|
|||
void Invalidate();
|
||||
|
||||
void AddTouchEvent(TouchEvent const & event);
|
||||
void Scale(double factor, m2::PointD const & pxPoint, bool isAnim);
|
||||
void Scale(double factor, m2::PointD const & pxPoint, bool isAnim);
|
||||
|
||||
/// if zoom == -1, then current zoom will not change
|
||||
void SetModelViewCenter(m2::PointD const & centerPt, int zoom, bool isAnim);
|
||||
|
|
|
@ -56,6 +56,9 @@ char const * UserEventStream::TRY_FILTER = "TryFilter";
|
|||
char const * UserEventStream::END_FILTER = "EndFilter";
|
||||
char const * UserEventStream::CANCEL_FILTER = "CancelFilter";
|
||||
char const * UserEventStream::TWO_FINGERS_TAP = "TwoFingersTap";
|
||||
char const * UserEventStream::BEGIN_DOUBLE_TAP_AND_HOLD = "BeginDoubleTapAndHold";
|
||||
char const * UserEventStream::DOUBLE_TAP_AND_HOLD = "DoubleTapAndHold";
|
||||
char const * UserEventStream::END_DOUBLE_TAP_AND_HOLD = "EndDoubleTapAndHold";
|
||||
#endif
|
||||
|
||||
uint8_t const TouchEvent::INVALID_MASKED_POINTER = 0xFF;
|
||||
|
@ -114,6 +117,7 @@ void TouchEvent::Swap()
|
|||
UserEventStream::UserEventStream()
|
||||
: m_state(STATE_EMPTY)
|
||||
, m_startDragOrg(m2::PointD::Zero())
|
||||
, m_startDoubleTapAndHold(m2::PointD::Zero())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -639,9 +643,14 @@ bool UserEventStream::TouchDown(array<Touch, 2> const & touches)
|
|||
break;
|
||||
case STATE_TAP_DETECTION:
|
||||
case STATE_WAIT_DOUBLE_TAP:
|
||||
case STATE_WAIT_DOUBLE_TAP_HOLD:
|
||||
CancelTapDetector();
|
||||
BeginTwoFingersTap(touches[0], touches[1]);
|
||||
break;
|
||||
case STATE_DOUBLE_TAP_HOLD:
|
||||
EndDoubleTapAndHold(touches[0]);
|
||||
BeginScale(touches[0], touches[1]);
|
||||
break;
|
||||
case STATE_DRAG:
|
||||
isMapTouch = EndDrag(touches[0], true /* cancelled */);
|
||||
BeginScale(touches[0], touches[1]);
|
||||
|
@ -657,7 +666,7 @@ bool UserEventStream::TouchDown(array<Touch, 2> const & touches)
|
|||
|
||||
bool UserEventStream::TouchMove(array<Touch, 2> const & touches, double timestamp)
|
||||
{
|
||||
double const dragThreshold = my::sq(VisualParams::Instance().GetDragThreshold());
|
||||
double const kDragThreshold = my::sq(VisualParams::Instance().GetDragThreshold());
|
||||
size_t touchCount = GetValidTouchesCount(touches);
|
||||
bool isMapTouch = true;
|
||||
|
||||
|
@ -666,7 +675,7 @@ bool UserEventStream::TouchMove(array<Touch, 2> const & touches, double timestam
|
|||
case STATE_EMPTY:
|
||||
if (touchCount == 1)
|
||||
{
|
||||
if (m_startDragOrg.SquareLength(touches[0].m_location) > dragThreshold)
|
||||
if (m_startDragOrg.SquareLength(touches[0].m_location) > kDragThreshold)
|
||||
BeginDrag(touches[0], timestamp);
|
||||
else
|
||||
isMapTouch = false;
|
||||
|
@ -679,7 +688,7 @@ bool UserEventStream::TouchMove(array<Touch, 2> const & touches, double timestam
|
|||
case STATE_TAP_TWO_FINGERS:
|
||||
if (touchCount == 2)
|
||||
{
|
||||
float const threshold = static_cast<float>(dragThreshold);
|
||||
float const threshold = static_cast<float>(kDragThreshold);
|
||||
if (m_twoFingersTouches[0].SquareLength(touches[0].m_location) > threshold ||
|
||||
m_twoFingersTouches[1].SquareLength(touches[1].m_location) > threshold)
|
||||
BeginScale(touches[0], touches[1]);
|
||||
|
@ -693,11 +702,18 @@ bool UserEventStream::TouchMove(array<Touch, 2> const & touches, double timestam
|
|||
break;
|
||||
case STATE_TAP_DETECTION:
|
||||
case STATE_WAIT_DOUBLE_TAP:
|
||||
if (m_startDragOrg.SquareLength(touches[0].m_location) > dragThreshold)
|
||||
if (m_startDragOrg.SquareLength(touches[0].m_location) > kDragThreshold)
|
||||
CancelTapDetector();
|
||||
else
|
||||
isMapTouch = false;
|
||||
break;
|
||||
case STATE_WAIT_DOUBLE_TAP_HOLD:
|
||||
if (m_startDragOrg.SquareLength(touches[0].m_location) > kDragThreshold)
|
||||
StartDoubleTapAndHold(touches[0]);
|
||||
break;
|
||||
case STATE_DOUBLE_TAP_HOLD:
|
||||
UpdateDoubleTapAndHold(touches[0]);
|
||||
break;
|
||||
case STATE_DRAG:
|
||||
if (touchCount > 1)
|
||||
{
|
||||
|
@ -741,6 +757,11 @@ bool UserEventStream::TouchCancel(array<Touch, 2> const & touches)
|
|||
case STATE_TAP_TWO_FINGERS:
|
||||
isMapTouch = false;
|
||||
break;
|
||||
case STATE_WAIT_DOUBLE_TAP_HOLD:
|
||||
case STATE_DOUBLE_TAP_HOLD:
|
||||
ASSERT_EQUAL(touchCount, 1, ());
|
||||
EndDoubleTapAndHold(touches[0]);
|
||||
break;
|
||||
case STATE_FILTER:
|
||||
ASSERT_EQUAL(touchCount, 1, ());
|
||||
CancelFilter(touches[0]);
|
||||
|
@ -787,10 +808,15 @@ bool UserEventStream::TouchUp(array<Touch, 2> const & touches)
|
|||
break;
|
||||
case STATE_TAP_TWO_FINGERS:
|
||||
if (touchCount == 2)
|
||||
{
|
||||
EndTwoFingersTap();
|
||||
isMapTouch = true;
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_DOUBLE_TAP_HOLD:
|
||||
ASSERT_EQUAL(touchCount, 1, ());
|
||||
PerformDoubleTap(touches[0]);
|
||||
break;
|
||||
case STATE_DOUBLE_TAP_HOLD:
|
||||
ASSERT_EQUAL(touchCount, 1, ());
|
||||
EndDoubleTapAndHold(touches[0]);
|
||||
break;
|
||||
case STATE_DRAG:
|
||||
ASSERT_EQUAL(touchCount, 1, ());
|
||||
|
@ -993,11 +1019,17 @@ bool UserEventStream::DetectDoubleTap(Touch const & touch)
|
|||
if (m_state != STATE_WAIT_DOUBLE_TAP || ms > kDoubleTapPauseMs)
|
||||
return false;
|
||||
|
||||
m_state = STATE_WAIT_DOUBLE_TAP_HOLD;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UserEventStream::PerformDoubleTap(Touch const & touch)
|
||||
{
|
||||
ASSERT_EQUAL(m_state, STATE_WAIT_DOUBLE_TAP_HOLD, ());
|
||||
m_state = STATE_EMPTY;
|
||||
if (m_listener)
|
||||
m_listener->OnDoubleTap(touch.m_location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserEventStream::DetectForceTap(Touch const & touch)
|
||||
|
@ -1057,6 +1089,34 @@ void UserEventStream::CancelFilter(Touch const & t)
|
|||
if (m_listener)
|
||||
m_listener->OnSingleTouchFiltrate(t.m_location, TouchEvent::TOUCH_CANCEL);
|
||||
}
|
||||
|
||||
void UserEventStream::StartDoubleTapAndHold(Touch const & touch)
|
||||
{
|
||||
TEST_CALL(BEGIN_DOUBLE_TAP_AND_HOLD);
|
||||
ASSERT_EQUAL(m_state, STATE_WAIT_DOUBLE_TAP_HOLD, ());
|
||||
m_state = STATE_DOUBLE_TAP_HOLD;
|
||||
m_startDoubleTapAndHold = m_startDragOrg;
|
||||
}
|
||||
|
||||
void UserEventStream::UpdateDoubleTapAndHold(Touch const & touch)
|
||||
{
|
||||
TEST_CALL(DOUBLE_TAP_AND_HOLD);
|
||||
ASSERT_EQUAL(m_state, STATE_DOUBLE_TAP_HOLD, ());
|
||||
float const kPowerModifier = 10.0f;
|
||||
float const scaleFactor = exp(kPowerModifier * (touch.m_location.y - m_startDoubleTapAndHold.y) / GetCurrentScreen().PixelRect().SizeY());
|
||||
m_startDoubleTapAndHold = touch.m_location;
|
||||
m2::PointD scaleCenter = m_startDragOrg;
|
||||
if (m_listener)
|
||||
m_listener->CorrectScalePoint(scaleCenter);
|
||||
m_navigator.Scale(scaleCenter, scaleFactor);
|
||||
}
|
||||
|
||||
void UserEventStream::EndDoubleTapAndHold(Touch const & touch)
|
||||
{
|
||||
TEST_CALL(END_DOUBLE_TAP_AND_HOLD);
|
||||
ASSERT_EQUAL(m_state, STATE_DOUBLE_TAP_HOLD, ());
|
||||
m_state = STATE_EMPTY;
|
||||
}
|
||||
|
||||
bool UserEventStream::IsInUserAction() const
|
||||
{
|
||||
|
|
|
@ -291,6 +291,9 @@ public:
|
|||
static char const * END_FILTER;
|
||||
static char const * CANCEL_FILTER;
|
||||
static char const * TWO_FINGERS_TAP;
|
||||
static char const * BEGIN_DOUBLE_TAP_AND_HOLD;
|
||||
static char const * DOUBLE_TAP_AND_HOLD;
|
||||
static char const * END_DOUBLE_TAP_AND_HOLD;
|
||||
|
||||
using TTestBridge = function<void (char const * action)>;
|
||||
void SetTestBridge(TTestBridge const & fn) { m_testFn = fn; }
|
||||
|
@ -333,9 +336,14 @@ private:
|
|||
void DetectShortTap(Touch const & touch);
|
||||
void DetectLongTap(Touch const & touch);
|
||||
bool DetectDoubleTap(Touch const & touch);
|
||||
void PerformDoubleTap(Touch const & touch);
|
||||
bool DetectForceTap(Touch const & touch);
|
||||
void EndTapDetector(Touch const & touch);
|
||||
void CancelTapDetector();
|
||||
|
||||
void StartDoubleTapAndHold(Touch const & touch);
|
||||
void UpdateDoubleTapAndHold(Touch const & touch);
|
||||
void EndDoubleTapAndHold(Touch const & touch);
|
||||
|
||||
void BeginTwoFingersTap(Touch const & t1, Touch const & t2);
|
||||
void EndTwoFingersTap();
|
||||
|
@ -358,6 +366,8 @@ private:
|
|||
STATE_TAP_DETECTION,
|
||||
STATE_WAIT_DOUBLE_TAP,
|
||||
STATE_TAP_TWO_FINGERS,
|
||||
STATE_WAIT_DOUBLE_TAP_HOLD,
|
||||
STATE_DOUBLE_TAP_HOLD,
|
||||
STATE_DRAG,
|
||||
STATE_SCALE
|
||||
} m_state;
|
||||
|
@ -379,6 +389,7 @@ private:
|
|||
#endif
|
||||
m2::PointD m_startDragOrg;
|
||||
array<m2::PointF, 2> m_twoFingersTouches;
|
||||
m2::PointD m_startDoubleTapAndHold;
|
||||
|
||||
KineticScroller m_scroller;
|
||||
my::Timer m_kineticTimer;
|
||||
|
|
Loading…
Add table
Reference in a new issue