mirror of
https://github.com/SimpleMobileTools/Simple-Launcher.git
synced 2025-04-03 12:51:25 +02:00
Handle moving items inside a folder
This commit is contained in:
parent
10603be76b
commit
62686f48c3
@ -44,8 +44,8 @@ interface HomeScreenGridItemsDao {
|
|||||||
@Query("DELETE FROM home_screen_grid_items WHERE parent_id IN (SELECT id FROM home_screen_grid_items WHERE package_name = :packageName)")
|
@Query("DELETE FROM home_screen_grid_items WHERE parent_id IN (SELECT id FROM home_screen_grid_items WHERE package_name = :packageName)")
|
||||||
fun deleteItemsByParentPackageName(packageName: String)
|
fun deleteItemsByParentPackageName(packageName: String)
|
||||||
|
|
||||||
@Query("UPDATE home_screen_grid_items SET `left` = `left` + :shiftBy WHERE parent_id == :folderId AND `left` >= :shiftFrom")
|
@Query("UPDATE home_screen_grid_items SET `left` = `left` + :shiftBy WHERE parent_id == :folderId AND `left` > :shiftFrom AND id != :excludingId")
|
||||||
fun shiftFolderItems(folderId: Long, shiftFrom: Int, shiftBy: Int)
|
fun shiftFolderItems(folderId: Long, shiftFrom: Int, shiftBy: Int, excludingId: Long)
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
fun deleteByPackageName(packageName: String) {
|
fun deleteByPackageName(packageName: String) {
|
||||||
|
@ -250,6 +250,11 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
|
|
||||||
fun itemDraggingStarted(draggedGridItem: HomeScreenGridItem) {
|
fun itemDraggingStarted(draggedGridItem: HomeScreenGridItem) {
|
||||||
draggedItem = draggedGridItem
|
draggedItem = draggedGridItem
|
||||||
|
|
||||||
|
if (draggedGridItem.type == ITEM_TYPE_WIDGET) {
|
||||||
|
closeFolder()
|
||||||
|
}
|
||||||
|
|
||||||
if (draggedItem!!.drawable == null) {
|
if (draggedItem!!.drawable == null) {
|
||||||
if (draggedItem?.type == ITEM_TYPE_FOLDER) {
|
if (draggedItem?.type == ITEM_TYPE_FOLDER) {
|
||||||
draggedItem!!.drawable =
|
draggedItem!!.drawable =
|
||||||
@ -424,6 +429,10 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
// check if the destination cell is empty
|
// check if the destination cell is empty
|
||||||
var isDroppingPositionValid = true
|
var isDroppingPositionValid = true
|
||||||
val wantedCell = Pair(xIndex, yIndex)
|
val wantedCell = Pair(xIndex, yIndex)
|
||||||
|
// No moving folder into the dock
|
||||||
|
if (draggedHomeGridItem?.type == ITEM_TYPE_FOLDER && yIndex == rowCount - 1) {
|
||||||
|
isDroppingPositionValid = false
|
||||||
|
} else {
|
||||||
gridItems.filterVisibleOnly().forEach { item ->
|
gridItems.filterVisibleOnly().forEach { item ->
|
||||||
for (xCell in item.left..item.right) {
|
for (xCell in item.left..item.right) {
|
||||||
for (yCell in item.getDockAdjustedTop(rowCount)..item.getDockAdjustedBottom(rowCount)) {
|
for (yCell in item.getDockAdjustedTop(rowCount)..item.getDockAdjustedBottom(rowCount)) {
|
||||||
@ -436,6 +445,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isDroppingPositionValid) {
|
if (isDroppingPositionValid) {
|
||||||
draggedHomeGridItem?.apply {
|
draggedHomeGridItem?.apply {
|
||||||
@ -462,19 +472,38 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addAppIconOrShortcut() {
|
private fun addAppIconOrShortcut() {
|
||||||
|
var isDroppingPositionValid: Boolean = false
|
||||||
|
var potentialParent: HomeScreenGridItem? = null
|
||||||
|
var xIndex: Int? = null
|
||||||
|
var yIndex: Int? = null
|
||||||
|
var redrawIcons = false
|
||||||
|
|
||||||
|
val folder = currentlyOpenFolder
|
||||||
|
if (folder != null && folder.getFolderItemsRect().contains(
|
||||||
|
(sideMargins.left + draggedItemCurrentCoords.first).toFloat(),
|
||||||
|
(sideMargins.top + draggedItemCurrentCoords.second).toFloat()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
val center = folder.getFolderGridCenters().minBy {
|
||||||
|
abs(it.second - draggedItemCurrentCoords.first + sideMargins.left) + abs(it.third - draggedItemCurrentCoords.second + sideMargins.top)
|
||||||
|
}
|
||||||
|
isDroppingPositionValid = true
|
||||||
|
potentialParent = folder
|
||||||
|
xIndex = center.first
|
||||||
|
yIndex = 0
|
||||||
|
redrawIcons = true
|
||||||
|
} else {
|
||||||
val center = gridCenters.minBy {
|
val center = gridCenters.minBy {
|
||||||
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
||||||
}
|
}
|
||||||
|
|
||||||
var redrawIcons = false
|
|
||||||
val gridCells = getClosestGridCells(center)
|
val gridCells = getClosestGridCells(center)
|
||||||
if (gridCells != null) {
|
if (gridCells != null) {
|
||||||
val xIndex = gridCells.first
|
xIndex = gridCells.first
|
||||||
val yIndex = gridCells.second
|
yIndex = gridCells.second
|
||||||
|
|
||||||
// check if the destination cell is empty or a folder
|
// check if the destination cell is empty or a folder
|
||||||
var isDroppingPositionValid = true
|
isDroppingPositionValid = true
|
||||||
var potentialParent: HomeScreenGridItem? = null
|
|
||||||
val wantedCell = Pair(xIndex, yIndex)
|
val wantedCell = Pair(xIndex, yIndex)
|
||||||
gridItems.filterVisibleOnly().forEach { item ->
|
gridItems.filterVisibleOnly().forEach { item ->
|
||||||
for (xCell in item.left..item.right) {
|
for (xCell in item.left..item.right) {
|
||||||
@ -482,7 +511,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
val cell = Pair(xCell, yCell)
|
val cell = Pair(xCell, yCell)
|
||||||
val isAnyCellOccupied = wantedCell == cell
|
val isAnyCellOccupied = wantedCell == cell
|
||||||
if (isAnyCellOccupied) {
|
if (isAnyCellOccupied) {
|
||||||
if (item.type != ITEM_TYPE_WIDGET) {
|
if (item.type != ITEM_TYPE_WIDGET && !item.docked) {
|
||||||
potentialParent = item
|
potentialParent = item
|
||||||
} else {
|
} else {
|
||||||
isDroppingPositionValid = false
|
isDroppingPositionValid = false
|
||||||
@ -492,13 +521,15 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isDroppingPositionValid) {
|
if (isDroppingPositionValid) {
|
||||||
val draggedHomeGridItem = gridItems.firstOrNull { it.id == draggedItem?.id }
|
val draggedHomeGridItem = gridItems.firstOrNull { it.id == draggedItem?.id }
|
||||||
|
|
||||||
if (potentialParent != null) {
|
if (potentialParent != null) {
|
||||||
if (potentialParent?.type == ITEM_TYPE_FOLDER) {
|
if (potentialParent?.type == ITEM_TYPE_FOLDER) {
|
||||||
addAppIconOrShortcut(draggedHomeGridItem, xIndex, yIndex, potentialParent?.id)
|
addAppIconOrShortcut(draggedHomeGridItem, xIndex!!, yIndex!!, potentialParent?.id, toFolderEnd = potentialParent != currentlyOpenFolder)
|
||||||
} else {
|
} else {
|
||||||
val parentItem = potentialParent!!.copy(
|
val parentItem = potentialParent!!.copy(
|
||||||
type = ITEM_TYPE_FOLDER,
|
type = ITEM_TYPE_FOLDER,
|
||||||
@ -515,20 +546,19 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
}
|
}
|
||||||
(context as? MainActivity)?.runOnUiThread {
|
(context as? MainActivity)?.runOnUiThread {
|
||||||
gridItems.add(parentItem)
|
gridItems.add(parentItem)
|
||||||
addAppIconOrShortcut(draggedHomeGridItem, xIndex, yIndex, newId)
|
addAppIconOrShortcut(draggedHomeGridItem, xIndex!!, yIndex!!, newId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
addAppIconOrShortcut(draggedHomeGridItem, xIndex, yIndex)
|
addAppIconOrShortcut(draggedHomeGridItem, xIndex!!, yIndex!!)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
performHapticFeedback()
|
performHapticFeedback()
|
||||||
redrawIcons = true
|
redrawIcons = true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
draggedItem = null
|
draggedItem = null
|
||||||
draggedItemCurrentCoords = Pair(-1, -1)
|
draggedItemCurrentCoords = Pair(-1, -1)
|
||||||
@ -537,12 +567,24 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addAppIconOrShortcut(draggedHomeGridItem: HomeScreenGridItem?, xIndex: Int, yIndex: Int, newParentId: Long? = null) {
|
private fun addAppIconOrShortcut(
|
||||||
|
draggedHomeGridItem: HomeScreenGridItem?,
|
||||||
|
xIndex: Int,
|
||||||
|
yIndex: Int,
|
||||||
|
newParentId: Long? = null,
|
||||||
|
toFolderEnd: Boolean = true
|
||||||
|
) {
|
||||||
val finalXIndex = if (newParentId != null) {
|
val finalXIndex = if (newParentId != null) {
|
||||||
if (newParentId == draggedHomeGridItem?.parentId) {
|
if (toFolderEnd) {
|
||||||
draggedHomeGridItem.left
|
|
||||||
} else {
|
|
||||||
gridItems.firstOrNull { it.id == newParentId }?.getFolderItems()?.maxOf { it.left + 1 } ?: 0
|
gridItems.firstOrNull { it.id == newParentId }?.getFolderItems()?.maxOf { it.left + 1 } ?: 0
|
||||||
|
} else {
|
||||||
|
min(xIndex, gridItems.firstOrNull { it.id == newParentId }?.getFolderItems()?.maxOf {
|
||||||
|
if (draggedHomeGridItem?.parentId == newParentId) {
|
||||||
|
it.left
|
||||||
|
} else {
|
||||||
|
it.left + 1
|
||||||
|
}
|
||||||
|
} ?: 0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
xIndex
|
xIndex
|
||||||
@ -572,11 +614,19 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, newParentId, id!!)
|
context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, newParentId, id!!)
|
||||||
if (deleteOldParent && oldParentId != null) {
|
if (deleteOldParent && oldParentId != null) {
|
||||||
context.homeScreenGridItemsDB.deleteById(oldParentId)
|
context.homeScreenGridItemsDB.deleteById(oldParentId)
|
||||||
} else if (oldParentId != null) {
|
} else if (oldParentId != null && gridItems.none { it.parentId == oldParentId && it.left == oldLeft }) {
|
||||||
gridItems.filter { it.parentId == oldParentId && it.left >= oldLeft }.forEach {
|
gridItems.filter { it.parentId == oldParentId && it.left > oldLeft && it.id != id }.forEach {
|
||||||
it.left -= 1
|
it.left -= 1
|
||||||
}
|
}
|
||||||
context.homeScreenGridItemsDB.shiftFolderItems(oldParentId, oldLeft, -1)
|
context.homeScreenGridItemsDB.shiftFolderItems(oldParentId, oldLeft, -1, id!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newParentId != null && gridItems.any { it.parentId == newParentId && it.left == left }) {
|
||||||
|
gridItems.filter { it.parentId == newParentId && it.left >= left && it.id != id }.forEach {
|
||||||
|
it.left += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
context.homeScreenGridItemsDB.shiftFolderItems(newParentId, left - 1, +1, id!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1024,6 +1074,21 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
|
|
||||||
if (draggedItem != null && draggedItemCurrentCoords.first != -1 && draggedItemCurrentCoords.second != -1) {
|
if (draggedItem != null && draggedItemCurrentCoords.first != -1 && draggedItemCurrentCoords.second != -1) {
|
||||||
if (draggedItem!!.type == ITEM_TYPE_ICON || draggedItem!!.type == ITEM_TYPE_SHORTCUT || draggedItem!!.type == ITEM_TYPE_FOLDER) {
|
if (draggedItem!!.type == ITEM_TYPE_ICON || draggedItem!!.type == ITEM_TYPE_SHORTCUT || draggedItem!!.type == ITEM_TYPE_FOLDER) {
|
||||||
|
if (folder != null && folder.getFolderItemsRect().contains(
|
||||||
|
(sideMargins.left + draggedItemCurrentCoords.first).toFloat(),
|
||||||
|
(sideMargins.top + draggedItemCurrentCoords.second).toFloat()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
|
||||||
|
val center = folder.getFolderGridCenters().minBy {
|
||||||
|
abs(it.second - draggedItemCurrentCoords.first + sideMargins.left) + abs(it.third - draggedItemCurrentCoords.second + sideMargins.top)
|
||||||
|
}
|
||||||
|
|
||||||
|
val shadowX = center.second - cellWidth / 2 + iconMargin + iconSize / 2f + extraXMargin
|
||||||
|
val shadowY = center.third - cellHeight / 2 + iconMargin + iconSize / 2f + extraYMargin
|
||||||
|
|
||||||
|
canvas.drawCircle(shadowX, shadowY, iconSize / 2f, dragShadowCirclePaint)
|
||||||
|
} else {
|
||||||
// draw a circle under the current cell
|
// draw a circle under the current cell
|
||||||
val center = gridCenters.minBy {
|
val center = gridCenters.minBy {
|
||||||
abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
||||||
@ -1040,6 +1105,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
|
|
||||||
canvas.drawCircle(shadowX, shadowY, iconSize / 2f, dragShadowCirclePaint)
|
canvas.drawCircle(shadowX, shadowY, iconSize / 2f, dragShadowCirclePaint)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// show the app icon itself at dragging, move it above the finger a bit to make it visible
|
// show the app icon itself at dragging, move it above the finger a bit to make it visible
|
||||||
val drawableX = (draggedItemCurrentCoords.first - iconSize / 1.5f).toInt()
|
val drawableX = (draggedItemCurrentCoords.first - iconSize / 1.5f).toInt()
|
||||||
@ -1415,6 +1481,23 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun HomeScreenGridItem.getFolderGridCenters(): List<Triple<Int, Int, Int>> {
|
||||||
|
val count = getFolderItems().count()
|
||||||
|
val columnsCount = ceil(sqrt(count.toDouble())).roundToInt()
|
||||||
|
val rowsCount = ceil(count.toFloat() / columnsCount).roundToInt()
|
||||||
|
val folderItemsRect = getFolderItemsRect()
|
||||||
|
return (0 until columnsCount * rowsCount)
|
||||||
|
.toList()
|
||||||
|
.map { Pair(it % columnsCount, it / columnsCount) }
|
||||||
|
.mapIndexed { index, (x, y) ->
|
||||||
|
Triple(
|
||||||
|
index,
|
||||||
|
(folderItemsRect.left + x * cellWidth + cellWidth / 2).toInt(),
|
||||||
|
(folderItemsRect.top + y * cellHeight + cellHeight / 2).toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun HomeScreenGridItem.getPositionInFolder(folder: HomeScreenGridItem): Pair<Int, Int> {
|
private fun HomeScreenGridItem.getPositionInFolder(folder: HomeScreenGridItem): Pair<Int, Int> {
|
||||||
val count = folder.getFolderItems().count()
|
val count = folder.getFolderItems().count()
|
||||||
val columnsCount = ceil(sqrt(count.toDouble())).roundToInt()
|
val columnsCount = ceil(sqrt(count.toDouble())).roundToInt()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user