TizenRefApp-8321 [Gallery] Implement TouchParser 56/123456/1
authorIgor Nazarov <i.nazarov@samsung.com>
Wed, 5 Apr 2017 14:41:32 +0000 (17:41 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Wed, 5 Apr 2017 14:41:32 +0000 (17:41 +0300)
- Added TouchParser class with initial parsing of
  tap and double tap gestures.

Change-Id: Ia7ae94a3db52ff4367dc033eb007814c2d99d143

inc/presentation/TouchParser.h [new file with mode: 0644]
inc/presentation/types.h
src/presentation/TouchParser.cpp [new file with mode: 0644]

diff --git a/inc/presentation/TouchParser.h b/inc/presentation/TouchParser.h
new file mode 100644 (file)
index 0000000..2c65fb3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GALLERY_PRESENTATION_TOUCH_PARSER_H__
+#define __GALLERY_PRESENTATION_TOUCH_PARSER_H__
+
+#include "ucl/gui/Widget.h"
+
+#include "types.h"
+
+namespace gallery {
+
+       class TouchParser final : public ucl::RefCountAware {
+       public:
+               using TapHandler = ucl::Delegate<void(int x, int y)>;
+
+       private:
+               friend class ucl::RefCountObj<TouchParser>;
+               TouchParser(ucl::RefCountObjBase &rc, ucl::Widget &eventSource);
+               virtual ~TouchParser();
+
+       public:
+               void setTapHandler(TapHandler handler);
+               void setDoubleTapHandler(TapHandler handler);
+
+       private:
+               void onMouseDown(ucl::Widget &widget, void *eventInfo);
+               void onMouseUp(ucl::Widget &widget, void *eventInfo);
+               void onMouseMove(ucl::Widget &widget, void *eventInfo);
+
+               void updateIsTapPossible(int flags, int curX, int curY);
+
+               bool isFastTap(ucl::UInt curTime, int curX, int curY) const;
+               double calcDownDistance(int curX, int curY) const;
+
+       private:
+               TapHandler m_tapHandler;
+               TapHandler m_doubleTapHandler;
+               ucl::UInt m_downTime;
+               int m_downX;
+               int m_downY;
+               int m_tapCounter;
+               bool m_isMouseDown;
+               bool m_isTapPossible;
+       };
+}
+
+#endif // __GALLERY_PRESENTATION_TOUCH_PARSER_H__
index d34fbb4ab171d7c7e8f62683788e6c5f0b3adff2..4e277c8b08a2e559c1954de926a490532ae531ad 100644 (file)
@@ -25,6 +25,8 @@ namespace gallery {
 
        class IImageGridListener;
 
+       UCL_DECLARE_REF_ALIASES(TouchParser);
+
        UCL_DECLARE_REF_ALIASES(ImageGrid);
        UCL_DECLARE_REF_ALIASES(ImageViewer);
 
diff --git a/src/presentation/TouchParser.cpp b/src/presentation/TouchParser.cpp
new file mode 100644 (file)
index 0000000..a556fd5
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "presentation/TouchParser.h"
+
+#include "common.h"
+
+namespace gallery { namespace { namespace impl {
+
+       constexpr auto TAP_MOVE_THRESHOLD = 30;
+       constexpr auto FAST_TAP_DISTANCE = 60;
+       constexpr auto FAST_TAP_DELAY_MS = 300;
+}}}
+
+namespace gallery {
+
+       using namespace ucl;
+
+       TouchParser::TouchParser(RefCountObjBase &rc, Widget &eventSource) :
+               RefCountAware(&rc),
+               m_downTime(0),
+               m_downX(0),
+               m_downY(0),
+               m_tapCounter(0),
+               m_isMouseDown(false),
+               m_isTapPossible(false)
+       {
+               eventSource.addEventHandler(WidgetEvent::MOUSE_DOWN,
+                               WEAK_DELEGATE(TouchParser::onMouseDown, asWeak(*this)));
+
+               eventSource.addEventHandler(WidgetEvent::MOUSE_UP,
+                               WEAK_DELEGATE(TouchParser::onMouseUp, asWeak(*this)));
+
+               eventSource.addEventHandler(WidgetEvent::MOUSE_MOVE,
+                               WEAK_DELEGATE(TouchParser::onMouseMove, asWeak(*this)));
+       }
+
+       TouchParser::~TouchParser()
+       {
+       }
+
+       void TouchParser::setTapHandler(TapHandler handler)
+       {
+               m_tapHandler = handler;
+       }
+
+       void TouchParser::setDoubleTapHandler(TapHandler handler)
+       {
+               m_doubleTapHandler = handler;
+       }
+
+       void TouchParser::onMouseDown(Widget &widget, void *eventInfo)
+       {
+               if (m_isMouseDown) {
+                       return;
+               }
+               m_isMouseDown = true;
+
+               const auto e = static_cast<Evas_Event_Mouse_Down *>(eventInfo);
+
+               if (!isFastTap(e->timestamp, e->canvas.x, e->canvas.y)) {
+                       m_tapCounter = 0;
+               } else if (m_doubleTapHandler && (m_tapCounter == 1)) {
+                       m_doubleTapHandler(m_downX, m_downY);
+               }
+
+               m_downTime = e->timestamp;
+               m_downX = e->canvas.x;
+               m_downY = e->canvas.y;
+               m_isTapPossible = true;
+       }
+
+       void TouchParser::onMouseUp(Widget &widget, void *eventInfo)
+       {
+               if (!m_isMouseDown) {
+                       return;
+               }
+               m_isMouseDown = false;
+
+               const auto e = static_cast<Evas_Event_Mouse_Up *>(eventInfo);
+
+               updateIsTapPossible(e->event_flags, e->canvas.x, e->canvas.y);
+
+               if (!m_isTapPossible) {
+                       m_tapCounter = 0;
+                       return;
+               }
+
+               ++m_tapCounter;
+
+               if (m_tapHandler) {
+                       m_tapHandler(e->canvas.x, e->canvas.y);
+               }
+       }
+
+       void TouchParser::onMouseMove(Widget &widget, void *eventInfo)
+       {
+               if (!m_isMouseDown || !m_isTapPossible) {
+                       return;
+               }
+
+               const auto e = static_cast<Evas_Event_Mouse_Move *>(eventInfo);
+
+               updateIsTapPossible(e->event_flags, e->cur.canvas.x, e->cur.canvas.y);
+       }
+
+       void TouchParser::updateIsTapPossible(const int flags,
+                       const int curX, const int curY)
+       {
+               if (!m_isTapPossible) {
+                       return;
+               }
+               if ((flags & EVAS_EVENT_FLAG_ON_HOLD) || (calcDownDistance(curX, curY) >
+                               ELM_SCALE_SIZE(impl::TAP_MOVE_THRESHOLD))) {
+                       m_isTapPossible = false;
+               }
+       }
+
+       bool TouchParser::isFastTap(const UInt curTime,
+                       const int curX, const int curY) const
+       {
+               return (((curTime - m_downTime) <= impl::FAST_TAP_DELAY_MS) &&
+                               (calcDownDistance(curX, curY) <=
+                                               ELM_SCALE_SIZE(impl::FAST_TAP_DISTANCE)));
+       }
+
+       double TouchParser::calcDownDistance(int curX, int curY) const
+       {
+               const auto dx = (curX - m_downX);
+               const auto dy = (curY - m_downY);
+
+               return sqrt(1.0 * dx * dx + 1.0 * dy * dy);
+       }
+}