Add basic support for folders on home screen

This commit is contained in:
Ensar Sarajčić
2023-08-01 12:13:55 +02:00
parent 65f4cf4b0a
commit a9f879628c
8 changed files with 222 additions and 87 deletions

View File

@ -147,6 +147,7 @@ class MainActivity : SimpleActivity(), FlingListener {
shortcutId, shortcutId,
icon.toBitmap(), icon.toBitmap(),
false, false,
null,
icon icon
) )
@ -781,7 +782,8 @@ class MainActivity : SimpleActivity(), FlingListener {
-1, -1,
"", "",
null, null,
true true,
null
) )
homeScreenGridItems.add(dialerIcon) homeScreenGridItems.add(dialerIcon)
} }
@ -807,7 +809,8 @@ class MainActivity : SimpleActivity(), FlingListener {
-1, -1,
"", "",
null, null,
true true,
null
) )
homeScreenGridItems.add(SMSMessengerIcon) homeScreenGridItems.add(SMSMessengerIcon)
} }
@ -835,7 +838,8 @@ class MainActivity : SimpleActivity(), FlingListener {
-1, -1,
"", "",
null, null,
true true,
null
) )
homeScreenGridItems.add(browserIcon) homeScreenGridItems.add(browserIcon)
} }
@ -862,7 +866,8 @@ class MainActivity : SimpleActivity(), FlingListener {
-1, -1,
"", "",
null, null,
true true,
null
) )
homeScreenGridItems.add(storeIcon) homeScreenGridItems.add(storeIcon)
} }
@ -891,7 +896,8 @@ class MainActivity : SimpleActivity(), FlingListener {
-1, -1,
"", "",
null, null,
true true,
null
) )
homeScreenGridItems.add(cameraIcon) homeScreenGridItems.add(cameraIcon)
} }

View File

@ -68,8 +68,8 @@ abstract class AppsDatabase : RoomDatabase() {
private val MIGRATION_4_5 = object : Migration(4, 5) { private val MIGRATION_4_5 = object : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) { override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE `home_screen_grid_items_new` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `left` INTEGER NOT NULL, `top` INTEGER NOT NULL, `right` INTEGER NOT NULL, `bottom` INTEGER NOT NULL, `page` INTEGER NOT NULL, `package_name` TEXT NOT NULL, `activity_name` TEXT NOT NULL, `title` TEXT NOT NULL, `type` INTEGER NOT NULL, `class_name` TEXT NOT NULL, `widget_id` INTEGER NOT NULL, `shortcut_id` TEXT NOT NULL, `icon` BLOB, `docked` INTEGER NOT NULL DEFAULT 0)") database.execSQL("CREATE TABLE `home_screen_grid_items_new` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `left` INTEGER NOT NULL, `top` INTEGER NOT NULL, `right` INTEGER NOT NULL, `bottom` INTEGER NOT NULL, `page` INTEGER NOT NULL, `package_name` TEXT NOT NULL, `activity_name` TEXT NOT NULL, `title` TEXT NOT NULL, `type` INTEGER NOT NULL, `class_name` TEXT NOT NULL, `widget_id` INTEGER NOT NULL, `shortcut_id` TEXT NOT NULL, `icon` BLOB, `docked` INTEGER NOT NULL DEFAULT 0, `parent_id` INTEGER)")
database.execSQL("INSERT INTO `home_screen_grid_items_new` (`id`, `left`, `top`, `right`, `bottom`, `page`, `package_name`, `activity_name`, `title`, `type`, `class_name`, `widget_id`, `shortcut_id`, `icon`, `docked`) SELECT `id`, `left`, `top`, `right`, `bottom`, 0 as `page`, `package_name`, `activity_name`, `title`, `type`, `class_name`, `widget_id`, `shortcut_id`, `icon`, CASE WHEN `type` != 1 AND `top` = 5 THEN 1 ELSE 0 END AS `docked` FROM `home_screen_grid_items` WHERE `intent` IS NULL OR `intent` = ''") database.execSQL("INSERT INTO `home_screen_grid_items_new` (`id`, `left`, `top`, `right`, `bottom`, `page`, `package_name`, `activity_name`, `title`, `type`, `class_name`, `widget_id`, `shortcut_id`, `icon`, `docked`, `parent_id`) SELECT `id`, `left`, `top`, `right`, `bottom`, 0 as `page`, `package_name`, `activity_name`, `title`, `type`, `class_name`, `widget_id`, `shortcut_id`, `icon`, CASE WHEN `type` != 1 AND `top` = 5 THEN 1 ELSE 0 END AS `docked`, NULL AS `parent_id` FROM `home_screen_grid_items` WHERE `intent` IS NULL OR `intent` = ''")
database.execSQL("DROP TABLE `home_screen_grid_items`") database.execSQL("DROP TABLE `home_screen_grid_items`")
database.execSQL("ALTER TABLE `home_screen_grid_items_new` RENAME TO `home_screen_grid_items`") database.execSQL("ALTER TABLE `home_screen_grid_items_new` RENAME TO `home_screen_grid_items`")
database.execSQL("CREATE UNIQUE INDEX `index_home_screen_grid_items_id` ON `home_screen_grid_items` (`id`)") database.execSQL("CREATE UNIQUE INDEX `index_home_screen_grid_items_id` ON `home_screen_grid_items` (`id`)")

