package Ġit . se phi ro th . android . library . ui gest ures Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . os . Message Ċ import Ġandroid . util . Log Ċ import Ġandroid . view . Motion Event Ċ import Ġkotlin . math . atan 2 Ċ Ċ /** Ċ Ġ* ĠU IR ot ation Gesture Recognizer Ġis Ġa Ġsubclass Ġof ĠU IG est ure Recognizer Ġthat Ġlooks Ġfor Ġrotation Ġgest ures Ġinvol ving Ġtwo Ċ Ġ* Ġto uches . ĠWhen Ġthe Ġuser Ġmoves Ġthe Ġf ingers Ġopposite Ġeach Ġother Ġin Ġa Ġcircular Ġmotion , Ġthe Ġunderlying Ġview Ġshould Ġrotate Ġin Ġa Ċ Ġ* Ġcorresponding Ġdirection Ġand Ġspeed . Ċ Ġ* Ċ Ġ* Ġ@ author Ġa less andro Ġcr ug n ola Ċ Ġ* Ġ@ see Ġ[ Ċ Ġ* Ġhttps :// developer . apple . com / reference / u ikit / ui rotation gest ur ere cognizer ]( https :// developer . apple . com / reference / u ikit / ui rotation gest ur ere cognizer ) Ċ Ġ*/ Ċ Ċ @ Suppress (" Member Visibility Can Be Private ", Ġ" unused ") Ċ open Ġclass ĠU IR ot ate Gesture Recognizer ( context : ĠContext ) Ġ: ĠU IG est ure Recognizer ( context ), ĠUI Continuous Recognizer Ġ{ ĊĊĠĠĠ Ġ// ĠTODO : Ġimplement Ġrotation Ġwith Ġ> Ġ 2 Ġf ingers ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġminimum Ġrotation Ġthreshold Ġ( in Ġradians ) Ġbefore Ġthe ĊĠĠĠĠ Ġ* Ġgesture Ġcan Ġbe Ġaccepted ĊĠĠĠĠ Ġ* Ġ@ since Ġ 1 . 0 . 0 ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġvar Ġrotation Threshold : ĠDouble Ġ= Ġ 0 . toDouble () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġthe Ġrotation Ġin Ġradians ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġthe Ġcurrent Ġrotation Ġin Ġradians ĊĠĠĠĠ Ġ* Ġ@ see Ġ# rotation In Degrees ĊĠĠĠĠ Ġ* Ġ@ since Ġ 1 . 0 . 0 ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġvar Ġrotation In Radians : ĠDouble Ġ= Ġ 0 . 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġset ĊĊĠĠĠ Ġprivate Ġvar Ġm Initial Rotation : ĠDouble Ġ= Ġ 0 . toDouble () ĊĠĠĠ Ġprivate Ġvar Ġm Previous Angle : ĠDouble Ġ= Ġ 0 . toDouble () ĊĊĠĠĠ Ġprivate Ġvar Ġx 1 : ĠFloat Ġ= Ġ 0 . toFloat () ĊĠĠĠ Ġprivate Ġvar Ġy 1 : ĠFloat Ġ= Ġ 0 . toFloat () ĊĠĠĠ Ġprivate Ġvar Ġx 2 : ĠFloat Ġ= Ġ 0 . toFloat () ĊĠĠĠ Ġprivate Ġvar Ġy 2 : ĠFloat Ġ= Ġ 0 . toFloat () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ return ĠThe Ġvelocity Ġof Ġthe Ġrotation Ġgesture Ġin Ġradians Ġper Ġsecond . ĊĠĠĠĠ Ġ* Ġ@ since Ġ 1 . 0 . 0 ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġvar Ġvelocity : ĠDouble Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠ Ġprivate Ġset ĊĊĠĠĠ Ġprivate Ġvar Ġm Valid : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġm Started : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġm Down : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġm Ptr ID 1 : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġm Ptr ID 2 : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġm Previous Event : ĠMotion Event ? Ġ= Ġnull ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġthe Ġrotation Ġin Ġdegrees ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġthe Ġcurrent Ġrotation Ġin Ġdegrees ĊĠĠĠĠ Ġ* Ġ@ see Ġ. get Rotation In Radians ĊĠĠĠĠ Ġ* Ġ@ since Ġ 1 . 0 . 0 ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġrotation In Degrees : ĠDouble ĊĠĠĠĠĠĠĠ Ġget () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġangle Ġ= ĠMath . to Degrees ( rotation In Radians ) Ġ% Ġ 3 6 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( angle Ġ< Ġ- 1 8 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġangle Ġ+= Ġ 3 6 0 . 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( angle Ġ> Ġ 1 8 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġangle Ġ-= Ġ 3 6 0 . 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġangle ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġhandle Message ( msg : ĠMessage ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( msg . what ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMESSAGE _ RESET Ġ-> Ġhandle Reset () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġreset () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . reset () ĊĠĠĠĠĠĠĠ Ġhandle Reset () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Reset () Ġ{ ĊĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Possible ĊĠĠĠĠĠĠĠ Ġm Initial Rotation Ġ= Ġ 0 . 0 ĊĠĠĠĠĠĠĠ Ġset Begin F iring Events ( false ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġrotation Threshold Ġ= ĠROT ATION _ S LO P ĊĠĠĠĠĠĠĠ Ġm Ptr ID 1 Ġ= ĠINVALID _ POINTER _ ID ĊĠĠĠĠĠĠĠ Ġm Ptr ID 2 Ġ= ĠINVALID _ POINTER _ ID ĊĠĠĠĠĠĠĠ Ġvelocity Ġ= Ġ 0 . toDouble () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon StateChanged ( re cognizer : ĠU IG est ure Recognizer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( re cognizer . state Ġ=== ĠState . Failed Ġ&& Ġstate Ġ=== ĠState . Be gan ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstop Listen For Other State Changes () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent If Can Recognize Sim ultaneous ly () ĊĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( re cognizer . in State ( State . Be gan , ĠState . Ended ) Ġ&& Ġin State ( State . Be gan , ĠState . Possible ) Ġ&& Ġm Started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstop Listen For Other State Changes () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremove Messages () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Failed ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġfire ActionEvent If Can Recognize Sim ultaneous ly () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( in State ( State . Changed , ĠState . Ended )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Begin F iring Events ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( delegate !!. should Recognize Sim ultaneous ly With Gesture Recognizer ( this )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Begin F iring Events ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġhas Be gan F iring Events (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġsuper . has Be gan F iring Events () Ġ&& Ġin State ( State . Be gan , ĠState . Changed ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Touch Event ( event : ĠMotion Event ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Touch Event ( event ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! isEnabled ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġaction Ġ= Ġevent . action Mask ed ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( action ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ DOWN Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! delegate ?. should Receive Touch ?. invoke ( this ) !! ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcancel s Tou ches In View ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Down Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Initial Rotation Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstop Listen For Other State Changes () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Possible ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Begin F iring Events ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ POINTER _ DOWN Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( m Down Ġ&& ĠnumberOf Tou ches Ġ== Ġ 2 Ġ&& Ġstate Ġ!= ĠState . Failed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Ptr ID 1 Ġ= Ġevent . get Pointer Id ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Ptr ID 2 Ġ= Ġevent . get Pointer Id ( 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġx 1 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġy 1 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġx 2 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġy 2 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Initial Rotation Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ POINTER _ UP Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( m Down Ġ&& ĠnumberOf Tou ches Ġ== Ġ 2 Ġ&& Ġstate Ġ!= ĠState . Failed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpointer Index Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġevent . action Ġand ĠMotion Event . ACTION _ POINTER _ INDEX _ MASK Ġshr ĠMotion Event . ACTION _ POINTER _ INDEX _ SHIFT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpointer Id Ġ= Ġevent . get Pointer Id ( pointer Index ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġfound Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġevent . pointer Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġid Ġ= Ġevent . get Pointer Id ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( id Ġ== Ġpointer Id ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! found ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Ptr ID 1 Ġ= Ġid ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Ptr ID 2 Ġ= Ġid ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfound Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġx 1 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġy 1 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġx 2 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġy 2 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Initial Rotation Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ UP Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Down Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Angle Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Initial Rotation Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvelocity Ġ= Ġ 0 . toDouble () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( null Ġ!= Ġm Previous Event ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Event !!. recycle () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Event Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( in State ( State . Be gan , ĠState . Changed )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbegan Ġ= Ġhas Be gan F iring Events () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Ended ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( be gan ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Handler . send Empty Message ( MESSAGE _ RESET ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ MOVE Ġ-> Ġif Ġ( m Valid Ġ&& Ġstate Ġ!= ĠState . Failed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnx 1 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġny 1 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnx 2 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġny 2 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 2 )) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! m Started Ġ&& Ġm Down ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Initial Rotation Ġ+= Ġangle Between Lines ( x 2 , Ġy 2 , Ġx 1 , Ġy 1 , Ġnx 2 , Ġny 2 , Ġnx 1 , Ġny 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlogMessage ( Log . INFO , Ġ" m Initial Rotation , Ġ$ m Initial Rotation , Ġ$ rotation Threshold ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Math . abs ( m Initial Rotation ) Ġ> Ġrotation Threshold ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Started Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( delegate ?. should Begin ?. invoke ( this ) !! ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Be gan ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( null Ġ== Ġrequire Failure Of ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent If Can Recognize Sim ultaneous ly () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequire Failure Of !!. state Ġ== ĠState . Failed Ġ-> Ġfire ActionEvent If Can Recognize Sim ultaneous ly () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequire Failure Of !!. in State ( State . Be gan , ĠState . Ended , ĠState . Changed ) Ġ-> Ġstate Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠState . Failed ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlisten For Other State Changes () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Begin F iring Events ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlogMessage ( Log . DEBUG , Ġ" waiting ...") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Failed ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( m Started Ġ&& Ġm Down ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrotation In Radians Ġ= Ġangle Between Lines ( x 2 , Ġy 2 , Ġx 1 , Ġy 1 , Ġnx 2 , Ġny 2 , Ġnx 1 , Ġny 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( state Ġ== ĠState . Be gan ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( has Be gan F iring Events ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Changed ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( state Ġ== ĠState . Changed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Changed ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfire ActionEvent () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Event ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdiff Ġ= ĠMath . max ( rotation In Radians , Ġm Previous Angle ) Ġ- ĠMath . min ( rotation In Radians , Ġm Previous Angle ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtime Ġ= Ġevent . event Time Ġ- Ġit . event Time ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvelocity Ġ= Ġif Ġ( time Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 0 0 0 Ġ/ Ġtime Ġ* Ġdiff ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . recycle () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġx 1 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġy 1 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġx 2 Ġ= Ġevent . getX ( event . find Pointer Index ( m Ptr ID 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġy 2 Ġ= Ġevent . getY ( event . find Pointer Index ( m Ptr ID 2 )) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Event Ġ= ĠMotion Event . obtain ( event ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Angle Ġ= Ġrotation In Radians ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ CANCEL Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Ptr ID 1 Ġ= ĠINVALID _ POINTER _ ID ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Ptr ID 2 Ġ= ĠINVALID _ POINTER _ ID ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Valid Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Down Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Angle Ġ= Ġ 0 . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvelocity Ġ= Ġ 0 . toDouble () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( null Ġ!= Ġm Previous Event ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Event !!. recycle () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Previous Event Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Cancelled ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Begin F iring Events ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Handler . send Empty Message ( MESSAGE _ RESET ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcancel s Tou ches In View ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġangle Between Lines ( f X : ĠFloat , Ġf Y : ĠFloat , Ġs X : ĠFloat , Ġs Y : ĠFloat , Ġnf X : ĠFloat , Ġnf Y : ĠFloat , Ġns X : ĠFloat , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġns Y : ĠFloat ): ĠDouble Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġangle 1 Ġ= Ġatan 2 (( f Y Ġ- Ġs Y ), Ġ( f X Ġ- Ġs X )). toDouble () ĊĠĠĠĠĠĠĠ Ġval Ġangle 2 Ġ= Ġatan 2 (( nf Y Ġ- Ġns Y ), Ġ( nf X Ġ- Ġns X )). toDouble () ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ(( angle 1 Ġ>= Ġ 0 Ġ&& Ġangle 2 Ġ>= Ġ 0 ) Ġ|| Ġ( angle 1 Ġ< Ġ 0 Ġ&& Ġangle 2 Ġ< Ġ 0 )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġangle 2 Ġ- Ġangle 1 ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( angle 2 Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġangle 1 Ġ+ Ġangle 2 ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġangle 2 Ġ+ Ġangle 1 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġremove Messages () Ġ{ ĊĠĠĠĠĠĠĠ Ġremove Messages ( MESSAGE _ RESET ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠMESSAGE _ RESET Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠINVALID _ POINTER _ ID Ġ= Ġ- 1 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠROT ATION _ S LO P Ġ= Ġ 0 . 0 0 8 ĊĠĠĠ Ġ} Ċ } Ċ