1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.constraintlayout.core.dsl;
18 
19 /**
20  * Create automatic swipe handling object
21  */
22 public class OnSwipe {
23 
24     private Drag mDragDirection = null;
25     private Side mTouchAnchorSide = null;
26 
27     private String mTouchAnchorId = null;
28     private String mLimitBoundsTo = null;
29     private TouchUp mOnTouchUp = null;
30     private String mRotationCenterId = null;
31     private float mMaxVelocity = Float.NaN;
32     private float mMaxAcceleration = Float.NaN;
33     private float mDragScale = Float.NaN;
34 
35     private float mDragThreshold = Float.NaN;
36     private float mSpringDamping = Float.NaN;
37     private float mSpringMass = Float.NaN;
38     private float mSpringStiffness = Float.NaN;
39     private float mSpringStopThreshold = Float.NaN;
40     private Boundary mSpringBoundary = null;
41     private Mode mAutoCompleteMode = null;
42 
OnSwipe()43     public OnSwipe() {
44     }
45 
OnSwipe(String anchor, Side side, Drag dragDirection)46     public OnSwipe(String anchor, Side side, Drag dragDirection) {
47         mTouchAnchorId = anchor;
48         mTouchAnchorSide = side;
49         mDragDirection = dragDirection;
50     }
51 
52     public enum Mode {
53         VELOCITY,
54         SPRING
55     }
56 
57     public enum Boundary {
58         OVERSHOOT,
59         BOUNCE_START,
60         BOUNCE_END,
61         BOUNCE_BOTH,
62     }
63 
64 
65     public enum Drag {
66         UP,
67         DOWN,
68         LEFT,
69         RIGHT,
70         START,
71         END,
72         CLOCKWISE,
73         ANTICLOCKWISE
74     }
75 
76     public static final int FLAG_DISABLE_POST_SCROLL = 1;
77     public static final int FLAG_DISABLE_SCROLL = 2;
78 
79     public enum Side {
80         TOP,
81         LEFT,
82         RIGHT,
83         BOTTOM,
84         MIDDLE,
85         START,
86         END,
87     }
88 
89     public enum TouchUp {
90         AUTOCOMPLETE,
91         TO_START,
92         NEVER_COMPLETE_END,
93         TO_END,
94         STOP,
95         DECELERATE,
96         DECELERATE_COMPLETE,
97         NEVER_COMPLETE_START
98     }
99 
100     /**
101      * The id of the view who's movement is matched to your drag
102      * If not specified it will map to a linear movement across the width of the motionLayout
103      */
setTouchAnchorId(String id)104     public OnSwipe setTouchAnchorId(String id) {
105         mTouchAnchorId = id;
106         return this;
107     }
108 
getTouchAnchorId()109     public String getTouchAnchorId() {
110         return mTouchAnchorId;
111     }
112 
113     /**
114      * This side of the view that matches the drag movement.
115      * Only meaning full if the object changes size during the movement.
116      * (rotation is not considered)
117      */
setTouchAnchorSide(Side side)118     public OnSwipe setTouchAnchorSide(Side side) {
119         mTouchAnchorSide = side;
120         return this;
121     }
122 
getTouchAnchorSide()123     public Side getTouchAnchorSide() {
124         return mTouchAnchorSide;
125     }
126 
127     /**
128      * The direction of the drag.
129      */
setDragDirection(Drag dragDirection)130     public OnSwipe setDragDirection(Drag dragDirection) {
131         mDragDirection = dragDirection;
132         return this;
133     }
134 
getDragDirection()135     public Drag getDragDirection() {
136         return mDragDirection;
137     }
138 
139     /**
140      * The maximum velocity (Change in progress per second) animation can achieve
141      */
setMaxVelocity(int maxVelocity)142     public OnSwipe setMaxVelocity(int maxVelocity) {
143         mMaxVelocity = maxVelocity;
144         return this;
145     }
146 
getMaxVelocity()147     public float getMaxVelocity() {
148         return mMaxVelocity;
149     }
150 
151     /**
152      * The maximum acceleration and deceleration of the animation
153      * (Change in Change in progress per second)
154      * Faster makes the object seem lighter and quicker
155      */
setMaxAcceleration(int maxAcceleration)156     public OnSwipe setMaxAcceleration(int maxAcceleration) {
157         mMaxAcceleration = maxAcceleration;
158         return this;
159     }
160 
getMaxAcceleration()161     public float getMaxAcceleration() {
162         return mMaxAcceleration;
163     }
164 
165 
166     /**
167      * Normally 1 this can be tweaked to make the acceleration faster
168      */
setDragScale(int dragScale)169     public OnSwipe setDragScale(int dragScale) {
170         mDragScale = dragScale;
171         return this;
172     }
173 
getDragScale()174     public float getDragScale() {
175         return mDragScale;
176     }
177 
178     /**
179      * This sets the threshold before the animation is kicked off.
180      * It is important when have multi state animations the have some play before the
181      * System decides which animation to jump on.
182      */
setDragThreshold(int dragThreshold)183     public OnSwipe setDragThreshold(int dragThreshold) {
184         mDragThreshold = dragThreshold;
185         return this;
186     }
187 
getDragThreshold()188     public float getDragThreshold() {
189         return mDragThreshold;
190     }
191 
192 
193     /**
194      * Configures what happens when the user releases on mouse up.
195      * One of: ON_UP_AUTOCOMPLETE, ON_UP_AUTOCOMPLETE_TO_START, ON_UP_AUTOCOMPLETE_TO_END,
196      * ON_UP_STOP, ON_UP_DECELERATE, ON_UP_DECELERATE_AND_COMPLETE
197      *
198      * @param mode default = ON_UP_AUTOCOMPLETE
199      */
setOnTouchUp(TouchUp mode)200     public OnSwipe setOnTouchUp(TouchUp mode) {
201         mOnTouchUp = mode;
202         return this;
203     }
204 
getOnTouchUp()205     public TouchUp getOnTouchUp() {
206         return mOnTouchUp;
207     }
208 
209     /**
210      * Only allow touch actions to be initiated within this region
211      */
setLimitBoundsTo(String id)212     public OnSwipe setLimitBoundsTo(String id) {
213         mLimitBoundsTo = id;
214         return this;
215     }
216 
getLimitBoundsTo()217     public String getLimitBoundsTo() {
218         return mLimitBoundsTo;
219     }
220 
221     /**
222      * The view to center the rotation about
223      *
224      * @return this
225      */
setRotateCenter(String rotationCenterId)226     public OnSwipe setRotateCenter(String rotationCenterId) {
227         mRotationCenterId = rotationCenterId;
228         return this;
229     }
230 
getRotationCenterId()231     public String getRotationCenterId() {
232         return mRotationCenterId;
233     }
234 
235 
getSpringDamping()236     public float getSpringDamping() {
237         return mSpringDamping;
238     }
239 
240     /**
241      * Set the damping of the spring if using spring.
242      * c in "a = (-k*x-c*v)/m" equation for the acceleration of a spring
243      *
244      * @return this
245      */
setSpringDamping(float springDamping)246     public OnSwipe setSpringDamping(float springDamping) {
247         mSpringDamping = springDamping;
248         return this;
249     }
250 
251     /**
252      * Get the mass of the spring.
253      * the m in "a = (-k*x-c*v)/m" equation for the acceleration of a spring
254      */
getSpringMass()255     public float getSpringMass() {
256         return mSpringMass;
257     }
258 
259     /**
260      * Set the Mass of the spring if using spring.
261      * m in "a = (-k*x-c*v)/m" equation for the acceleration of a spring
262      *
263      * @return this
264      */
setSpringMass(float springMass)265     public OnSwipe setSpringMass(float springMass) {
266         mSpringMass = springMass;
267         return this;
268     }
269 
270     /**
271      * get the stiffness of the spring
272      *
273      * @return NaN if not set
274      */
getSpringStiffness()275     public float getSpringStiffness() {
276         return mSpringStiffness;
277     }
278 
279     /**
280      * set the stiffness of the spring if using spring.
281      * If this is set the swipe will use a spring return system.
282      * If set to NaN it will revert to the norm system.
283      * K in "a = (-k*x-c*v)/m" equation for the acceleration of a spring
284      */
setSpringStiffness(float springStiffness)285     public OnSwipe setSpringStiffness(float springStiffness) {
286         mSpringStiffness = springStiffness;
287         return this;
288     }
289 
290     /**
291      * The threshold for spring motion to stop.
292      */
getSpringStopThreshold()293     public float getSpringStopThreshold() {
294         return mSpringStopThreshold;
295     }
296 
297     /**
298      * set the threshold for spring motion to stop.
299      * This is in change in progress / second
300      * If the spring will never go above that threshold again it will stop.
301      *
302      * @param springStopThreshold when to stop.
303      */
setSpringStopThreshold(float springStopThreshold)304     public OnSwipe setSpringStopThreshold(float springStopThreshold) {
305         mSpringStopThreshold = springStopThreshold;
306         return this;
307     }
308 
309     /**
310      * The behaviour at the boundaries 0 and 1
311      */
getSpringBoundary()312     public Boundary getSpringBoundary() {
313         return mSpringBoundary;
314     }
315 
316     /**
317      * The behaviour at the boundaries 0 and 1.
318      *
319      * @param springBoundary behaviour at the boundaries
320      */
setSpringBoundary(Boundary springBoundary)321     public OnSwipe setSpringBoundary(Boundary springBoundary) {
322         mSpringBoundary = springBoundary;
323         return this;
324     }
325 
getAutoCompleteMode()326     public Mode getAutoCompleteMode() {
327         return mAutoCompleteMode;
328     }
329 
330 
331     /**
332      * sets the behaviour at the boundaries 0 and 1
333      * COMPLETE_MODE_CONTINUOUS_VELOCITY = 0;
334      * COMPLETE_MODE_SPRING = 1;
335      */
setAutoCompleteMode(Mode autoCompleteMode)336     public void setAutoCompleteMode(Mode autoCompleteMode) {
337         mAutoCompleteMode = autoCompleteMode;
338     }
339 
340     @Override
toString()341     public String toString() {
342         StringBuilder ret = new StringBuilder();
343         ret.append("OnSwipe:{\n");
344         if (mTouchAnchorId != null) {
345             ret.append("anchor:'").append(mTouchAnchorId).append("',\n");
346         }
347         if (mDragDirection != null) {
348             ret.append("direction:'").append(mDragDirection.toString().toLowerCase()).append(
349                     "',\n");
350         }
351         if (mTouchAnchorSide != null) {
352             ret.append("side:'").append(mTouchAnchorSide.toString().toLowerCase()).append("',\n");
353         }
354         if (!Float.isNaN(mDragScale)) {
355             ret.append("scale:'").append(mDragScale).append("',\n");
356         }
357         if (!Float.isNaN(mDragThreshold)) {
358             ret.append("threshold:'").append(mDragThreshold).append("',\n");
359         }
360         if (!Float.isNaN(mMaxVelocity)) {
361             ret.append("maxVelocity:'").append(mMaxVelocity).append("',\n");
362         }
363         if (!Float.isNaN(mMaxAcceleration)) {
364             ret.append("maxAccel:'").append(mMaxAcceleration).append("',\n");
365         }
366         if (mLimitBoundsTo != null) {
367             ret.append("limitBounds:'").append(mLimitBoundsTo).append("',\n");
368         }
369         if (mAutoCompleteMode != null) {
370             ret.append("mode:'").append(mAutoCompleteMode.toString().toLowerCase()).append("',\n");
371         }
372         if (mOnTouchUp != null) {
373             ret.append("touchUp:'").append(mOnTouchUp.toString().toLowerCase()).append("',\n");
374         }
375         if (!Float.isNaN(mSpringMass)) {
376             ret.append("springMass:'").append(mSpringMass).append("',\n");
377         }
378 
379         if (!Float.isNaN(mSpringStiffness)) {
380             ret.append("springStiffness:'").append(mSpringStiffness).append("',\n");
381         }
382         if (!Float.isNaN(mSpringDamping)) {
383             ret.append("springDamping:'").append(mSpringDamping).append("',\n");
384         }
385         if (!Float.isNaN(mSpringStopThreshold)) {
386             ret.append("stopThreshold:'").append(mSpringStopThreshold).append("',\n");
387         }
388         if (mSpringBoundary != null) {
389             ret.append("springBoundary:'").append(mSpringBoundary).append("',\n");
390         }
391         if (mRotationCenterId != null) {
392             ret.append("around:'").append(mRotationCenterId).append("',\n");
393         }
394 
395         ret.append("},\n");
396 
397         return ret.toString();
398     }
399 }
400