diff --git a/include/nuiGestureRecognizer.h b/include/nuiGestureRecognizer.h new file mode 100644 index 00000000..50e586da --- /dev/null +++ b/include/nuiGestureRecognizer.h @@ -0,0 +1,143 @@ +/* + NUI3 - C++ cross-platform GUI framework for OpenGL based applications + Copyright (C) 2002-2003 Sebastien Metrot & Vincent Caron + + licence: see nui3/LICENCE.TXT + */ + + +#pragma once +#include "nui.h" + + +class nuiGestureRecognizer; +class nuiSwipeGestureRecognizer; + + + +//********************************************************************** +// +// enum nuiGestureRecognizerState +// +// defines current state of a gesture recognizer +// +enum nuiGestureRecognizerState +{ + eGestureRecognizerStatePossible, // default state + eGestureRecognizerStateBegan, // touches recognized as the gesture. + eGestureRecognizerStateEnded, // the end of the gesture. + eGestureRecognizerStateFailed // a touch sequence that can not be recognized as the gesture. + + // maybe later... + // eGestureRecognizerStateCancelled, // cancellation of the gesture. + // eGestureRecognizerStateChanged, // the recognizer has received touches recognized as a change to the gesture. the action method will be called at the next turn of the run loop + // eGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible + +}; + + + + +//********************************************************************** +// +// class nuiGestureRecognizer +// +// mother class to handle a gesture recognizer +// +class nuiGestureRecognizer : public nuiSimpleContainer +{ +public: + nuiGestureRecognizer(); + virtual ~nuiGestureRecognizer(); + + nuiSignal1 SignalStateChanged; + nuiGestureRecognizerState GetState() const; + + +protected: + + void SetState(nuiGestureRecognizerState state); + + virtual bool MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); + virtual bool MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); + virtual bool MouseMoved(nuiSize X, nuiSize Y); + +private: + nuiGestureRecognizerState mState; + +}; + + + + + +typedef uint32 nuiGestureDirection; + +// +// directions the swipe gesture is applying on. can combine several directions +// +const uint32 nuiGestureDirectionNull = 1 << 0; + +const uint32 nuiGestureDirectionRight = 1 << 1; +const uint32 nuiGestureDirectionLeft = 1 << 2; +const uint32 nuiGestureDirectionUp = 1 << 3; +const uint32 nuiGestureDirectionDown = 1 << 4; + +const uint32 nuiGestureDirectionUpRight = 1 << 5; +const uint32 nuiGestureDirectionDownRight = 1 << 6; +const uint32 nuiGestureDirectionDownLeft = 1 << 7; +const uint32 nuiGestureDirectionUpLeft = 1 << 8; + +const uint32 nuiGestureDirectionHorizontal = nuiGestureDirectionRight | nuiGestureDirectionLeft; +const uint32 nuiGestureDirectionVertical = nuiGestureDirectionUp | nuiGestureDirectionDown; + +const uint32 nuiGestureDirectionDiagonals = nuiGestureDirectionUpRight | nuiGestureDirectionDownRight | nuiGestureDirectionDownLeft | nuiGestureDirectionUpLeft; + + + + + + + +//********************************************************************** +// +// class nuiSwipeGestureRecognizer +// +// implements a swipe gesture recognizer +// +class nuiSwipeGestureRecognizer: public nuiGestureRecognizer +{ +public: + + nuiSwipeGestureRecognizer(nuiGestureDirection direction); + ~nuiSwipeGestureRecognizer(); + + void SetDirections(nuiGestureDirection direction); + + nuiSignal1 SignalSwipe; + nuiGestureDirection GetRecognizedDirection() const; + + +protected: + + virtual bool MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); + virtual bool MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); + virtual bool MouseMoved(nuiSize X, nuiSize Y); + +private: + +// nuiPosition GetGesturePosition(bool evalOnX, bool evalOnY, nuiSize x1, nuiSize x2, nuiSize y1, nuiSize y2) const; + nuiGestureDirection GetGestureDirection(bool evalOnX, bool evalOnY, nuiSize x1, nuiSize x2, nuiSize y1, nuiSize y2) const; + +// static bool DoesPositionMatchesDirection(nuiPosition position, nuiSwipeGestureRecognizerDirection direction); + + bool mClicked; + double mTime; + double mInitiatedTime; + nuiSize mStartX; + nuiSize mStartY; + + nuiGestureDirection mDirection; + nuiGestureDirection mRecognizedDirection; +}; + diff --git a/include/nuiViewController.h b/include/nuiViewController.h index ea2d4629..7f4bbf5a 100644 --- a/include/nuiViewController.h +++ b/include/nuiViewController.h @@ -33,23 +33,11 @@ class nuiViewController : public nuiSimpleContainer virtual void ViewDidAppear(); virtual void ViewDidDisappear(); - virtual void SwipeBegan(nuiPosition swipeDirection); - virtual void SwipeEnd(nuiPosition swipeDirection); - nuiSimpleEventSource<0> EventSwipeBegan; - nuiSimpleEventSource<0> EventSwipeEnd; - nuiPosition GetSwipeDirection() const; - - virtual void ConnectTopLevel(); - virtual bool MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); - virtual bool MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); - virtual bool MouseMoved(nuiSize X, nuiSize Y); private: - nuiPosition GetGestureDirection(bool evalOnX, bool evalOnY, nuiSize x1, nuiSize x2, nuiSize y1, nuiSize y2) const; - bool mAnimated; nuiNavigationBar* mpBar; diff --git a/nui3.xcodeproj/project.pbxproj b/nui3.xcodeproj/project.pbxproj index f2384376..a29a91ea 100644 --- a/nui3.xcodeproj/project.pbxproj +++ b/nui3.xcodeproj/project.pbxproj @@ -1716,6 +1716,14 @@ BC0F70800DB3BC0100329939 /* nglThreadChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0F707C0DB3BC0100329939 /* nglThreadChecker.cpp */; }; BC0F70D50DB4A70F00329939 /* nglThreadChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0F70D40DB4A70F00329939 /* nglThreadChecker.h */; }; BC0F70D60DB4A70F00329939 /* nglThreadChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0F70D40DB4A70F00329939 /* nglThreadChecker.h */; }; + BC1684DD1381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1684DC1381605F00A605E6 /* nuiGestureRecognizer.cpp */; }; + BC1684DE1381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1684DC1381605F00A605E6 /* nuiGestureRecognizer.cpp */; }; + BC1684DF1381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1684DC1381605F00A605E6 /* nuiGestureRecognizer.cpp */; }; + BC1684E01381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1684DC1381605F00A605E6 /* nuiGestureRecognizer.cpp */; }; + BC1684E21381606C00A605E6 /* nuiGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1684E11381606C00A605E6 /* nuiGestureRecognizer.h */; }; + BC1684E31381606C00A605E6 /* nuiGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1684E11381606C00A605E6 /* nuiGestureRecognizer.h */; }; + BC1684E41381606C00A605E6 /* nuiGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1684E11381606C00A605E6 /* nuiGestureRecognizer.h */; }; + BC1684E51381606C00A605E6 /* nuiGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1684E11381606C00A605E6 /* nuiGestureRecognizer.h */; }; BC19B5CF12AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC19B5CE12AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp */; }; BC19B5D012AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC19B5CE12AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp */; }; BC19B5D112AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC19B5CE12AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp */; }; @@ -7315,6 +7323,8 @@ 944C54170E00018200B691C5 /* nuiHotKeyEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nuiHotKeyEditor.h; path = include/nuiHotKeyEditor.h; sourceTree = SOURCE_ROOT; }; BC0F707C0DB3BC0100329939 /* nglThreadChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = nglThreadChecker.cpp; path = src/Threading/nglThreadChecker.cpp; sourceTree = SOURCE_ROOT; }; BC0F70D40DB4A70F00329939 /* nglThreadChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nglThreadChecker.h; path = include/nglThreadChecker.h; sourceTree = SOURCE_ROOT; }; + BC1684DC1381605F00A605E6 /* nuiGestureRecognizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = nuiGestureRecognizer.cpp; path = NavigationViews/nuiGestureRecognizer.cpp; sourceTree = ""; }; + BC1684E11381606C00A605E6 /* nuiGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nuiGestureRecognizer.h; path = include/nuiGestureRecognizer.h; sourceTree = SOURCE_ROOT; }; BC19B5CE12AFC0F1002DA665 /* nuiNavigationViewDecoration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = nuiNavigationViewDecoration.cpp; path = src/Decorations/nuiNavigationViewDecoration.cpp; sourceTree = SOURCE_ROOT; }; BC19B5D312AFC0FE002DA665 /* nuiNavigationViewDecoration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nuiNavigationViewDecoration.h; path = include/nuiNavigationViewDecoration.h; sourceTree = SOURCE_ROOT; }; BC19E1960EA3AC030026CB6B /* nuiImageSequence.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = nuiImageSequence.cpp; path = src/Layout/nuiImageSequence.cpp; sourceTree = SOURCE_ROOT; }; @@ -9190,7 +9200,6 @@ BC3BA4670D251050005B175E /* nuiFrame.cpp */, BC3BA4730D25107B005B175E /* nuiFrame.h */, BC3BA4680D251050005B175E /* nuiGradientDecoration.cpp */, - BC3BA4740D25107B005B175E /* nuiGradientDecoration.h */, BC915AF80DE187E80044CD59 /* nuiImageDecoration.cpp */, BC915AFB0DE187F80044CD59 /* nuiImageDecoration.h */, E5D053F60D318DC000B1A021 /* nuiMetaDecoration.cpp */, @@ -9226,6 +9235,8 @@ BC87DF0312A9599B00D836BF /* nuiNavigationButton.h */, BCF87564137D27630092DAAD /* nuiImageAnimation.cpp */, BCF8755F137D27570092DAAD /* nuiImageAnimation.h */, + BC1684DC1381605F00A605E6 /* nuiGestureRecognizer.cpp */, + BC1684E11381606C00A605E6 /* nuiGestureRecognizer.h */, ); name = NavigationViews; sourceTree = ""; @@ -10616,6 +10627,7 @@ E5816D860C3CECAB00902DFE /* Image */, BCC51B9A0DC0D8FA00563B7E /* Introspector */, 40033E6A12B14D31000695D2 /* Json */, + BC3BA4740D25107B005B175E /* nuiGradientDecoration.h */, E5816D920C3CECAB00902DFE /* Layout */, E5816DA30C3CECAB00902DFE /* Math */, BC92AC991282F8F1006A27B0 /* NavigationViews */, @@ -13000,6 +13012,7 @@ 401705C812E06878008769D5 /* nuiSynthVoice.h in Headers */, E5345F3112F3317500F435D9 /* TextureAtlas.h in Headers */, BCF87562137D27570092DAAD /* nuiImageAnimation.h in Headers */, + BC1684E41381606C00A605E6 /* nuiGestureRecognizer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -13386,6 +13399,7 @@ 401705C612E06878008769D5 /* nuiSynthVoice.h in Headers */, E5345F3512F3317500F435D9 /* TextureAtlas.h in Headers */, BCF87563137D27570092DAAD /* nuiImageAnimation.h in Headers */, + BC1684E51381606C00A605E6 /* nuiGestureRecognizer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -13772,6 +13786,7 @@ E5345F3912F3317500F435D9 /* TextureAtlas.h in Headers */, BC2475041377D7EA000F1ABB /* nuiNavigationBarStyle.h in Headers */, BCF87561137D27570092DAAD /* nuiImageAnimation.h in Headers */, + BC1684E31381606C00A605E6 /* nuiGestureRecognizer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -14158,6 +14173,7 @@ E5345F3712F3317500F435D9 /* TextureAtlas.h in Headers */, BC2475031377D7EA000F1ABB /* nuiNavigationBarStyle.h in Headers */, BCF87560137D27570092DAAD /* nuiImageAnimation.h in Headers */, + BC1684E21381606C00A605E6 /* nuiGestureRecognizer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16996,6 +17012,7 @@ 401705C912E06878008769D5 /* nuiSynthVoice.cpp in Sources */, E5345F3212F3317500F435D9 /* TextureAtlas.cpp in Sources */, BCF87567137D27630092DAAD /* nuiImageAnimation.cpp in Sources */, + BC1684DF1381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17337,6 +17354,7 @@ 401705C712E06878008769D5 /* nuiSynthVoice.cpp in Sources */, E5345F3612F3317500F435D9 /* TextureAtlas.cpp in Sources */, BCF87568137D27630092DAAD /* nuiImageAnimation.cpp in Sources */, + BC1684E01381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17682,6 +17700,7 @@ 401705CB12E06878008769D5 /* nuiSynthVoice.cpp in Sources */, E5345F3A12F3317500F435D9 /* TextureAtlas.cpp in Sources */, BCF87566137D27630092DAAD /* nuiImageAnimation.cpp in Sources */, + BC1684DE1381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18026,6 +18045,7 @@ 401705CF12E06878008769D5 /* nuiSynthVoice.cpp in Sources */, E5345F3812F3317500F435D9 /* TextureAtlas.cpp in Sources */, BCF87565137D27630092DAAD /* nuiImageAnimation.cpp in Sources */, + BC1684DD1381605F00A605E6 /* nuiGestureRecognizer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/NavigationViews/nuiGestureRecognizer.cpp b/src/NavigationViews/nuiGestureRecognizer.cpp new file mode 100644 index 00000000..d7d9f9cd --- /dev/null +++ b/src/NavigationViews/nuiGestureRecognizer.cpp @@ -0,0 +1,281 @@ +/* + NUI3 - C++ cross-platform GUI framework for OpenGL based applications + Copyright (C) 2002-2003 Sebastien Metrot & Vincent Caron + + licence: see nui3/LICENCE.TXT + */ + + +#pragma once +#include "nuiGestureRecognizer.h" + + + +//******************************************************************************************************************* +//******************************************************************************************************************* +// +// class nuiGestureRecognizer +// + + +nuiGestureRecognizer::nuiGestureRecognizer() +: nuiSimpleContainer() +{ + mState = eGestureRecognizerStatePossible; +} + + +nuiGestureRecognizer::~nuiGestureRecognizer() +{ + +} + + +nuiGestureRecognizerState nuiGestureRecognizer::GetState() const +{ + return mState; +} + +void nuiGestureRecognizer::SetState(nuiGestureRecognizerState state) +{ + mState = state; + + // send synchronous signal + SignalStateChanged(mState); +} + + + +// virtual +bool nuiGestureRecognizer::MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) +{ + return false; +} + + +// virtual +bool nuiGestureRecognizer::MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) +{ + return false; +} + + +// virtual +bool nuiGestureRecognizer::MouseMoved(nuiSize X, nuiSize Y) +{ + return false; +} + + + + + + + + + + +#define SWIPE_INITIATED_THRESHOLD 9 +#define SWIPE_INITIATED_TIMEOUT 0.10f +#define SWIPE_ACTIVATED_THRESHOLD 70 +#define SWIPE_ACTIVATED_TIMEOUT 0.15f + + +//************************************************************************************************************ +//************************************************************************************************************ +// +// class nuiSwipeGestureRecognizer +// + + +nuiSwipeGestureRecognizer::nuiSwipeGestureRecognizer(nuiGestureDirection direction) +: nuiGestureRecognizer() +{ + mClicked = false; + mStartX = 0; + mStartY = 0; + + mDirection = direction; + mRecognizedDirection = nuiGestureDirectionNull; +} + + + +nuiSwipeGestureRecognizer::~nuiSwipeGestureRecognizer() +{ + +} + +void nuiSwipeGestureRecognizer::SetDirections(nuiGestureDirection direction) +{ + mDirection = direction; +} + + +// virtual +bool nuiSwipeGestureRecognizer::MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) +{ + bool res = nuiGestureRecognizer::MouseClicked(X, Y, Button); + + mRecognizedDirection = nuiGestureDirectionNull; + + mClicked = true; + mTime = nglTime(); + mInitiatedTime = 0; + mStartX = X; + mStartY = Y; + + return false; +} + + +// virtual +bool nuiSwipeGestureRecognizer::MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) +{ + bool res = nuiGestureRecognizer::MouseUnclicked(X, Y, Button); + + mClicked = false; + SetState(eGestureRecognizerStatePossible); + + mTime = nglTime(); + mInitiatedTime = 0; + mStartX = 0; + mStartY = 0; + + return false; +} + + +// virtual +bool nuiSwipeGestureRecognizer::MouseMoved(nuiSize X, nuiSize Y) +{ + bool res = nuiGestureRecognizer::MouseMoved(X, Y); + + if (!mClicked) + return false; + + if (GetState() == eGestureRecognizerStateEnded) + return false; + + double diffx = mStartX - X + 0.1; // adding 0.1 to avoid division by zero + double diffy = mStartY - Y + 0.1; // adding 0.1 to avoid division by zero + double currentTime = nglTime(); + + // has the swipe gesture been initiated? + if (GetState() != eGestureRecognizerStateBegan) + { + bool initiatedOnX = (abs(diffx) >= SWIPE_INITIATED_THRESHOLD); + bool initiatedOnY = (abs(diffy) >= SWIPE_INITIATED_THRESHOLD); + + // yes, it's been initiated. + if (initiatedOnX || initiatedOnY) + { + mRecognizedDirection = GetGestureDirection(initiatedOnX, initiatedOnY, mStartX, X, mStartY, Y); + + // is this recognizer in charge of the detected gesture? + if ((mRecognizedDirection & mDirection) + && ((currentTime - mTime) < SWIPE_INITIATED_TIMEOUT)) + { + // yes. consider that the gesture recognition has began + mInitiatedTime = currentTime; + SetState(eGestureRecognizerStateBegan); + } + // no, it's not. set data for the next call + else + { + mStartX = X; + mStartY = Y; + mTime = currentTime; + } + } + } + + // not yet. it's a simple "move" gesture. + if (GetState() != eGestureRecognizerStateBegan) + return false; + + // swipe has been initiated, is the gesture fully completed? + bool activatedOnX = (abs(diffx) >= SWIPE_ACTIVATED_THRESHOLD); + bool activatedOnY = (abs(diffy) >= SWIPE_ACTIVATED_THRESHOLD); + + if(activatedOnX || activatedOnY) + { + // the swipe gesture has been avorted. let's reset the data and start again + if ((currentTime - mInitiatedTime) > SWIPE_ACTIVATED_TIMEOUT) + { + mTime = nglTime(); + mInitiatedTime = 0; + mStartX = X; + mStartY = Y; + SetState(eGestureRecognizerStateFailed); + mRecognizedDirection = nuiGestureDirectionNull; + + return false; + } + + // ok! the swipe gesture has been completed! + SetState(eGestureRecognizerStateEnded); + + // let's assume it's no use to compute mDirection here, since it's been done when the swipe gesture has been initiated. + // we'll see in the future if it's wrong to make that assumption. + // mDirection = GetGesturePosition(activatedOnX, activatedOnY, mStartX, X, mStartY, Y); + + // send synchronous event + SignalSwipe(mRecognizedDirection); + } + + return false; +} + + +nuiGestureDirection nuiSwipeGestureRecognizer::GetRecognizedDirection() const +{ + return mRecognizedDirection; +} + + +nuiGestureDirection nuiSwipeGestureRecognizer::GetGestureDirection(bool evalOnX, bool evalOnY, nuiSize x1, nuiSize x2, nuiSize y1, nuiSize y2) const +{ + // diagonal gesture? + if (evalOnX && evalOnY) + { + if (x1 < x2) + { + if (y1 < y2) + return nuiGestureDirectionDownRight; + else + return nuiGestureDirectionUpRight; + } + else + { + if (y1 < y2) + return nuiGestureDirectionDownLeft; + else + return nuiGestureDirectionUpLeft; + } + } + // horizontal gesture? + else if (evalOnX) + { + if (x1 < x2) + return nuiGestureDirectionRight; + else + return nuiGestureDirectionLeft; + } + // vertical gesture? + else if (evalOnY) + { + if (y1 < y2) + return nuiGestureDirectionDown; + else + return nuiGestureDirectionUp; + } + + return nuiGestureDirectionNull; +} + + + + + + diff --git a/src/NavigationViews/nuiViewController.cpp b/src/NavigationViews/nuiViewController.cpp index cbcc3084..969199b8 100644 --- a/src/NavigationViews/nuiViewController.cpp +++ b/src/NavigationViews/nuiViewController.cpp @@ -16,16 +16,7 @@ nuiViewController::nuiViewController() SetObjectClass(_T("nuiViewController")); mAnimated = false; - mClicked = false; - mSwipeStartX = 0; - mSwipeStartY = 0; - mSwipeInitiated = false; - mSwipeActivated = false; - mSwipeDirection = nuiNoPosition; - - mpBar = new nuiNavigationBar(); - } @@ -86,222 +77,3 @@ nuiNavigationBar* nuiViewController::GetNavigationBar() - - - - - -// virtual -void nuiViewController::SwipeBegan(nuiPosition swipeDirection) -{ - //NGL_OUT(_T("SwipeBegan %ls\n"), nuiGetPosition(swipeDirection).GetChars()); - // to be overloaded -} - - -void nuiViewController::SwipeEnd(nuiPosition swipeDirection) -{ - //NGL_OUT(_T("SwipeEnd(nuiPosition swipeD %ls\n"), nuiGetPosition(swipeDirection).GetChars()); - // to be overloaded -} - -nuiPosition nuiViewController::GetSwipeDirection() const -{ - return mSwipeDirection; -} - - - - - - - - -#define SWIPE_INITIATED_THRESHOLD 9 -#define SWIPE_INITIATED_TIMEOUT 0.10f -#define SWIPE_ACTIVATED_THRESHOLD 70 -#define SWIPE_ACTIVATED_TIMEOUT 0.15f - - -// virtual -bool nuiViewController::MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) -{ - mClicked = true; - mSwipeTime = nglTime(); - mSwipeInitiatedTime = 0; - mSwipeStartX = X; - mSwipeStartY = Y; - - mSwipeInitiated = false; - mSwipeActivated = false; - mSwipeDirection = nuiNoPosition; - - return false; -} - - - -// virtual -bool nuiViewController::MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) -{ - mClicked = false; - mSwipeInitiated = false; - mSwipeActivated = false; - mSwipeTime = nglTime(); - mSwipeInitiatedTime = 0; - mSwipeStartX = 0; - mSwipeStartY = 0; - mSwipeDirection = nuiNoPosition; - - return false; -} - - - -// virtual -bool nuiViewController::MouseMoved(nuiSize X, nuiSize Y) -{ - if (!mClicked) - return false; - - if (mSwipeActivated) - return false; - - double diffx = mSwipeStartX - X + 0.1; // adding 0.1 to avoid division by zero - double diffy = mSwipeStartY - Y + 0.1; // adding 0.1 to avoid division by zero - double currentTime = nglTime(); - - // has the swipe gesture been initiated? - if (!mSwipeInitiated) - { - //LBDEBUG - NGL_OUT(_T("\n")); - NGL_OUT(_T("diffX %.2f diffY %.2f\n"), diffx, diffy); - - bool initiatedOnX = (abs(diffx) >= SWIPE_INITIATED_THRESHOLD); - bool initiatedOnY = (abs(diffy) >= SWIPE_INITIATED_THRESHOLD); - - if (initiatedOnX || initiatedOnY) - { - NGL_OUT(_T("initiated? %.2f\n"), (currentTime - mSwipeTime)); - - // yes, it's been initiated. - if ((currentTime - mSwipeTime) < SWIPE_INITIATED_TIMEOUT) - { - NGL_OUT(_T("YES! initiated!\n")); - - mSwipeInitiated = true; - mSwipeInitiatedTime = currentTime; - mSwipeDirection = GetGestureDirection(initiatedOnX, initiatedOnY, mSwipeStartX, X, mSwipeStartY, Y); - - // send synchronous event - EventSwipeBegan(); - // call virtual cbk - SwipeBegan(mSwipeDirection); - - } - // no, it's not. set data for the next call - else - { - NGL_OUT(_T("NO! let's start again\n\n")); - - mSwipeStartX = X; - mSwipeStartY = Y; - mSwipeTime = currentTime; - } - } - } - - // not yet. it's a simple "move" gesture. - if (!mSwipeInitiated) - return false; - - // swipe has been initiated, is the gesture fully completed? - bool activatedOnX = (abs(diffx) >= SWIPE_ACTIVATED_THRESHOLD); - bool activatedOnY = (abs(diffy) >= SWIPE_ACTIVATED_THRESHOLD); - - // LBDEBUG - // if(abs(diffx / diffy) > 1 && abs(diffx) > SWIPE_ACTIVATED_THRESHOLD) - if(activatedOnX || activatedOnY) - { - NGL_OUT(_T("activated? %.2f\n"), (currentTime - mSwipeInitiatedTime)); - - // the swipe gesture has been avorted. let's reset the data and start again - if ((currentTime - mSwipeInitiatedTime) > SWIPE_ACTIVATED_TIMEOUT) - { - NGL_OUT(_T("NO! let's start again\n\n")); - - mSwipeTime = nglTime(); - mSwipeInitiatedTime = 0; - mSwipeStartX = X; - mSwipeStartY = Y; - mSwipeInitiated = false; - mSwipeActivated = false; - mSwipeDirection = nuiNoPosition; - - return false; - } - - NGL_OUT(_T("YES! activated!\n")); - - // ok! the swipe gesture has been completed! - mSwipeActivated = true; - - // let's assume it's no use to compute mSwipeDirection here, since it's been done when the swipe gesture has been initiated. - // we'll see in the future if it's wrong to make that assumption. - // mSwipeDirection = GetGestureDirection(activatedOnX, activatedOnY, mSwipeStartX, X, mSwipeStartY, Y); - - // send synchronous event - EventSwipeEnd(); - // call virtual cbk - SwipeEnd(mSwipeDirection); - } - - - return false; -} - - - - - -nuiPosition nuiViewController::GetGestureDirection(bool evalOnX, bool evalOnY, nuiSize x1, nuiSize x2, nuiSize y1, nuiSize y2) const -{ - // diagonal gesture? - if (evalOnX && evalOnY) - { - if (x1 < x2) - { - if (y1 < y2) - return nuiBottomRight; - else - return nuiTopRight; - } - else - { - if (y1 < y2) - return nuiBottomLeft; - else - return nuiTopLeft; - } - } - // horizontal gesture? - else if (evalOnX) - { - if (x1 < x2) - return nuiRight; - else - return nuiLeft; - } - // vertical gesture? - else if (evalOnY) - { - if (y1 < y2) - return nuiBottom; - else - return nuiTop; - } - - return nuiNoPosition; - -} diff --git a/tutorials/NavigationViewSwipe/resources/css/style.css b/tutorials/NavigationViewSwipe/resources/css/style.css index bc503fdb..fc85750e 100644 --- a/tutorials/NavigationViewSwipe/resources/css/style.css +++ b/tutorials/NavigationViewSwipe/resources/css/style.css @@ -62,9 +62,31 @@ MyViewController Position: TopLeft; BorderTop: 40; BorderLeft: 50; +} + +nuiComboBox! +{ + Position: TopLeft; + BorderTop: 54; + BorderLeft: 24; + UserWidth: 180; + UserHeight: 26; } +@nuiFont fontCombo +{ + Name: "Arial"; + Size: 16; + Italic: false; + Bold: true; +} + +(nuiComboBox)nuiLabel! +{ + Font: fontCombo; +} + // blank ending line following diff --git a/tutorials/NavigationViewSwipe/src/MainWindow.cpp b/tutorials/NavigationViewSwipe/src/MainWindow.cpp index a0c4542c..bfbf2fa2 100644 --- a/tutorials/NavigationViewSwipe/src/MainWindow.cpp +++ b/tutorials/NavigationViewSwipe/src/MainWindow.cpp @@ -13,7 +13,8 @@ #include "nuiImageAnimation.h" #include "nuiTask.h" #include "nuiSpriteView.h" - +#include "nuiGestureRecognizer.h" +#include "nuiComboBox.h" /* @@ -46,11 +47,6 @@ void MainWindow::OnCreation() } - - - - - void MainWindow::OnClose() { if (GetNGLWindow()->IsInModalState()) @@ -92,33 +88,30 @@ bool MainWindow::LoadCSS(const nglPath& rPath) +//************************************************************************************** +//************************************************************************************** +//************************************************* +// MyViewController +// MyViewController::MyViewController() : nuiViewController(), mTimer(0.4f), mEventSink(this) { SetObjectClass(_T("MyViewController")); SetTitle(_T("Swipe Detector")); + + // a simple background icon nuiImage* pIcon = new nuiImage(); pIcon->SetObjectName(_T("SwipeIcon")); AddChild(pIcon); -// mClicked = false; - -// mpArrowsContainer = new nuiSimpleContainer(); -// mpArrowsContainer->SetObjectName(_T("ArrowsContainer")); -// AddChild(mpArrowsContainer); -// -// mpArrows = new nuiImageAnimation(17, _T("rsrc:/decorations/directions.png")); -// mpArrows->SetObjectName(_T("Arrows")); -// mpArrowsContainer->AddChild(mpArrows); - + // sprite view to manage the sprites nuiSpriteView* pSpriteView = new nuiSpriteView(); -// pSpriteView->EnableRenderCache(false); AddChild(pSpriteView); nuiSpriteDef* pDef = new nuiSpriteDef(nglPath(_T("rsrc:/decorations/arrow"))); @@ -126,6 +119,7 @@ MyViewController::MyViewController() nuiSprite* pSprite = NULL; float angle = 0; + // a set of sprite, rotated around the pivot for (uint32 i = 0; i < 8; i++) { pSprite = new nuiSprite(pDef); @@ -139,117 +133,132 @@ MyViewController::MyViewController() angle += 360 / 8; } + // swipe gesture recognizer + mpSwipeRecognizer = new nuiSwipeGestureRecognizer(nuiGestureDirectionRight); + mSink.Connect(mpSwipeRecognizer->SignalSwipe, nuiMakeDelegate(this, &MyViewController::OnSignalSwipe)); + mSink.Connect(mpSwipeRecognizer->SignalStateChanged, nuiMakeDelegate(this, &MyViewController::OnSignalRecognizerStateChanged)); + AddChild(mpSwipeRecognizer); + + // a combo box to setup the gesture recognizer + nuiTreeNode* pTree = new nuiTreeNode(_T("Swipe"), true); + nuiTreeNode* pNode = new nuiTreeNode(_T("right"), true); + pTree->AddChild(pNode); + pTree->AddChild(new nuiTreeNode(_T("right/left"))); + pTree->AddChild(new nuiTreeNode(_T("top/bottom"))); + pTree->AddChild(new nuiTreeNode(_T("diagonals"))); + pTree->AddChild(new nuiTreeNode(_T("all"))); + nuiComboBox* pCombo = new nuiComboBox(pTree); + pCombo->SetSelected(pNode); + mEventSink.Connect(pCombo->ValueChanged, &MyViewController::OnComboChanged, (void*)pCombo); + AddChild(pCombo); + + + // monitor reset mEventSink.Connect(mTimer.Tick, &MyViewController::OnResetArrows); } +//************************************************* +// ~MyViewController +// MyViewController::~MyViewController() { } -//// virtual -//bool MyViewController::MouseClicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) -//{ -// bool res = nuiViewController::MouseClicked(X, Y, Button); -// mClicked = true; -// return res; -//} -// -// -//// virtual -//bool MyViewController::MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button) -//{ -// bool res = nuiViewController::MouseUnclicked(X, Y, Button); -// mClicked = false; -// -// SetDelay(nuiMakeTask(this, &MyViewController::ResetArrows), 0.4f); -// -// return res; -//} -// -// -//// virtual -//bool MyViewController::MouseMoved(nuiSize X, nuiSize Y) -//{ -// bool res = nuiViewController::MouseMoved(X, Y); -// if (!mClicked) -// return res; -// -// -// -// return res; -//} +void MyViewController::OnComboChanged(const nuiEvent& rEvent) +{ + nuiComboBox* pCombo = (nuiComboBox*)rEvent.mpUser; + uint32 value = pCombo->GetValue(); + + nuiGestureDirection direction; + + switch (value) + { + case 0: direction = nuiGestureDirectionRight; break; + case 1: direction = nuiGestureDirectionHorizontal; break; + case 2: direction = nuiGestureDirectionVertical; break; + case 3: direction = nuiGestureDirectionDiagonals; break; + case 4: direction = nuiGestureDirectionHorizontal | nuiGestureDirectionVertical | nuiGestureDirectionDiagonals; break; + } + + mpSwipeRecognizer->SetDirections(direction); +} + -// virtual -void MyViewController::SwipeBegan(nuiPosition swipeDirection) +void MyViewController::OnSignalSwipe(nuiGestureDirection direction) { mTimer.Stop(); - - uint32 index = 0; - switch (swipeDirection) + uint32 index = 0; + switch (direction) { - case nuiTop: index = 0; break; - case nuiTopRight: index = 1; break; - case nuiRight: index = 2; break; - case nuiBottomRight: index = 3; break; - case nuiBottom: index = 4; break; - case nuiBottomLeft: index = 5; break; - case nuiLeft: index = 6; break; - case nuiTopLeft: index = 7; break; + case nuiGestureDirectionUp : index = 0; break; + case nuiGestureDirectionUpRight : index = 1; break; + case nuiGestureDirectionRight : index = 2; break; + case nuiGestureDirectionDownRight : index = 3; break; + case nuiGestureDirectionDown : index = 4; break; + case nuiGestureDirectionDownLeft: index = 5; break; + case nuiGestureDirectionLeft: index = 6; break; + case nuiGestureDirectionUpLeft: index = 7; break; } - mpArrows[index]->SetAnimation(_T("initiated")); -// mpArrows->Invalidate(); - + mpArrows[index]->SetAnimation(_T("activated")); mTimer.Start(false); } -void MyViewController::SwipeEnd(nuiPosition swipeDirection) +void MyViewController::OnSignalRecognizerStateChanged(nuiGestureRecognizerState state) { + + nglString str; + switch (state) + { + case eGestureRecognizerStatePossible: str = _T("StatePossible"); break; + case eGestureRecognizerStateBegan: str = _T("StateBegan"); break; + case eGestureRecognizerStateEnded: str = _T("StateEnd"); break; + case eGestureRecognizerStateFailed: str = _T("StateFailed"); break; + default: str = _T("unknown"); + } + + NGL_OUT(_T("OnSwipeStateChanged %ls\n"), str.GetChars()); + + if (state != eGestureRecognizerStateBegan) + return; + mTimer.Stop(); uint32 index = 0; - - switch (swipeDirection) + switch (mpSwipeRecognizer->GetRecognizedDirection()) { - case nuiTop: index = 0; break; - case nuiTopRight: index = 1; break; - case nuiRight: index = 2; break; - case nuiBottomRight: index = 3; break; - case nuiBottom: index = 4; break; - case nuiBottomLeft: index = 5; break; - case nuiLeft: index = 6; break; - case nuiTopLeft: index = 7; break; + case nuiGestureDirectionUp : index = 0; break; + case nuiGestureDirectionUpRight : index = 1; break; + case nuiGestureDirectionRight : index = 2; break; + case nuiGestureDirectionDownRight : index = 3; break; + case nuiGestureDirectionDown : index = 4; break; + case nuiGestureDirectionDownLeft: index = 5; break; + case nuiGestureDirectionLeft: index = 6; break; + case nuiGestureDirectionUpLeft: index = 7; break; } - mpArrows[index]->SetAnimation(_T("activated")); -// mpArrows->Invalidate(); - + mpArrows[index]->SetAnimation(_T("initiated")); mTimer.Start(false); } -//SetDelay(nuiMakeTask(this, &MyViewController::ResetArrows), 0.4f); -//void MyViewController::SetDelay(nuiTask* pTask, float seconds) -//{ -// nuiAnimation::RunOnAnimationTick(pTask, seconds / nuiAnimation::GetTimer()->GetPeriod()); -//} - +//************************************************* +// OnResetArrows +// void MyViewController::OnResetArrows(const nuiEvent& rEvent) { mTimer.Stop(); for (uint32 index = 0; index < 8; index++) mpArrows[index]->SetAnimation(_T("off")); -// mpArrows->SetFrameIndex(0); -// mpArrows->Invalidate(); } diff --git a/tutorials/NavigationViewSwipe/src/MainWindow.h b/tutorials/NavigationViewSwipe/src/MainWindow.h index 74640398..05a63751 100644 --- a/tutorials/NavigationViewSwipe/src/MainWindow.h +++ b/tutorials/NavigationViewSwipe/src/MainWindow.h @@ -10,12 +10,12 @@ #include "nuiMainWindow.h" #include "nuiNavigationController.h" #include "nuiViewController.h" +#include "nuiGestureRecognizer.h" class nuiImageAnimation; class nuiSprite; - class MainWindow : public nuiMainWindow { public: @@ -27,7 +27,6 @@ class MainWindow : public nuiMainWindow protected: - private: nuiNavigationController* mpNav; @@ -37,6 +36,7 @@ class MainWindow : public nuiMainWindow +// the inherited view controller to handle the application running class MyViewController : public nuiViewController { public: @@ -45,21 +45,25 @@ class MyViewController : public nuiViewController protected: - virtual void SwipeBegan(nuiPosition swipeDirection); - virtual void SwipeEnd(nuiPosition swipeDirection); - void OnResetArrows(const nuiEvent& rEvent); + void OnComboChanged(const nuiEvent& rEvent); + void OnSignalSwipe(nuiGestureDirection direction); + void OnSignalRecognizerStateChanged(nuiGestureRecognizerState state); -// void SetDelay(nuiTask* pTask, float seconds); + // available virtual callbacks from nuiViewController + // virtual void ViewWillAppear(); + // virtual void ViewWillDisappear(); + // virtual void ViewDidAppear(); + // virtual void ViewDidDisappear(); -// bool mClicked; -// virtual bool MouseClicked (nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); -// virtual bool MouseUnclicked(nuiSize X, nuiSize Y, nglMouseInfo::Flags Button); -// virtual bool MouseMoved (nuiSize X, nuiSize Y); +private: + void OnResetArrows(const nuiEvent& rEvent); + + nuiSwipeGestureRecognizer* mpSwipeRecognizer; + nuiTimer mTimer; -// nuiImageAnimation* mpArrows; -// nuiSimpleContainer* mpArrowsContainer; std::vector mpArrows; nuiEventSink mEventSink; + nuiSlotsSink mSink; };