fix #162 - place new widgets in free area if possible

This commit is contained in:
Josia Pietsch 2025-05-12 16:33:59 +02:00
parent 30e9fcd20f
commit 33ccea8cbc
Signed by: jrpie
GPG key ID: E70B571D66986A2D
2 changed files with 60 additions and 15 deletions

View file

@ -17,9 +17,12 @@ import de.jrpie.android.launcher.databinding.ActivityManageWidgetsBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.UIObject
import de.jrpie.android.launcher.widgets.AppWidget
import de.jrpie.android.launcher.widgets.GRID_SIZE
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
// http://coderender.blogspot.com/2012/01/hosting-android-widgets-my.html
@ -143,14 +146,12 @@ class ManageWidgetsActivity : UIObject, Activity() {
val display = windowManager.defaultDisplay
val position = WidgetPosition.fromAbsoluteRect(
Rect(
0, 0,
min(400, appWidgetManager.getAppWidgetInfo(appWidgetId).minWidth),
min(400, appWidgetManager.getAppWidgetInfo(appWidgetId).minHeight)
),
display.width,
display.height
val widgetInfo = appWidgetManager.getAppWidgetInfo(appWidgetId)
val position = WidgetPosition.findFreeSpace(
WidgetPanel.byId(panelId),
max(3, (GRID_SIZE * (widgetInfo.minWidth) / display.width.toFloat()).roundToInt()),
max(3, (GRID_SIZE * (widgetInfo.minHeight) / display.height.toFloat()).roundToInt())
)
val widget = AppWidget(appWidgetId, position, panelId, provider)

View file

@ -11,9 +11,20 @@ const val GRID_SIZE: Short = 12
@Serializable
data class WidgetPosition(var x: Short, var y: Short, var width: Short, var height: Short) {
constructor(rect: Rect) : this(
rect.left.toShort(),
rect.top.toShort(),
(rect.right - rect.left).toShort(),
(rect.bottom - rect.top).toShort()
)
fun toRect(): Rect {
return Rect(x.toInt(), y.toInt(), x + width, y + height)
}
fun getAbsoluteRect(screenWidth: Int, screenHeight: Int): Rect {
val gridWidth = screenWidth / GRID_SIZE.toFloat()
val gridHeight= screenHeight / GRID_SIZE.toFloat()
val gridHeight = screenHeight / GRID_SIZE.toFloat()
return Rect(
(x * gridWidth).toInt(),
@ -23,25 +34,33 @@ data class WidgetPosition(var x: Short, var y: Short, var width: Short, var heig
)
}
companion object {
fun fromAbsoluteRect(absolute: Rect, screenWidth: Int, screenHeight: Int): WidgetPosition {
val gridWidth = screenWidth / GRID_SIZE.toFloat()
val gridHeight= screenHeight / GRID_SIZE.toFloat()
val gridHeight = screenHeight / GRID_SIZE.toFloat()
val x = (absolute.left / gridWidth).roundToInt().toShort().coerceIn(0, (GRID_SIZE-1).toShort())
val y = (absolute.top / gridHeight).roundToInt().toShort().coerceIn(0, (GRID_SIZE-1).toShort())
val x = (absolute.left / gridWidth).roundToInt().toShort()
.coerceIn(0, (GRID_SIZE - 1).toShort())
val y = (absolute.top / gridHeight).roundToInt().toShort()
.coerceIn(0, (GRID_SIZE - 1).toShort())
val w = max(2, ((absolute.right - absolute.left) / gridWidth).roundToInt()).toShort()
val h = max(2, ((absolute.bottom - absolute.top) / gridHeight).roundToInt()).toShort()
return WidgetPosition(x,y,w,h)
return WidgetPosition(x, y, w, h)
}
fun center(minWidth: Int, minHeight: Int, screenWidth: Int, screenHeight: Int): WidgetPosition {
fun center(
minWidth: Int,
minHeight: Int,
screenWidth: Int,
screenHeight: Int
): WidgetPosition {
val gridWidth = screenWidth / GRID_SIZE.toFloat()
val gridHeight= screenHeight / GRID_SIZE.toFloat()
val gridHeight = screenHeight / GRID_SIZE.toFloat()
val cellsWidth = ceil(minWidth / gridWidth).toInt().toShort()
val cellsHeight = ceil(minHeight / gridHeight).toInt().toShort()
@ -52,7 +71,32 @@ data class WidgetPosition(var x: Short, var y: Short, var width: Short, var heig
cellsWidth,
cellsHeight
)
}
fun findFreeSpace(
widgetPanel: WidgetPanel?,
minWidth: Int,
minHeight: Int
): WidgetPosition {
val rect = Rect(0, 0, minWidth, minHeight)
if (widgetPanel == null) {
return WidgetPosition(rect)
}
val widgets = widgetPanel.getWidgets().map { it.position.toRect() }
for (x in 0..<GRID_SIZE - minWidth) {
rect.left = x
rect.right = x + minWidth
for (y in 0..<GRID_SIZE - minHeight) {
rect.top = y
rect.bottom = y + minHeight
if (!widgets.any { Rect(it).intersect(rect) }) {
return WidgetPosition(rect)
}
}
}
return WidgetPosition(0, 0, minWidth.toShort(), minHeight.toShort())
}
}
}