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 ) {
15 
16     fun calculatePosition(
17         currentRotation: Int,
18         taskbarVisible: Boolean,
19         taskbarStashed: Boolean
20     ): Position {
21 
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         when (rotation) {
59             Surface.ROTATION_0 -> Gravity.BOTTOM or Gravity.LEFT
60             Surface.ROTATION_90 -> Gravity.BOTTOM or Gravity.RIGHT
61             Surface.ROTATION_180 -> Gravity.TOP or Gravity.RIGHT
62             Surface.ROTATION_270 -> Gravity.TOP or Gravity.LEFT
63             else -> throw IllegalArgumentException("Invalid rotation $rotation")
64         }
65 }
66