@@ -42,12 +42,19 @@ class EditPerspectiveImageView @JvmOverloads constructor(
4242
4343 private val trackedOldPosition = PointF ()
4444
45+ // Point edit or first point of line edit
4546 private var trackedPoint: PointF ? = null
4647 private var trackedViewPoint = PointF ()
4748 private var trackedAllowedRect = RectF ()
4849 private var trackedMovedAlongLine: LineF ? = null
4950 private var trackedMovedAlongLineHorizontal = true
5051
52+ // Second point of line edit
53+ private var trackedPoint2: PointF ? = null
54+ private var trackedViewPoint2 = PointF ()
55+ private var trackedAllowedRect2 = RectF ()
56+ private var trackedMovedAlongLine2: LineF ? = null
57+
5158 private val paint = Paint ()
5259 private var onPerspectiveChanged: (()-> Unit )? = null
5360 private var onEditStart: (()-> Unit )? = null
@@ -158,10 +165,26 @@ class EditPerspectiveImageView @JvmOverloads constructor(
158165 paint.style = Paint .Style .FILL_AND_STROKE
159166 paint.color = Color .argb( 128 , 0 , 0 , 255 )
160167
161- drawPoint( viewPerspective.pointLeftTop, canvas, paint, perspectivePoints.pointLeftTop == trackedPoint )
162- drawPoint( viewPerspective.pointLeftBottom, canvas, paint, perspectivePoints.pointLeftBottom == trackedPoint )
163- drawPoint( viewPerspective.pointRightTop, canvas, paint, perspectivePoints.pointRightTop == trackedPoint )
164- drawPoint( viewPerspective.pointRightBottom, canvas, paint, perspectivePoints.pointRightBottom == trackedPoint )
168+ drawPoint(
169+ viewPerspective.pointLeftTop,
170+ canvas,
171+ paint,
172+ perspectivePoints.pointLeftTop == trackedPoint || perspectivePoints.pointLeftTop == trackedPoint2)
173+ drawPoint(
174+ viewPerspective.pointLeftBottom,
175+ canvas,
176+ paint,
177+ perspectivePoints.pointLeftBottom == trackedPoint || perspectivePoints.pointLeftBottom == trackedPoint2)
178+ drawPoint(
179+ viewPerspective.pointRightTop,
180+ canvas,
181+ paint,
182+ perspectivePoints.pointRightTop == trackedPoint || perspectivePoints.pointRightTop == trackedPoint2)
183+ drawPoint(
184+ viewPerspective.pointRightBottom,
185+ canvas,
186+ paint,
187+ perspectivePoints.pointRightBottom == trackedPoint || perspectivePoints.pointRightBottom == trackedPoint2)
165188 }
166189
167190 private fun distance ( pointA : PointF , pointB : PointF ): Float =
@@ -172,13 +195,26 @@ class EditPerspectiveImageView @JvmOverloads constructor(
172195 trackedViewPoint : PointF ,
173196 allowedRect : RectF ,
174197 moveAlongLine : LineF ? = null,
175- lineIsHorizontal : Boolean = true
198+ lineIsHorizontal : Boolean = true,
199+ trackedPoint2 : PointF ? = null,
200+ trackedViewPoint2 : PointF ? = null,
201+ allowedRect2 : RectF ? = null,
202+ moveAlongLine2 : LineF ? = null
176203 ) {
177204 this .trackedPoint = trackedPoint
178205 this .trackedViewPoint.set( trackedViewPoint )
179206 this .trackedAllowedRect.set( allowedRect )
180207 this .trackedMovedAlongLine = moveAlongLine
181208 this .trackedMovedAlongLineHorizontal = lineIsHorizontal
209+
210+ if (null != trackedPoint2 && null != trackedViewPoint2 && null != allowedRect2) {
211+ this .trackedPoint2 = trackedPoint2
212+ this .trackedViewPoint2.set( trackedViewPoint2 )
213+ this .trackedAllowedRect2.set( allowedRect2 )
214+ this .trackedMovedAlongLine2 = moveAlongLine2
215+ } else {
216+ this .trackedPoint2 = null
217+ }
182218 }
183219
184220 private fun calculateNewViewPoint (
@@ -215,104 +251,195 @@ class EditPerspectiveImageView @JvmOverloads constructor(
215251 )
216252 }
217253
218- override fun onTouchEvent (event : MotionEvent ? ): Boolean {
219- if (null == event) return true
220- val bitmap = super .getBitmap() ? : return true
254+ private fun handleActionDown ( event : MotionEvent , bitmap : Bitmap ): Boolean {
255+ if (null != trackedPoint) return true
221256
222- when ( event.action ) {
223- MotionEvent .ACTION_DOWN -> {
224- if (null == trackedPoint) {
225- transform.set(bitmap.width, bitmap.height, viewRect)
226-
227- val screenPoint = PointF (event.x, event.y)
228- val viewPerspective = transform.mapToView(perspectivePoints)
229- val minDistance = dpToPixels(MIN_POINT_DISTANCE_TO_TRACK )
230-
231- trackedOldPosition.set(event.x, event.y)
232-
233- when {
234- distance(viewPerspective.pointLeftTop, screenPoint) < minDistance -> {
235- startEdit(
236- perspectivePoints.pointLeftTop,
237- viewPerspective.pointLeftTop,
238- viewPerspective.safeRectLeftTop(),
239- getMoveAlongLine( viewPerspective.pointLeftTop, viewPerspective.pointRightTop, viewPerspective.pointLeftBottom ),
240- pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
241- )
242- }
243-
244- distance(viewPerspective.pointLeftBottom, screenPoint) < minDistance -> {
245- startEdit(
246- perspectivePoints.pointLeftBottom,
247- viewPerspective.pointLeftBottom,
248- viewPerspective.safeRectLeftBottom(),
249- getMoveAlongLine( viewPerspective.pointLeftBottom, viewPerspective.pointRightBottom, viewPerspective.pointLeftTop ),
250- pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
251- )
252- }
253-
254- distance(viewPerspective.pointRightTop, screenPoint) < minDistance -> {
255- startEdit(
256- perspectivePoints.pointRightTop,
257- viewPerspective.pointRightTop,
258- viewPerspective.safeRectRightTop(),
259- getMoveAlongLine( viewPerspective.pointRightTop, viewPerspective.pointLeftTop, viewPerspective.pointRightBottom ),
260- pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
261- )
262- }
263-
264- distance(viewPerspective.pointRightBottom, screenPoint) < minDistance -> {
265- startEdit(
266- perspectivePoints.pointRightBottom,
267- viewPerspective.pointRightBottom,
268- viewPerspective.safeRectRightBottom(),
269- getMoveAlongLine( viewPerspective.pointRightBottom, viewPerspective.pointLeftBottom, viewPerspective.pointRightTop ),
270- pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
271- )
272- }
273- }
274-
275- if (null != trackedPoint) onEditStart?.invoke()
276- }
257+ transform.set(bitmap.width, bitmap.height, viewRect)
258+
259+ val screenPoint = PointF (event.x, event.y)
260+ val viewPerspective = transform.mapToView(perspectivePoints)
261+ val minDistance = dpToPixels(MIN_POINT_DISTANCE_TO_TRACK )
262+ val allowEditLineHorizontal = POINT_EDIT_DIRECTION_ALL == pointEditDirection || POINT_EDIT_DIRECTION_HORIZONTAL == pointEditDirection
263+ val allowEditLineVertical = POINT_EDIT_DIRECTION_ALL == pointEditDirection || POINT_EDIT_DIRECTION_VERTICAL == pointEditDirection
264+
265+ trackedOldPosition.set(event.x, event.y)
266+
267+ when {
268+ distance(viewPerspective.pointLeftTop, screenPoint) < minDistance -> {
269+ startEdit(
270+ perspectivePoints.pointLeftTop,
271+ viewPerspective.pointLeftTop,
272+ viewPerspective.safeRectLeftTop(),
273+ getMoveAlongLine( viewPerspective.pointLeftTop, viewPerspective.pointRightTop, viewPerspective.pointLeftBottom ),
274+ pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
275+ )
277276 }
278277
279- MotionEvent .ACTION_MOVE -> {
280- val trackedPoint = this .trackedPoint
278+ distance(viewPerspective.pointLeftBottom, screenPoint) < minDistance -> {
279+ startEdit(
280+ perspectivePoints.pointLeftBottom,
281+ viewPerspective.pointLeftBottom,
282+ viewPerspective.safeRectLeftBottom(),
283+ getMoveAlongLine( viewPerspective.pointLeftBottom, viewPerspective.pointRightBottom, viewPerspective.pointLeftTop ),
284+ pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
285+ )
286+ }
281287
282- if (null != trackedPoint) {
283- transform.set(bitmap.width, bitmap.height, viewRect)
288+ distance(viewPerspective.pointRightTop, screenPoint) < minDistance -> {
289+ startEdit(
290+ perspectivePoints.pointRightTop,
291+ viewPerspective.pointRightTop,
292+ viewPerspective.safeRectRightTop(),
293+ getMoveAlongLine( viewPerspective.pointRightTop, viewPerspective.pointLeftTop, viewPerspective.pointRightBottom ),
294+ pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
295+ )
296+ }
284297
285- val newTrackedViewPoint = calculateNewViewPoint(
286- event.x - trackedOldPosition.x,
287- event.y - trackedOldPosition.y,
288- trackedViewPoint,
289- trackedAllowedRect,
290- trackedMovedAlongLine,
291- trackedMovedAlongLineHorizontal
292- )
298+ distance(viewPerspective.pointRightBottom, screenPoint) < minDistance -> {
299+ startEdit(
300+ perspectivePoints.pointRightBottom,
301+ viewPerspective.pointRightBottom,
302+ viewPerspective.safeRectRightBottom(),
303+ getMoveAlongLine( viewPerspective.pointRightBottom, viewPerspective.pointLeftBottom, viewPerspective.pointRightTop ),
304+ pointEditDirection == POINT_EDIT_DIRECTION_HORIZONTAL
305+ )
306+ }
293307
294- trackedOldPosition.set(event.x, event.y)
308+ allowEditLineVertical && viewPerspective.lineTop.distanceFrom(screenPoint) < minDistance -> {
309+ startEdit(
310+ perspectivePoints.lineTop.from,
311+ viewPerspective.lineTop.from,
312+ viewPerspective.safeRectLeftTop(),
313+ viewPerspective.lineLeft.clone(),
314+ false ,
315+ perspectivePoints.lineTop.to,
316+ viewPerspective.lineTop.to,
317+ viewPerspective.safeRectRightTop(),
318+ viewPerspective.lineRight.clone()
319+ )
320+ }
295321
296- if (null != newTrackedViewPoint) {
297- trackedViewPoint.set(newTrackedViewPoint)
298- trackedPoint.set(transform.mapToBitmap(trackedViewPoint))
299- invalidate()
300- onPerspectiveChanged?.invoke()
301- }
322+ allowEditLineVertical && viewPerspective.lineBottom.distanceFrom(screenPoint) < minDistance -> {
323+ startEdit(
324+ perspectivePoints.lineBottom.from,
325+ viewPerspective.lineBottom.from,
326+ viewPerspective.safeRectLeftBottom(),
327+ viewPerspective.lineLeft.clone(),
328+ false ,
329+ perspectivePoints.lineBottom.to,
330+ viewPerspective.lineBottom.to,
331+ viewPerspective.safeRectRightBottom(),
332+ viewPerspective.lineRight.clone()
333+ )
334+ }
302335
303- return true
304- }
336+ allowEditLineHorizontal && viewPerspective.lineLeft.distanceFrom(screenPoint) < minDistance -> {
337+ startEdit(
338+ perspectivePoints.lineLeft.from,
339+ viewPerspective.lineLeft.from,
340+ viewPerspective.safeRectLeftTop(),
341+ viewPerspective.lineTop.clone(),
342+ true ,
343+ perspectivePoints.lineLeft.to,
344+ viewPerspective.lineLeft.to,
345+ viewPerspective.safeRectLeftBottom(),
346+ viewPerspective.lineBottom.clone()
347+ )
305348 }
306349
307- MotionEvent .ACTION_UP -> {
308- if (null != trackedPoint) {
309- trackedPoint = null
310- onEditEnd?.invoke()
311- return true
312- }
350+ allowEditLineHorizontal && viewPerspective.lineRight.distanceFrom(screenPoint) < minDistance -> {
351+ startEdit(
352+ perspectivePoints.lineRight.from,
353+ viewPerspective.lineRight.from,
354+ viewPerspective.safeRectRightTop(),
355+ viewPerspective.lineTop.clone(),
356+ true ,
357+ perspectivePoints.lineRight.to,
358+ viewPerspective.lineRight.to,
359+ viewPerspective.safeRectRightBottom(),
360+ viewPerspective.lineBottom.clone()
361+ )
313362 }
314363 }
315364
365+ if (null != trackedPoint) {
366+ onEditStart?.invoke()
367+ return true
368+ }
369+
370+ return false
371+ }
372+
373+ private fun handleActionMove (event : MotionEvent , bitmap : Bitmap ): Boolean {
374+ val trackedPoint = this .trackedPoint ? : return false
375+
376+ transform.set(bitmap.width, bitmap.height, viewRect)
377+
378+ val dx = event.x - trackedOldPosition.x
379+ val dy = event.y - trackedOldPosition.y
380+
381+ trackedOldPosition.set(event.x, event.y)
382+
383+ Log .i(" [PERSPECTIVE]" , " dx: $dx , dy: $dy " )
384+
385+ if (dx > 2 ) {
386+ trackedOldPosition.set(event.x, event.y)
387+ }
388+
389+ val newTrackedViewPoint = calculateNewViewPoint(
390+ dx,
391+ dy,
392+ trackedViewPoint,
393+ trackedAllowedRect,
394+ trackedMovedAlongLine,
395+ trackedMovedAlongLineHorizontal
396+ ) ? : return true
397+
398+ val trackedPoint2 = this .trackedPoint2
399+ if (null != trackedPoint2) {
400+ val newTrackedViewPoint2 = calculateNewViewPoint(
401+ dx,
402+ dy,
403+ trackedViewPoint2,
404+ trackedAllowedRect2,
405+ trackedMovedAlongLine2,
406+ trackedMovedAlongLineHorizontal
407+ ) ? : return true
408+
409+ trackedViewPoint2.set(newTrackedViewPoint2)
410+ trackedPoint2.set(transform.mapToBitmap(trackedViewPoint2))
411+ }
412+
413+ trackedViewPoint.set(newTrackedViewPoint)
414+ trackedPoint.set(transform.mapToBitmap(trackedViewPoint))
415+
416+ invalidate()
417+ onPerspectiveChanged?.invoke()
418+
419+ return true
420+ }
421+
422+ private fun handleActionUp (): Boolean {
423+ if (null != trackedPoint) {
424+ trackedPoint = null
425+ trackedPoint2 = null
426+ onEditEnd?.invoke()
427+ return true
428+ }
429+
430+ return false
431+ }
432+
433+ override fun onTouchEvent (event : MotionEvent ? ): Boolean {
434+ if (null == event) return true
435+ val bitmap = super .getBitmap() ? : return true
436+
437+ when ( event.action ) {
438+ MotionEvent .ACTION_DOWN -> if (handleActionDown(event, bitmap)) return true
439+ MotionEvent .ACTION_MOVE -> if (handleActionMove(event, bitmap)) return true
440+ MotionEvent .ACTION_UP -> if (handleActionUp()) return true
441+ }
442+
316443 if (null != trackedPoint) {
317444 Log .i(" EDIT" , " Track is ON" )
318445 return true
0 commit comments