Commit b9d178c3 authored by Amit Kumar's avatar Amit Kumar 💻
Browse files

Recurse through open folder in all cases

parent d13159f2
Pipeline #151960 passed with stage
in 7 minutes and 57 seconds
......@@ -50,21 +50,11 @@ class Folder @JvmOverloads constructor(
attrs: AttributeSet? = null
) : AbstractFloatingView(context, attrs), DragController.DragListener,
FolderTitleInput.OnBackKeyListener, FolderItem.FolderListener, View.OnFocusChangeListener,
OnEditorActionListener, DragSource {
OnEditorActionListener, DragSource, DropTarget {
/**
* Fraction of icon width which behave as scroll region.
*/
private val ICON_OVERSCROLL_WIDTH_FACTOR = 0.45f
private val FOLDER_NAME_ANIMATION_DURATION = 633L
private val REORDER_DELAY = 250L
private val ON_EXIT_CLOSE_DELAY = 400L
private val sTempRect = Rect()
private var mScrollAreaOffset: Int = 0
private val MIN_FOLDERS_FOR_HARDWARE_OPTIMIZATION = 10
private val mReorderAlarm: Alarm = Alarm()
private val mOnExitAlarm: Alarm = Alarm()
val mItemsInReadingOrder = ArrayList<View>()
......@@ -79,8 +69,6 @@ class Folder @JvmOverloads constructor(
lateinit var mFolderTitleInput: FolderTitleInput
private lateinit var mPageIndicator: CircleIndicator
// Cell ranks used for drag and drop
var mTargetRank = 0
var mPrevTargetRank = 0
var mEmptyCellRank = 0
......@@ -138,7 +126,7 @@ class Folder @JvmOverloads constructor(
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
ev?.let {
/*ev?.let {
if (it.action == MotionEvent.ACTION_DOWN) {
val dl: DragLayer = launcher.dragLayer
if (isEditingName()) {
......@@ -152,7 +140,7 @@ class Folder @JvmOverloads constructor(
return true
}
}
}
}*/
return false
}
......@@ -200,6 +188,7 @@ class Folder @JvmOverloads constructor(
private fun closeComplete(wasAnimated: Boolean) {
// TODO: Clear all active animations.
(this.parent as DragLayer?)?.removeView(this)
dragController?.removeDropTarget(this)
clearFocus()
folderIcon?.apply {
launcher.getLauncherPagedView().alpha = 1f
......@@ -235,7 +224,7 @@ class Folder @JvmOverloads constructor(
// Convert to a string here to ensure that no other state associated with the text field
// gets saved.
val newTitle: String = mFolderTitleInput.text.toString()
mInfo?.setTitle(newTitle)
mInfo.setTitle(newTitle)
// Update database
launcher.getLauncherPagedView().updateDatabase()
......@@ -253,14 +242,16 @@ class Folder @JvmOverloads constructor(
// we need to create the illusion that the item isn't added back to the folder yet, to
// to correspond to the animation of the icon back into the folder. This is
fun hideItem(info: LauncherItem) {
getViewForInfo(info).apply {
visibility = INVISIBLE
getViewForInfo(info)?.apply {
this.clearAnimation()
this.visibility = INVISIBLE
}
}
fun showItem(info: LauncherItem) {
getViewForInfo(info)?.apply {
visibility = VISIBLE
this.clearAnimation()
this.visibility = VISIBLE
}
}
......@@ -271,6 +262,7 @@ class Folder @JvmOverloads constructor(
override fun onTitleChanged(title: CharSequence?) {}
override fun onRemove(item: LauncherItem) {
Log.d(TAG, "onRemove() called with: item = $item")
mItemsInvalidated = true
val v: View? = getViewForInfo(item)
mContent.adapter?.notifyDataSetChanged()
......@@ -302,15 +294,12 @@ class Folder @JvmOverloads constructor(
if (dragObject.dragSource != this) {
return
}
mContent.removeItem(mCurrentDragView)
mCurrentDragView?.clearAnimation()
hideItem(dragObject.dragInfo)
if (dragObject.dragInfo is LauncherItem) {
mItemsInvalidated = true
SuppressInfoChanges().use { _ ->
mInfo.remove(
dragObject.dragInfo as LauncherItem,
true
)
// mInfo?.remove(dragObject.dragInfo, true)
}
}
mDragInProgress = true
......@@ -400,8 +389,6 @@ class Folder @JvmOverloads constructor(
}
})
// We use same size for height and width as we want to look it like square
val height =
mDeviceProfile.cellHeightPx * 3 + resources.getDimensionPixelSize(R.dimen.folder_padding)
mContent.layoutParams?.width =
mDeviceProfile.cellHeightPx * 3 + resources.getDimensionPixelSize(R.dimen.folder_padding) * 2
mContent.layoutParams?.height =
......@@ -480,6 +467,7 @@ class Folder @JvmOverloads constructor(
ViewGroup.LayoutParams.MATCH_PARENT
)
)
dragController?.addDropTarget(this)
} else {
Log.e(
TAG,
......@@ -498,7 +486,6 @@ class Folder @JvmOverloads constructor(
// dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice.
mDeleteFolderOnDropCompleted = false
// centerAboutIcon()
Log.i(TAG, "animateOpen: " + mContent.getItemCount() + " " + mInfo.items.size)
val anim: AnimatorSet = FolderAnimationManager(this, true /* isOpening */).animator
anim.play(ObjectAnimator.ofFloat(launcher.getLauncherPagedView(), View.ALPHA, 0f))
.with(ObjectAnimator.ofFloat(launcher.hotseat, View.ALPHA, 0f))
......@@ -518,6 +505,7 @@ class Folder @JvmOverloads constructor(
launcher.getLauncherPagedView().alpha = 0f
launcher.hotseat.alpha = 0f
launcher.getLauncherPagedView().pageIndicator.alpha = 0f
mContent.setFocusOnFirstChild()
}
override fun onAnimationCancel(animation: Animator?) {
......@@ -535,16 +523,20 @@ class Folder @JvmOverloads constructor(
}
fun completeDragExit() {
if (mIsOpen) {
when {
mIsOpen -> {
close(true)
mRearrangeOnClose = true
} else if (mState == STATE_ANIMATING) {
}
mState == STATE_ANIMATING -> {
mRearrangeOnClose = true
} else {
}
else -> {
rearrangeChildren()
clearDragInfo()
}
}
}
private fun clearDragInfo() {
mCurrentDragView = null
......@@ -563,7 +555,7 @@ class Folder @JvmOverloads constructor(
* @param itemCount if greater than the total children count, empty spaces are left at the end,
* otherwise it is ignored.
*/
fun rearrangeChildren(itemCount: Int) {
private fun rearrangeChildren(itemCount: Int) {
mContent.adapter?.notifyDataSetChanged()
mItemsInvalidated = true
}
......@@ -648,7 +640,12 @@ class Folder @JvmOverloads constructor(
}
} else {
// The drag failed, we need to return the item to the folder
mContent.adapter?.notifyDataSetChanged()
mContent.adapter =
FolderPagerAdapter(context, mInfo.items, launcher.deviceProfile)
launcher.dragLayer.removeView(d?.dragView)
d?.dragView = null
invalidate()
launcher.getLauncherPagedView().wobbleLayouts()
}
mDeleteFolderOnDropCompleted = false
......@@ -656,7 +653,7 @@ class Folder @JvmOverloads constructor(
mItemAddedBackToSelfViaIcon = false
mCurrentDragView = null
// Reordering may have occured, and we need to save the new item locations. We do this once
// Reordering may have occurred, and we need to save the new item locations. We do this once
// at the end to prevent unnecessary database operations.
launcher.getLauncherPagedView().updateDatabase()
}
......@@ -697,6 +694,8 @@ class Folder @JvmOverloads constructor(
const val STATE_ANIMATING = 1
const val STATE_OPEN = 2
private const val ON_EXIT_CLOSE_DELAY = 400L
const val TAG = "Folder"
private var sDefaultFolderName: String? = null
......@@ -740,4 +739,51 @@ class Folder @JvmOverloads constructor(
mInfo.removeListener(this@Folder)
}
}
override fun isDropEnabled(): Boolean = mState != STATE_ANIMATING
override fun onDrop(dragObject: DropTarget.DragObject?, options: DragOptions?) {
// Do nothing here as we don't allow to drop icon in folder.
}
override fun onDragEnter(d: DropTarget.DragObject) {
mPrevTargetRank = -1
mOnExitAlarm.cancelAlarm()
// Get the area offset such that the folder only closes if half the drag icon width
// is outside the folder area
// Get the area offset such that the folder only closes if half the drag icon width
// is outside the folder area
mScrollAreaOffset = d.dragView.dragRegionWidth / 2 - d.xOffset
}
override fun onDragOver(dragObject: DropTarget.DragObject?) {
// Do Nothing here, we don't allow drop.
Log.d(TAG, "onDragOver() called with: dragObject = $dragObject")
}
override fun onDragExit(d: DropTarget.DragObject) {
// We only close the folder if this is a true drag exit, ie. not because
// a drop has occurred above the folder.
if (!d.dragComplete) {
mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener)
mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY)
}
}
override fun acceptDrop(dragObject: DropTarget.DragObject?): Boolean = false
override fun prepareAccessibilityDrop() {
}
override fun getHitRectRelativeToDragLayer(outRect: Rect?) {
launcher.dragLayer.getDescendantRectRelativeToSelf(mContent, outRect)
// mContent.getHitRect(outRect)
/*outRect!!.left -= mScrollAreaOffset
outRect!!.right += mScrollAreaOffset*/
Log.i(TAG, "getHitRectRelativeToDragLayer: " + outRect)
}
fun getContent(): ViewGroup {
return mContent
}
}
......@@ -202,6 +202,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
*/
public final Map<ShortcutKey, MutableInt> pinnedShortcutCounts = new HashMap<>();
/** The value that {@link #mTransitionProgress} must be greater than for
* {@link #transitionStateShouldAllowDrop()} to return true. */
private static final float ALLOW_DROP_TRANSITION_PROGRESS = 0.25f;
public LauncherPagedView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, 0);
}
......@@ -333,7 +337,8 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
LauncherItem launcherItem = launcherItems.get(i);
View appView;
if (launcherItem.itemType == Constants.ITEM_TYPE_FOLDER) {
FolderIcon folderIcon = FolderIcon.Companion.fromXml(R.layout.folder_icon,
FolderIcon folderIcon = FolderIcon.Companion.fromXml(
R.layout.folder_icon,
getScreenWithId(launcherItem.screenId),
(FolderItem) launcherItem
);
......@@ -1379,11 +1384,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
if (!workspaceInModalState() && !mIsSwitchingState) {
result = super.scrollLeft();
}
// TODO: Fix this asap
/*Folder openFolder = Folder.getOpen(mLauncher);
Folder openFolder = Folder.Companion.getOpen(mLauncher);
if (openFolder != null) {
openFolder.completeDragExit();
}*/
}
return result;
}
......@@ -1393,11 +1397,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
if (!workspaceInModalState() && !mIsSwitchingState) {
result = super.scrollRight();
}
// TODO: Fix this asap
/*Folder openFolder = Folder.getOpen(mLauncher);
Folder openFolder = Folder.Companion.getOpen(mLauncher);
if (openFolder != null) {
openFolder.completeDragExit();
}*/
}
return result;
}
......@@ -1687,7 +1690,8 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
final int[] touchXY = new int[]{(int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1]};
// onDropExternal(touchXY, dropTargetLayout, d);
} else {
}
else {
final View cell = mDragInfo.getCell();
boolean droppedOnOriginalCellDuringTransition = false;
Runnable onCompleteRunnable = null;
......@@ -2211,7 +2215,7 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
}
// Handle the drag over
if (mDragTargetLayout != null) {
if (mDragTargetLayout != null && child != null) {
// We want the point to be mapped to the dragTarget.
if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
......@@ -2301,8 +2305,46 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
}
@Override
public boolean acceptDrop(DragObject dragObject) {
public boolean acceptDrop(DragObject d) {
CellLayout dropTargetLayout = mDropToLayout;
if(d.dragSource != this) {
if (dropTargetLayout == null) {
return false;
}
if (!transitionStateShouldAllowDrop()) return false;
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
// We want the point to be mapped to the dragTarget.
mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], dropTargetLayout,
mTargetCell);
float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
mDragViewVisualCenter[1], mTargetCell);
if (mCreateUserFolderOnDrop && willCreateUserFolder(d.dragInfo,
dropTargetLayout, mTargetCell, distance, true)) {
return true;
}
if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder(d.dragInfo,
dropTargetLayout, mTargetCell, distance)) {
return true;
}
int[] resultSpan = new int[2];
mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], 1, 1, 1, 1,
null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP);
boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
// Don't accept the drop if there's no room for the item
if (!foundCell) {
onNoCellFound(dropTargetLayout);
return false;
}
}
long screenId = getIdForScreen(dropTargetLayout);
if (screenId == EXTRA_EMPTY_SCREEN_ID) {
commitExtraEmptyScreen();
......@@ -2310,6 +2352,25 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
return true;
}
/**
* Updates the point in {@param xy} to point to the co-ordinate space of {@param layout}
* @param layout either hotseat of a page in workspace
* @param xy the point location in workspace co-ordinate space
*/
private void mapPointFromDropLayout(CellLayout layout, float[] xy) {
if (mLauncher.isHotseatLayout(layout)) {
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, xy, true);
mLauncher.getDragLayer().mapCoordInSelfToDescendant(layout, xy);
} else {
mapPointFromSelfToChild(layout, xy);
}
}
private boolean transitionStateShouldAllowDrop() {
return (!isSwitchingState() || mTransitionProgress > ALLOW_DROP_TRANSITION_PROGRESS) &&
workspaceIconsCanBeDragged();
}
@Override
public void prepareAccessibilityDrop() {
Log.d(TAG, "prepareAccessibilityDrop() called");
......@@ -2651,9 +2712,18 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
return;
}
}
Folder folder = Folder.Companion.getOpen(mLauncher);
if (folder != null && !folder.isDestroyed()) {
for (int i = 0; i < folder.getContent().getChildCount(); i++) {
GridLayout grid = (GridLayout) folder.getContent().getChildAt(i);
if (mapOverCellLayout(recurse, grid, op)) {
return;
}
}
}
}
private boolean mapOverCellLayout(boolean recurse, CellLayout layout, ItemOperator op) {
private boolean mapOverCellLayout(boolean recurse, GridLayout layout, ItemOperator op) {
// TODO(b/128460496) Potential race condition where layout is not yet loaded
if (layout == null) {
return false;
......
......@@ -3,6 +3,7 @@ package foundation.e.blisslauncher.features.folder
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.GridLayout
import androidx.core.view.get
import androidx.viewpager.widget.ViewPager
......@@ -67,4 +68,11 @@ class FolderViewPager @JvmOverloads constructor(
(getChildAt(lastPageIndex) as GridLayout).childCount + lastPageIndex * 9 // maxItems per page
}
}
/**
* Sets the focus on the first visible child.
*/
fun setFocusOnFirstChild() {
(getChildAt(currentItem) as ViewGroup?)?.getChildAt(0)?.requestFocus()
}
}
......@@ -16,6 +16,9 @@
package foundation.e.blisslauncher.features.test.dragndrop;
import static foundation.e.blisslauncher.features.test.LauncherState.NORMAL;
import static foundation.e.blisslauncher.features.test.anim.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import android.content.ComponentName;
import android.content.res.Resources;
import android.graphics.Bitmap;
......@@ -28,9 +31,6 @@ import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import foundation.e.blisslauncher.R;
import foundation.e.blisslauncher.core.database.model.ApplicationItem;
import foundation.e.blisslauncher.core.database.model.LauncherItem;
......@@ -39,6 +39,7 @@ import foundation.e.blisslauncher.features.test.LauncherItemMatcher;
import foundation.e.blisslauncher.features.test.TestActivity;
import foundation.e.blisslauncher.features.test.TouchController;
import foundation.e.blisslauncher.features.test.UiThreadHelper;
import java.util.ArrayList;
/**
* Class for initiating a drag within a view or across multiple views.
......@@ -251,8 +252,7 @@ public class DragController implements DragDriver.EventListener, TouchController
if (!accepted) {
// If it was not accepted, cleanup the state. If it was accepted, it is the
// responsibility of the drop target to cleanup the state.
// mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
//TODO: Go to normal state here.
mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
mDragObject.deferDragViewCleanupPostAnimation = false;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment