Fix drag & drop

There was an assumption that the list view would only contain MailboxListItem's.
Now it's not always the case with the headers like "recent folders".

Also killed the timer thing for the nested navigation during DnD.

Bug 4904006

Change-Id: I4ee756775d0115f3a39086758be69100c19163c9
This commit is contained in:
Makoto Onuki 2011-06-22 15:38:55 -07:00
parent 67cd9eb0d9
commit d5dfd76cb9

View File

@ -213,8 +213,6 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
private MailboxListItem mDropTargetView;
// Lazily instantiated height of a mailbox list item (-1 is a sentinel for 'not initialized')
private int mDragItemHeight = -1;
/** Task that actually does the work to auto-expand folder lists during drag-n-drop */
private TimerTask mDragTimerTask;
/** {@code true} if we are currently scrolling under the drag item */
private boolean mTargetScrolling;
@ -937,56 +935,15 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
mDragItemHeight = lv.getChildAt(0).getHeight();
}
for (int i = 0; i < itemCount; i++) {
MailboxListItem item = (MailboxListItem) lv.getChildAt(i);
final View child = lv.getChildAt(i);
if (!(child instanceof MailboxListItem)) {
continue;
}
MailboxListItem item = (MailboxListItem) child;
item.setDropTargetBackground(mDragInProgress, mDragItemMailboxId);
}
}
/**
* Starts the timer responsible for auto-selecting mailbox items while in drag-n-drop.
* If there is already an active task, we first try to cancel it. There are only two
* reasons why a new timer may not be started. First, if we are unable to cancel a
* previous timer, we must assume that a new mailbox has already been loaded. Second,
* if the target item is not permitted to be auto selected.
* @param newTarget The drag target that needs to be auto selected
*/
private void startDragTimer(final MailboxListItem newTarget) {
boolean canceledInTime = mDragTimerTask == null || stopDragTimer();
if (canceledInTime
&& newTarget != null
&& newTarget.isNavigable()
&& newTarget.isDropTarget(mDragItemMailboxId)) {
mDragTimerTask = new TimerTask() {
@Override
public void run() {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
stopDragTimer();
}
});
}
};
sDragTimer.schedule(mDragTimerTask, AUTO_EXPAND_DELAY);
}
}
/**
* Stops the timer responsible for auto-selecting mailbox items while in drag-n-drop.
* If the timer is not active, nothing will happen.
* @return Whether or not the timer was interrupted. {@link TimerTask#cancel()}.
*/
private boolean stopDragTimer() {
boolean timerInterrupted = false;
synchronized (sDragTimer) {
if (mDragTimerTask != null) {
timerInterrupted = mDragTimerTask.cancel();
mDragTimerTask = null;
}
}
return timerInterrupted;
}
/**
* Called when the user has dragged outside of the mailbox list area.
*/
@ -997,7 +954,6 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
mDropTargetView = null;
}
mDropTargetId = NO_DROP_TARGET;
stopDragTimer();
stopScrolling();
}
@ -1028,12 +984,14 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
mDropTargetView = null;
}
// Get the new target mailbox view
final MailboxListItem newTarget = (MailboxListItem) lv.getChildAt(viewIndex);
if (newTarget == null) {
final View childView = lv.getChildAt(viewIndex);
final MailboxListItem newTarget;
if (childView == null) {
// In any event, we're no longer dragging in the list view if newTarget is null
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Drag off the list");
}
newTarget = null;
final int childCount = lv.getChildCount();
if (viewIndex >= childCount) {
// Touching beyond the end of the list; may happen for small lists
@ -1043,27 +1001,34 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
// We should never get here
Log.w(TAG, "null view; idx: " + viewIndex + ", cnt: " + childCount);
}
} else if (newTarget.mMailboxType == Mailbox.TYPE_TRASH) {
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Trash mailbox; id: " + newTarget.mMailboxId);
}
newTarget.setDropTrashBackground();
} else if (newTarget.isDropTarget(mDragItemMailboxId)) {
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Target mailbox; id: " + newTarget.mMailboxId);
}
newTarget.setDropActiveBackground();
} else {
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Non-droppable mailbox; id: " + newTarget.mMailboxId);
}
newTarget.setDropTargetBackground(true, mDragItemMailboxId);
} else if (!(childView instanceof MailboxListItem)) {
// We're over a header suchas "Recent folders". We shouldn't finish DnD, but
// drop should be disabled.
newTarget = null;
targetId = NO_DROP_TARGET;
} else {
newTarget = (MailboxListItem) childView;
if (newTarget.mMailboxType == Mailbox.TYPE_TRASH) {
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Trash mailbox; id: " + newTarget.mMailboxId);
}
newTarget.setDropTrashBackground();
} else if (newTarget.isDropTarget(mDragItemMailboxId)) {
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Target mailbox; id: " + newTarget.mMailboxId);
}
newTarget.setDropActiveBackground();
} else {
if (DEBUG_DRAG_DROP) {
Log.d(TAG, "=== Non-droppable mailbox; id: " + newTarget.mMailboxId);
}
newTarget.setDropTargetBackground(true, mDragItemMailboxId);
targetId = NO_DROP_TARGET;
}
}
// Save away our current position and view
mDropTargetId = targetId;
mDropTargetView = newTarget;
startDragTimer(newTarget);
}
// This is a quick-and-dirty implementation of drag-under-scroll; something like this
@ -1107,7 +1072,6 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
}
private void onDragEnded() {
stopDragTimer();
if (mDragInProgress) {
mDragInProgress = false;
// Reenable updates to the view and redraw (in case it changed)
@ -1159,7 +1123,6 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
* @return {@code true} if the drop action was performed. Otherwise {@code false}.
*/
private boolean onDrop(DragEvent event) {
stopDragTimer();
stopScrolling();
// If we're not on a target, we're done
if (mDropTargetId == NO_DROP_TARGET) {