View File

@ -211,6 +211,7 @@ class AllAppsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
"", "",
null, null,
false, false,
null,
appLauncher.drawable appLauncher.drawable
) )

View File

@ -266,6 +266,7 @@ class WidgetsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
"", "",
null, null,
false, false,
null,
appWidget.widgetPreviewImage, appWidget.widgetPreviewImage,
appWidget.providerInfo, appWidget.providerInfo,
appWidget.activityInfo, appWidget.activityInfo,

View File

@ -27,6 +27,7 @@ const val REQUEST_CREATE_SHORTCUT = 53
const val ITEM_TYPE_ICON = 0 const val ITEM_TYPE_ICON = 0
const val ITEM_TYPE_WIDGET = 1 const val ITEM_TYPE_WIDGET = 1
const val ITEM_TYPE_SHORTCUT = 2 const val ITEM_TYPE_SHORTCUT = 2
const val ITEM_TYPE_FOLDER = 3
const val WIDGET_HOST_ID = 12345 const val WIDGET_HOST_ID = 12345
const val MAX_CLICK_DURATION = 150 const val MAX_CLICK_DURATION = 150

View File

@ -1,9 +1,6 @@
package com.simplemobiletools.launcher.interfaces package com.simplemobiletools.launcher.interfaces
import androidx.room.Dao import androidx.room.*
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.simplemobiletools.launcher.models.HomeScreenGridItem import com.simplemobiletools.launcher.models.HomeScreenGridItem
@Dao @Dao
@ -23,12 +20,30 @@ interface HomeScreenGridItemsDao {
@Query("UPDATE home_screen_grid_items SET title = :title WHERE id = :id") @Query("UPDATE home_screen_grid_items SET title = :title WHERE id = :id")
fun updateItemTitle(title: String, id: Long): Int fun updateItemTitle(title: String, id: Long): Int
@Query("UPDATE home_screen_grid_items SET `left` = :left, `top` = :top, `right` = :right, `bottom` = :bottom, `page` = :page, `docked` = :docked WHERE id = :id") @Query("UPDATE home_screen_grid_items SET `left` = :left, `top` = :top, `right` = :right, `bottom` = :bottom, `page` = :page, `docked` = :docked , `parent_id` = :parentId WHERE id = :id")
fun updateItemPosition(left: Int, top: Int, right: Int, bottom: Int, page: Int, docked: Boolean, id: Long) fun updateItemPosition(left: Int, top: Int, right: Int, bottom: Int, page: Int, docked: Boolean, parentId: Long?, id: Long)
@Query("DELETE FROM home_screen_grid_items WHERE id = :id") @Query("DELETE FROM home_screen_grid_items WHERE id = :id")
fun deleteById(id: Long) fun deleteItemById(id: Long)
@Query("DELETE FROM home_screen_grid_items WHERE parent_id = :id")
fun deleteItemsWithParentId(id: Long)
@Transaction
fun deleteById(id: Long) {
deleteItemById(id)
deleteItemsWithParentId(id)
}
@Query("DELETE FROM home_screen_grid_items WHERE package_name = :packageName") @Query("DELETE FROM home_screen_grid_items WHERE package_name = :packageName")
fun deleteByPackageName(packageName: String) fun deleteItemByPackageName(packageName: String)
@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)
@Transaction
fun deleteByPackageName(packageName: String) {
deleteItemByPackageName(packageName)
deleteItemsByParentPackageName(packageName)
}
} }

View File

