1 package com.android.systemui.shared.rotation
2 
3 import android.view.Gravity
4 import android.view.Surface
5 
6 /**
7  * Calculates gravity and translation that is necessary to display
8  * the button in the correct position based on the current state
9  */
10 class FloatingRotationButtonPositionCalculator(
11     private val defaultMargin: Int,
12     private val taskbarMarginLeft: Int,
13     private val taskbarMarginBottom: Int,
14     private val floatingRotationButtonPositionLeft: Boolean
15 ) {
16 
17     fun calculatePosition(
18         currentRotation: Int,
19         taskbarVisible: Boolean,
20         taskbarStashed: Boolean
21     ): Position {
22         val isTaskbarSide = currentRotation == Surface.ROTATION_0
23             || currentRotation == Surface.ROTATION_90
24         val useTaskbarMargin = isTaskbarSide && taskbarVisible && !taskbarStashed
25 
26         val gravity = resolveGravity(currentRotation)
27 
28         val marginLeft = if (useTaskbarMargin) taskbarMarginLeft else defaultMargin
29         val marginBottom = if (useTaskbarMargin) taskbarMarginBottom else defaultMargin
30 
31         val translationX =
32             if (gravity and Gravity.RIGHT == Gravity.RIGHT) {
33                 -marginLeft
34             } else {
35                 marginLeft
36             }
37         val translationY =
38             if (gravity and Gravity.BOTTOM == Gravity.BOTTOM) {
39                 -marginBottom
40             } else {
41                 marginBottom
42             }
43 
44         return Position(
45             gravity = gravity,
46             translationX = translationX,
47             translationY = translationY
48         )
49     }
50 
51     data class Position(
52         val gravity: Int,
53         val translationX: Int,
54         val translationY: Int
55     )
56 
57     private fun resolveGravity(rotation: Int): Int =
58         if (floatingRotationButtonPositionLeft) {
59             when (rotation) {
60                 Surface.ROTATION_0 -> Gravity.BOTTOM or Gravity.LEFT
61                 Surface.ROTATION_90 -> Gravity.BOTTOM or Gravity.RIGHT
62                 Surface.ROTATION_180 -> Gravity.TOP or Gravity.RIGHT
63                 Surface.ROTATION_270 -> Gravity.TOP or Gravity.LEFT
64                 else -> throw IllegalArgumentException("Invalid rotation $rotation")
65             }
66         } else {
67             when (rotation) {
68                 Surface.ROTATION_0 -> Gravity.BOTTOM or Gravity.RIGHT
69                 Surface.ROTATION_90 -> Gravity.TOP or Gravity.RIGHT
70                 Surface.ROTATION_180 -> Gravity.TOP or Gravity.LEFT
71                 Surface.ROTATION_270 -> Gravity.BOTTOM or Gravity.LEFT
72                 else -> throw IllegalArgumentException("Invalid rotation $rotation")
73             }
74         }
75 }
76