1+ package gov .nasa .worldwind .gesture ;
2+
3+ import android .view .GestureDetector .SimpleOnGestureListener ;
4+ import android .view .MotionEvent ;
5+ import android .view .ViewConfiguration ;
6+
7+ import gov .nasa .worldwind .PickedObject ;
8+ import gov .nasa .worldwind .WorldWindow ;
9+ import gov .nasa .worldwind .geom .Position ;
10+ import gov .nasa .worldwind .render .Renderable ;
11+
12+ public class SelectDragListener extends SimpleOnGestureListener {
13+
14+ private final WorldWindow wwd ;
15+ private final int slope ;
16+ private Position pickedPosition ;
17+ private Renderable pickedRenderable ;
18+ private boolean isDraggingArmed ;
19+ private boolean isDragging ;
20+
21+ private SelectDragCallback callback ;
22+
23+ public SelectDragListener (WorldWindow wwd ) {
24+ this .wwd = wwd ;
25+ this .slope = ViewConfiguration .get (wwd .getContext ()).getScaledTouchSlop ();
26+ }
27+
28+ public boolean isDragging () {
29+ return isDragging ;
30+ }
31+
32+ public void setCallback (SelectDragCallback callback ) {
33+ this .callback = callback ;
34+ }
35+
36+ public SelectDragCallback getCallback () {
37+ return callback ;
38+ }
39+
40+ @ Override
41+ public boolean onDown (MotionEvent event ) {
42+ pick (event );
43+ return false ;
44+ }
45+
46+ @ Override
47+ public boolean onSingleTapUp (MotionEvent event ) {
48+ if (pickedPosition != null && callback != null ) {
49+ if (pickedRenderable != null && callback .canPickRenderable (pickedRenderable ))
50+ callback .onRenderablePicked (pickedRenderable , pickedPosition );
51+ else callback .onTerrainPicked (pickedPosition );
52+ wwd .requestRedraw ();
53+ }
54+ return false ;
55+ }
56+
57+ @ Override
58+ public boolean onScroll (MotionEvent downEvent , MotionEvent moveEvent , float distanceX , float distanceY ) {
59+ Position fromPosition = pickedPosition ;
60+ if (isDraggingArmed && fromPosition != null && pickedRenderable != null && callback != null ) {
61+ // Signal that dragging is in progress
62+ isDragging = true ;
63+
64+ // Backup original altitude
65+ double altitude = fromPosition .altitude ;
66+ // First we compute the screen coordinates of the position's "ground" point. We'll apply the
67+ // screen X and Y drag distances to this point, from which we'll compute a new position,
68+ // wherein we restore the original position's altitude.
69+ PickedObject terrainPickedObject = wwd .pick (moveEvent .getX (), moveEvent .getY ()).terrainPickedObject ();
70+ if (terrainPickedObject != null && terrainPickedObject .getTerrainPosition () != null ) {
71+ Position toPosition = terrainPickedObject .getTerrainPosition ();
72+ // Restore original altitude
73+ toPosition .altitude = altitude ;
74+ // Callback event
75+ callback .onRenderableMoved (pickedRenderable , fromPosition , toPosition );
76+ // Remember new position
77+ pickedPosition = toPosition ;
78+ // Reflect the change in position on the globe.
79+ wwd .requestRedraw ();
80+ } else {
81+ // Probably clipped by near/far clipping plane or off the globe. The position was not updated. Stop the drag.
82+ isDraggingArmed = false ;
83+ }
84+ return true ; // We consumed this event, even if dragging has been stopped.
85+ }
86+ return false ;
87+ }
88+
89+ @ Override
90+ public boolean onDoubleTap (MotionEvent event ) {
91+ if (pickedRenderable != null && pickedPosition != null && callback != null ) {
92+ callback .onRenderableDoubleTap (pickedRenderable , pickedPosition );
93+ wwd .requestRedraw ();
94+ return true ;
95+ }
96+ return false ;
97+ }
98+
99+ @ Override
100+ public void onLongPress (MotionEvent event ) {
101+ showContext ();
102+ pick (event ); // Select possible drag point
103+ }
104+
105+ @ Override
106+ public boolean onContextClick (MotionEvent event ) {
107+ showContext ();
108+ pick (event ); // Select possible drag point
109+ return true ;
110+ }
111+
112+ public void cancelDragging () {
113+ isDragging = false ;
114+ isDraggingArmed = false ;
115+ // Callback event
116+ if (pickedRenderable != null && pickedPosition != null && callback != null ) {
117+ callback .onRenderableMovingFinished (pickedRenderable , pickedPosition );
118+ wwd .requestRedraw ();
119+ }
120+ }
121+
122+ private void showContext () {
123+ if (pickedPosition != null && callback != null ) {
124+ if (pickedRenderable != null ) callback .onRenderableContext (pickedRenderable , pickedPosition );
125+ else callback .onTerrainContext (pickedPosition );
126+ wwd .requestRedraw ();
127+ }
128+ }
129+
130+ /**
131+ * Performs a pick at the tap location and conditionally arms the dragging flag, so that dragging can occur if
132+ * the next event is an onScroll event.
133+ */
134+ private void pick (MotionEvent event ) {
135+ // Perform the pick at the screen x, y
136+ var pickList = wwd .pick (event .getX (), event .getY ());
137+
138+ // Store picked position
139+ pickedPosition = pickList .terrainPickedObject () != null ? pickList .terrainPickedObject ().getTerrainPosition () : null ;
140+
141+ // Pick objects inside touch slope if current pick list has no renderables
142+ if (!pickList .hasNonTerrainObjects ()) {
143+ pickList = wwd .pickShapesInRect (event .getX () - slope / 2f , event .getY () - slope / 2f , slope , slope );
144+ }
145+
146+ // Examine the picked objects for Renderables
147+ Object userObject = pickList .topPickedObject () != null ? pickList .topPickedObject ().getUserObject () : null ;
148+ pickedRenderable = userObject instanceof Renderable ? (Renderable ) userObject : null ;
149+
150+ // Determine whether the dragging flag should be "armed".
151+ isDraggingArmed = (userObject instanceof Renderable ) && callback != null && callback .canMoveRenderable ((Renderable ) userObject );
152+ }
153+
154+ }
0 commit comments