@ -25,6 +25,7 @@ data class HomeScreenGridItem(
@ColumnInfo(name = "shortcut_id") var shortcutId: String, // used at pinned shortcuts at startLauncher call @ColumnInfo(name = "shortcut_id") var shortcutId: String, // used at pinned shortcuts at startLauncher call
@ColumnInfo(name = "icon") var icon: Bitmap? = null, // store images of pinned shortcuts, those cannot be retrieved after creating @ColumnInfo(name = "icon") var icon: Bitmap? = null, // store images of pinned shortcuts, those cannot be retrieved after creating
@ColumnInfo(name = "docked") var docked: Boolean = false, // special flag, meaning that page, top and bottom don't matter for this item, it is always at the bottom of the screen @ColumnInfo(name = "docked") var docked: Boolean = false, // special flag, meaning that page, top and bottom don't matter for this item, it is always at the bottom of the screen
@ColumnInfo(name = "parent_id") var parentId: Long? = null, // id of folder this item is in (if it is in any)
@Ignore var drawable: Drawable? = null, @Ignore var drawable: Drawable? = null,
@Ignore var providerInfo: AppWidgetProviderInfo? = null, // used at widgets @Ignore var providerInfo: AppWidgetProviderInfo? = null, // used at widgets
@ -32,7 +33,7 @@ data class HomeScreenGridItem(
@Ignore var widthCells: Int = 1, @Ignore var widthCells: Int = 1,
@Ignore var heightCells: Int = 1 @Ignore var heightCells: Int = 1
) { ) {
constructor() : this(null, -1, -1, -1, -1, 0, "", "", "", ITEM_TYPE_ICON, "", -1, "", null, false, null, null, null, 1, 1) constructor() : this(null, -1, -1, -1, -1, 0, "", "", "", ITEM_TYPE_ICON, "", -1, "", null, false, null, null, null, null, 1, 1)
fun getWidthInCells() = if (right == -1 || left == -1) { fun getWidthInCells() = if (right == -1 || left == -1) {
widthCells widthCells

View File

@ -20,6 +20,7 @@ import android.util.Size
import android.util.SizeF import android.util.SizeF
import android.view.View import android.view.View
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
@ -153,6 +154,8 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
gridItems.forEach { item -> gridItems.forEach { item ->
if (item.type == ITEM_TYPE_ICON) { if (item.type == ITEM_TYPE_ICON) {
item.drawable = context.getDrawableForPackageName(item.packageName) item.drawable = context.getDrawableForPackageName(item.packageName)
} else if (item.type == ITEM_TYPE_FOLDER) {
item.drawable = resources.getColoredDrawableWithColor(R.drawable.ic_folder_vector, context.getProperPrimaryColor())
} else if (item.type == ITEM_TYPE_SHORTCUT) { } else if (item.type == ITEM_TYPE_SHORTCUT) {
if (item.icon != null) { if (item.icon != null) {
item.drawable = BitmapDrawable(item.icon) item.drawable = BitmapDrawable(item.icon)
@ -215,7 +218,11 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
fun itemDraggingStarted(draggedGridItem: HomeScreenGridItem) { fun itemDraggingStarted(draggedGridItem: HomeScreenGridItem) {
draggedItem = draggedGridItem draggedItem = draggedGridItem
if (draggedItem!!.drawable == null) { if (draggedItem!!.drawable == null) {
draggedItem!!.drawable = context.getDrawableForPackageName(draggedGridItem.packageName) if (draggedItem?.type == ITEM_TYPE_FOLDER) {
draggedItem!!.drawable = resources.getColoredDrawableWithColor(R.drawable.ic_folder_vector, context.getProperPrimaryColor())
} else {
draggedItem!!.drawable = context.getDrawableForPackageName(draggedGridItem.packageName)
}
} }
redrawGrid() redrawGrid()
@ -293,6 +300,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
scheduleIndicatorsFade() scheduleIndicatorsFade()
when (draggedItem!!.type) { when (draggedItem!!.type) {
ITEM_TYPE_FOLDER -> moveItem()
ITEM_TYPE_ICON, ITEM_TYPE_SHORTCUT -> addAppIconOrShortcut() ITEM_TYPE_ICON, ITEM_TYPE_SHORTCUT -> addAppIconOrShortcut()
ITEM_TYPE_WIDGET -> addWidget() ITEM_TYPE_WIDGET -> addWidget()
} }
@ -328,7 +336,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
updateWidgetPositionAndSize(widgetView, item) updateWidgetPositionAndSize(widgetView, item)
ensureBackgroundThread { ensureBackgroundThread {
context.homeScreenGridItemsDB.updateItemPosition(item.left, item.top, item.right, item.bottom, item.page, false, item.id!!) context.homeScreenGridItemsDB.updateItemPosition(item.left, item.top, item.right, item.bottom, item.page, false, null, item.id!!)
} }
} }
@ -353,6 +361,58 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
resizedWidget = null resizedWidget = null
} }
private fun moveItem() {
val draggedHomeGridItem = gridItems.firstOrNull { it.id == draggedItem?.id }
val center = gridCenters.minBy {
abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
}
var redrawIcons = false
val gridCells = getClosestGridCells(center)
if (gridCells != null) {
val xIndex = gridCells.first
val yIndex = gridCells.second
// check if the destination cell is empty
var isDroppingPositionValid = true
val wantedCell = Pair(xIndex, yIndex)
gridItems.filterVisibleOnly().forEach { item ->
for (xCell in item.left..item.right) {
for (yCell in item.getDockAdjustedTop(rowCount)..item.getDockAdjustedBottom(rowCount)) {
val cell = Pair(xCell, yCell)
val isAnyCellOccupied = wantedCell == cell
if (isAnyCellOccupied) {
isDroppingPositionValid = false
return@forEach
}
}
}
}
if (isDroppingPositionValid) {
draggedHomeGridItem?.apply {
left = xIndex
top = yIndex
right = xIndex
bottom = yIndex
page = currentPage
docked = yIndex == rowCount - 1
ensureBackgroundThread {
context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, parentId, id!!)
}
}
redrawIcons = true
}
}
draggedItem = null
draggedItemCurrentCoords = Pair(-1, -1)
if (redrawIcons) {
redrawGrid()
}
}
private fun addAppIconOrShortcut() { private fun addAppIconOrShortcut() {
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)
@ -364,78 +424,56 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
val xIndex = gridCells.first val xIndex = gridCells.first
val yIndex = gridCells.second val yIndex = gridCells.second
// check if the destination cell is empty // check if the destination cell is empty or a folder
var areAllCellsEmpty = true var isDroppingPositionValid = true
var potentialParent: HomeScreenGridItem? = null
val wantedCell = Pair(xIndex, yIndex) val wantedCell = Pair(xIndex, yIndex)
gridItems.filter { it.page == currentPage || it.docked }.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)) {
val cell = Pair(xCell, yCell) val cell = Pair(xCell, yCell)
val isAnyCellOccupied = wantedCell == cell val isAnyCellOccupied = wantedCell == cell
if (isAnyCellOccupied) { if (isAnyCellOccupied) {
areAllCellsEmpty = false if (item.type != ITEM_TYPE_WIDGET) {
potentialParent = item
} else {
isDroppingPositionValid = false
}
return@forEach return@forEach
} }
} }
} }
} }
if (areAllCellsEmpty) { if (isDroppingPositionValid) {
val draggedHomeGridItem = gridItems.firstOrNull { it.id == draggedItem?.id } val draggedHomeGridItem = gridItems.firstOrNull { it.id == draggedItem?.id }
// we are moving an existing home screen item from one place to another if (potentialParent != null) {
if (draggedHomeGridItem != null) { if (potentialParent?.type == ITEM_TYPE_FOLDER) {
draggedHomeGridItem.apply { addAppIconOrShortcut(draggedHomeGridItem, xIndex, yIndex, potentialParent?.id)
left = xIndex } else {
top = yIndex val parentItem = potentialParent!!.copy(
right = xIndex type = ITEM_TYPE_FOLDER,
bottom = yIndex id = null,
page = currentPage title = resources.getString(R.string.folder)
docked = yIndex == rowCount - 1 )
ensureBackgroundThread { ensureBackgroundThread {
context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, id!!) val newId = context.homeScreenGridItemsDB.insert(parentItem)
} parentItem.id = newId
} potentialParent?.apply {
redrawIcons = true parentId = newId
} else if (draggedItem != null) { context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, newId, id!!)
// we are dragging a new item at the home screen from the All Apps fragment }
val newHomeScreenGridItem = HomeScreenGridItem( (context as? MainActivity)?.runOnUiThread {
null, gridItems.add(parentItem)
xIndex, addAppIconOrShortcut(draggedHomeGridItem, xIndex, yIndex, newId)
yIndex,
xIndex,
yIndex,
currentPage,
draggedItem!!.packageName,
draggedItem!!.activityName,
draggedItem!!.title,
draggedItem!!.type,
"",
-1,
"",
draggedItem!!.icon,
yIndex == rowCount - 1,
draggedItem!!.drawable,
draggedItem!!.providerInfo,
draggedItem!!.activityInfo
)
if (newHomeScreenGridItem.type == ITEM_TYPE_ICON) {
ensureBackgroundThread {
storeAndShowGridItem(newHomeScreenGridItem)
}
} else if (newHomeScreenGridItem.type == ITEM_TYPE_SHORTCUT) {
(context as? MainActivity)?.handleShorcutCreation(newHomeScreenGridItem.activityInfo!!) { shortcutId, label, icon ->
ensureBackgroundThread {
newHomeScreenGridItem.shortcutId = shortcutId
newHomeScreenGridItem.title = label
newHomeScreenGridItem.icon = icon.toBitmap()
newHomeScreenGridItem.drawable = icon
storeAndShowGridItem(newHomeScreenGridItem)
} }
} }
} }
return
} else {
addAppIconOrShortcut(draggedHomeGridItem, xIndex, yIndex)
return
} }
} else { } else {
performHapticFeedback() performHapticFeedback()
@ -450,6 +488,68 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
} }
private fun addAppIconOrShortcut(draggedHomeGridItem: HomeScreenGridItem?, xIndex: Int, yIndex: Int, newParentId: Long? = null) {
// we are moving an existing home screen item from one place to another
if (draggedHomeGridItem != null) {
draggedHomeGridItem.apply {
left = xIndex
top = yIndex
right = xIndex
bottom = yIndex
page = currentPage
docked = yIndex == rowCount - 1
parentId = newParentId
ensureBackgroundThread {
context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, newParentId, id!!)
}
}
} else if (draggedItem != null) {
// we are dragging a new item at the home screen from the All Apps fragment
val newHomeScreenGridItem = HomeScreenGridItem(
null,
xIndex,
yIndex,
xIndex,
yIndex,
currentPage,
draggedItem!!.packageName,
draggedItem!!.activityName,
draggedItem!!.title,
draggedItem!!.type,
"",
-1,
"",
draggedItem!!.icon,
yIndex == rowCount - 1,
newParentId,
draggedItem!!.drawable,
draggedItem!!.providerInfo,
draggedItem!!.activityInfo
)
if (newHomeScreenGridItem.type == ITEM_TYPE_ICON) {
ensureBackgroundThread {
storeAndShowGridItem(newHomeScreenGridItem)
}
} else if (newHomeScreenGridItem.type == ITEM_TYPE_SHORTCUT) {
(context as? MainActivity)?.handleShorcutCreation(newHomeScreenGridItem.activityInfo!!) { shortcutId, label, icon ->
ensureBackgroundThread {
newHomeScreenGridItem.shortcutId = shortcutId
newHomeScreenGridItem.title = label
newHomeScreenGridItem.icon = icon.toBitmap()
newHomeScreenGridItem.drawable = icon
storeAndShowGridItem(newHomeScreenGridItem)
}
}
}
}
draggedItem = null
draggedItemCurrentCoords = Pair(-1, -1)
redrawGrid()
}
fun storeAndShowGridItem(item: HomeScreenGridItem) { fun storeAndShowGridItem(item: HomeScreenGridItem) {
val newId = context.homeScreenGridItemsDB.insert(item) val newId = context.homeScreenGridItemsDB.insert(item)
item.id = newId item.id = newId
@ -473,7 +573,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
var areAllCellsEmpty = true var areAllCellsEmpty = true
gridItems.filter { it.id != draggedItem?.id && (it.page == currentPage || it.docked) }.forEach { item -> gridItems.filterVisibleOnly().filter { it.id != draggedItem?.id }.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)) {
val cell = Pair(xCell, yCell) val cell = Pair(xCell, yCell)
@ -512,6 +612,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
widgetItem.bottom, widgetItem.bottom,
currentPage, currentPage,
false, false,
null,
widgetItem.id!! widgetItem.id!!
) )
val widgetView = widgetViews.firstOrNull { it.tag == widgetItem.widgetId } val widgetView = widgetViews.firstOrNull { it.tag == widgetItem.widgetId }
@ -694,13 +795,19 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
if (item.id != draggedItem?.id) { if (item.id != draggedItem?.id) {
val drawableX = cellXCoords[item.left] + iconMargin + extraXMargin + sideMargins.left + (width * xFactor).toInt() val drawableX = cellXCoords[item.left] + iconMargin + extraXMargin + sideMargins.left + (width * xFactor).toInt()
val drawable = if (item.type == ITEM_TYPE_FOLDER) {
resources.getColoredDrawableWithColor(R.drawable.ic_folder_vector, context.getProperPrimaryColor())
} else {
item.drawable!!
}
if (item.docked) { if (item.docked) {
val drawableY = cellYCoords[rowCount - 1] + cellHeight - iconMargin - iconSize + sideMargins.top val drawableY = cellYCoords[rowCount - 1] + cellHeight - iconMargin - iconSize + sideMargins.top
item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize) drawable.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
} else { } else {
val drawableY = cellYCoords[item.top] + iconMargin + extraYMargin + sideMargins.top val drawableY = cellYCoords[item.top] + iconMargin + extraYMargin + sideMargins.top
item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize) drawable.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
if (item.id != draggedItem?.id && item.title.isNotEmpty()) { if (item.id != draggedItem?.id && item.title.isNotEmpty()) {
val textX = cellXCoords[item.left].toFloat() + labelSideMargin + sideMargins.left + width * xFactor val textX = cellXCoords[item.left].toFloat() + labelSideMargin + sideMargins.left + width * xFactor
@ -719,11 +826,11 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
} }
item.drawable!!.draw(canvas) drawable.draw(canvas)
} }
} }
gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.page == currentPage && !it.docked } gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT || it.type == ITEM_TYPE_FOLDER) && it.page == currentPage && !it.docked && it.parentId == null }
.forEach { item -> .forEach { item ->
if (item.outOfBounds()) { if (item.outOfBounds()) {
return@forEach return@forEach
@ -731,15 +838,16 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
handleItemDrawing(item, currentXFactor) handleItemDrawing(item, currentXFactor)
} }
gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.docked }.forEach { item -> gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT || it.type == ITEM_TYPE_FOLDER) && it.docked && it.parentId == null }
if (item.outOfBounds()) { .forEach { item ->
return@forEach if (item.outOfBounds()) {
} return@forEach
}
handleItemDrawing(item, 0f) handleItemDrawing(item, 0f)
} }
if (pageChangeAnimLeftPercentage > 0f) { if (pageChangeAnimLeftPercentage > 0f) {
gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.page == lastPage && !it.docked } gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT || it.type == ITEM_TYPE_FOLDER) && it.page == lastPage && !it.docked && it.parentId == null }
.forEach { item -> .forEach { item ->
if (item.outOfBounds()) { if (item.outOfBounds()) {
return@forEach return@forEach
@ -794,7 +902,7 @@ 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) { if (draggedItem!!.type == ITEM_TYPE_ICON || draggedItem!!.type == ITEM_TYPE_SHORTCUT || draggedItem!!.type == ITEM_TYPE_FOLDER) {
// 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)
@ -936,12 +1044,12 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
fun isClickingGridItem(x: Int, y: Int): HomeScreenGridItem? { fun isClickingGridItem(x: Int, y: Int): HomeScreenGridItem? {
for (gridItem in gridItems.filter { it.page == currentPage || it.docked }) { for (gridItem in gridItems.filterVisibleOnly()) {
if (gridItem.outOfBounds()) { if (gridItem.outOfBounds()) {
continue continue
} }
if (gridItem.type == ITEM_TYPE_ICON || gridItem.type == ITEM_TYPE_SHORTCUT) { if (gridItem.type == ITEM_TYPE_ICON || gridItem.type == ITEM_TYPE_SHORTCUT || gridItem.type == ITEM_TYPE_FOLDER) {
val rect = getClickableRect(gridItem) val rect = getClickableRect(gridItem)
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) { if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
return gridItem return gridItem
@ -1106,6 +1214,8 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
} }
private fun ArrayList<HomeScreenGridItem>.filterVisibleOnly() = filter { (it.page == currentPage || it.docked) && it.parentId == null }
companion object { companion object {
private const val PAGE_CHANGE_HOLD_THRESHOLD = 500L private const val PAGE_CHANGE_HOLD_THRESHOLD = 500L
private const val PAGE_INDICATORS_FADE_DELAY = PAGE_CHANGE_HOLD_THRESHOLD + 300L private const val PAGE_INDICATORS_FADE_DELAY = PAGE_CHANGE_HOLD_THRESHOLD + 300L