mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-28 07:46:55 +00:00
* Update WidgetsTwoPaneSheet.java Signed-off-by: Pun Butrach <pun.butrach@gmail.com> * Update PopupContainerWithArrow.java Signed-off-by: Pun Butrach <pun.butrach@gmail.com> * Update SplitInstructionsView.java Signed-off-by: Pun Butrach <pun.butrach@gmail.com> * Update TaskbarView.java Signed-off-by: Pun Butrach <pun.butrach@gmail.com> --------- Signed-off-by: Pun Butrach <pun.butrach@gmail.com>
655 lines
27 KiB
Java
655 lines
27 KiB
Java
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.launcher3.popup;
|
|
|
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
|
|
import static com.android.launcher3.Utilities.squaredHypot;
|
|
import static com.android.launcher3.Utilities.squaredTouchSlop;
|
|
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
|
|
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
|
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
|
|
|
import android.animation.AnimatorSet;
|
|
import android.animation.LayoutTransition;
|
|
import android.content.Context;
|
|
import android.graphics.Point;
|
|
import android.graphics.PointF;
|
|
import android.graphics.Rect;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.util.AttributeSet;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
|
|
import androidx.annotation.LayoutRes;
|
|
|
|
import com.android.launcher3.AbstractFloatingView;
|
|
import com.android.launcher3.BaseDraggingActivity;
|
|
import com.android.launcher3.BubbleTextView;
|
|
import com.android.launcher3.DragSource;
|
|
import com.android.launcher3.DropTarget;
|
|
import com.android.launcher3.DropTarget.DragObject;
|
|
import com.android.launcher3.Flags;
|
|
import com.android.launcher3.Launcher;
|
|
import com.android.launcher3.R;
|
|
import com.android.launcher3.Utilities;
|
|
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
|
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
|
|
import com.android.launcher3.dragndrop.DragController;
|
|
import com.android.launcher3.dragndrop.DragOptions;
|
|
import com.android.launcher3.dragndrop.DragView;
|
|
import com.android.launcher3.dragndrop.DraggableView;
|
|
import com.android.launcher3.model.data.ItemInfo;
|
|
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
|
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
|
import com.android.launcher3.shortcuts.DeepShortcutView;
|
|
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
|
import com.android.launcher3.touch.ItemLongClickListener;
|
|
import com.android.launcher3.util.PackageUserKey;
|
|
import com.android.launcher3.util.ShortcutUtil;
|
|
import com.android.launcher3.views.ActivityContext;
|
|
import com.android.launcher3.views.BaseDragLayer;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* A container for shortcuts to deep links associated with an app.
|
|
*
|
|
* @param <T> The activity on with the popup shows
|
|
*/
|
|
public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
|
extends ArrowPopup<T> implements DragSource, DragController.DragListener {
|
|
|
|
private final List<DeepShortcutView> mDeepShortcuts = new ArrayList<>();
|
|
private final PointF mInterceptTouchDown = new PointF();
|
|
|
|
private final int mStartDragThreshold;
|
|
|
|
private static final int SHORTCUT_COLLAPSE_THRESHOLD = 6;
|
|
|
|
private final float mShortcutHeight;
|
|
|
|
private BubbleTextView mOriginalIcon;
|
|
private int mContainerWidth;
|
|
|
|
private ViewGroup mWidgetContainer;
|
|
private ViewGroup mDeepShortcutContainer;
|
|
private ViewGroup mSystemShortcutContainer;
|
|
|
|
protected PopupItemDragHandler mPopupItemDragHandler;
|
|
protected LauncherAccessibilityDelegate mAccessibilityDelegate;
|
|
|
|
public PopupContainerWithArrow(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
mStartDragThreshold = getResources().getDimensionPixelSize(
|
|
R.dimen.deep_shortcuts_start_drag_threshold);
|
|
mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
|
|
mShortcutHeight = getResources().getDimension(R.dimen.system_shortcut_header_height);
|
|
}
|
|
|
|
public PopupContainerWithArrow(Context context, AttributeSet attrs) {
|
|
this(context, attrs, 0);
|
|
}
|
|
|
|
public PopupContainerWithArrow(Context context) {
|
|
this(context, null, 0);
|
|
}
|
|
|
|
@Override
|
|
protected View getAccessibilityInitialFocusView() {
|
|
if (mSystemShortcutContainer != null) {
|
|
return mSystemShortcutContainer.getChildAt(0);
|
|
}
|
|
return super.getAccessibilityInitialFocusView();
|
|
}
|
|
|
|
public LauncherAccessibilityDelegate getAccessibilityDelegate() {
|
|
return mAccessibilityDelegate;
|
|
}
|
|
|
|
@Override
|
|
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
|
mInterceptTouchDown.set(ev.getX(), ev.getY());
|
|
}
|
|
// Stop sending touch events to deep shortcut views if user moved beyond touch slop.
|
|
return squaredHypot(mInterceptTouchDown.x - ev.getX(), mInterceptTouchDown.y - ev.getY())
|
|
> squaredTouchSlop(getContext());
|
|
}
|
|
|
|
@Override
|
|
protected boolean isOfType(int type) {
|
|
return (type & TYPE_ACTION_POPUP) != 0;
|
|
}
|
|
|
|
public OnClickListener getItemClickListener() {
|
|
return (view) -> {
|
|
mActivityContext.getItemOnClickListener().onClick(view);
|
|
};
|
|
}
|
|
|
|
public void setPopupItemDragHandler(PopupItemDragHandler popupItemDragHandler) {
|
|
mPopupItemDragHandler = popupItemDragHandler;
|
|
}
|
|
|
|
public PopupItemDragHandler getItemDragHandler() {
|
|
return mPopupItemDragHandler;
|
|
}
|
|
|
|
@Override
|
|
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
|
BaseDragLayer dl = getPopupContainer();
|
|
if (!dl.isEventOverView(this, ev)) {
|
|
// TODO: add WW log if want to log if tap closed deep shortcut container.
|
|
close(true);
|
|
|
|
// We let touches on the original icon go through so that users can launch
|
|
// the app with one tap if they don't find a shortcut they want.
|
|
return mOriginalIcon == null || !dl.isEventOverView(mOriginalIcon, ev);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if we can show the container.
|
|
*
|
|
* @deprecated Left here since some dependent projects are using this method
|
|
*/
|
|
@Deprecated
|
|
public static boolean canShow(View icon, ItemInfo item) {
|
|
return icon instanceof BubbleTextView && ShortcutUtil.supportsShortcuts(item);
|
|
}
|
|
|
|
/**
|
|
* Shows a popup with shortcuts associated with a Launcher icon
|
|
* @param icon the app icon to show the popup for
|
|
* @return the container if shown or null.
|
|
*/
|
|
public static PopupContainerWithArrow<Launcher> showForIcon(BubbleTextView icon) {
|
|
Launcher launcher = Launcher.getLauncher(icon.getContext());
|
|
if (getOpen(launcher) != null) {
|
|
// There is already an items container open, so don't open this one.
|
|
icon.clearFocus();
|
|
return null;
|
|
}
|
|
ItemInfo item = (ItemInfo) icon.getTag();
|
|
if (!ShortcutUtil.supportsShortcuts(item)) {
|
|
return null;
|
|
}
|
|
|
|
PopupContainerWithArrow<Launcher> container;
|
|
PopupDataProvider popupDataProvider = launcher.getPopupDataProvider();
|
|
int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item);
|
|
List<SystemShortcut> systemShortcuts = launcher.getSupportedShortcuts()
|
|
.map(s -> s.getShortcut(launcher, item, icon))
|
|
.filter(Objects::nonNull)
|
|
.collect(Collectors.toList());
|
|
container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
|
|
R.layout.popup_container, launcher.getDragLayer(), false);
|
|
container.configureForLauncher(launcher, item);
|
|
container.populateAndShowRows(icon, deepShortcutCount, systemShortcuts);
|
|
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
|
|
container.requestFocus();
|
|
return container;
|
|
}
|
|
|
|
private void configureForLauncher(Launcher launcher, ItemInfo itemInfo) {
|
|
addOnAttachStateChangeListener(new LauncherPopupLiveUpdateHandler(
|
|
launcher, (PopupContainerWithArrow<Launcher>) this));
|
|
if (!Flags.privateSpaceRestrictItemDrag()
|
|
|| !(itemInfo instanceof ItemInfoWithIcon itemInfoWithIcon)
|
|
|| (itemInfoWithIcon.runtimeStatusFlags & FLAG_NOT_PINNABLE) == 0) {
|
|
mPopupItemDragHandler = new LauncherPopupItemDragHandler(launcher, this);
|
|
}
|
|
mAccessibilityDelegate = new ShortcutMenuAccessibilityDelegate(launcher);
|
|
launcher.getDragController().addDragListener(this);
|
|
}
|
|
|
|
/**
|
|
* Populate and show shortcuts for the Launcher U app shortcut design.
|
|
* Will inflate the container and shortcut View instances for the popup container.
|
|
* @param originalIcon App icon that the popup is shown for
|
|
* @param deepShortcutCount Number of DeepShortcutView instances to add to container
|
|
* @param systemShortcuts List of SystemShortcuts to add to container
|
|
*/
|
|
public void populateAndShowRows(final BubbleTextView originalIcon,
|
|
int deepShortcutCount, List<SystemShortcut> systemShortcuts) {
|
|
|
|
mOriginalIcon = originalIcon;
|
|
mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
|
|
|
|
if (deepShortcutCount > 0) {
|
|
addAllShortcuts(deepShortcutCount, systemShortcuts);
|
|
} else if (!systemShortcuts.isEmpty()) {
|
|
addSystemShortcuts(systemShortcuts,
|
|
R.layout.system_shortcut_rows_container,
|
|
R.layout.system_shortcut);
|
|
}
|
|
show();
|
|
loadAppShortcuts((ItemInfo) originalIcon.getTag());
|
|
}
|
|
|
|
/**
|
|
* Animates and loads shortcuts on background thread for this popup container
|
|
*/
|
|
private void loadAppShortcuts(ItemInfo originalItemInfo) {
|
|
if (Utilities.ATLEAST_P) {
|
|
setAccessibilityPaneTitle(getTitleForAccessibility());
|
|
}
|
|
mOriginalIcon.setForceHideDot(true);
|
|
// All views are added. Animate layout from now on.
|
|
setLayoutTransition(new LayoutTransition());
|
|
// Load the shortcuts on a background thread and update the container as it animates.
|
|
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
|
|
mActivityContext, originalItemInfo, new Handler(Looper.getMainLooper()),
|
|
this, mDeepShortcuts));
|
|
}
|
|
|
|
/**
|
|
* Adds any Deep Shortcuts, System Shortcuts and the Widget Shortcut to their respective
|
|
* containers
|
|
* @param deepShortcutCount number of DeepShortcutView instances
|
|
* @param systemShortcuts List of SystemShortcuts
|
|
*/
|
|
private void addAllShortcuts(int deepShortcutCount,
|
|
List<SystemShortcut> systemShortcuts) {
|
|
if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) {
|
|
// add all system shortcuts including widgets shortcut to same container
|
|
addSystemShortcuts(systemShortcuts,
|
|
R.layout.system_shortcut_rows_container,
|
|
R.layout.system_shortcut);
|
|
float currentHeight = (mShortcutHeight * systemShortcuts.size())
|
|
+ mChildContainerMargin;
|
|
addDeepShortcuts(deepShortcutCount, currentHeight);
|
|
return;
|
|
}
|
|
|
|
float currentHeight = mShortcutHeight + mChildContainerMargin;
|
|
List<SystemShortcut> nonWidgetSystemShortcuts =
|
|
getNonWidgetSystemShortcuts(systemShortcuts);
|
|
// If total shortcuts over threshold, collapse system shortcuts to single row
|
|
addSystemShortcutsIconsOnly(nonWidgetSystemShortcuts);
|
|
// May need to recalculate row width
|
|
mContainerWidth = Math.max(mContainerWidth,
|
|
nonWidgetSystemShortcuts.size() * getResources()
|
|
.getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size));
|
|
// Add widget shortcut to separate container
|
|
Optional<SystemShortcut.Widgets> widgetShortcutOpt = getWidgetShortcut(systemShortcuts);
|
|
if (widgetShortcutOpt.isPresent()) {
|
|
mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container_material_u,
|
|
this);
|
|
initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
|
|
currentHeight += mShortcutHeight + mChildContainerMargin;
|
|
}
|
|
addDeepShortcuts(deepShortcutCount, currentHeight);
|
|
}
|
|
|
|
/**
|
|
* Finds the first instance of the Widgets Shortcut from the SystemShortcut List
|
|
* @param systemShortcuts List of SystemShortcut instances to search
|
|
* @return Optional Widgets SystemShortcut
|
|
*/
|
|
private static Optional<SystemShortcut.Widgets> getWidgetShortcut(
|
|
List<SystemShortcut> systemShortcuts) {
|
|
return systemShortcuts
|
|
.stream()
|
|
.filter(shortcut -> shortcut instanceof SystemShortcut.Widgets)
|
|
.map(SystemShortcut.Widgets.class::cast)
|
|
.findFirst();
|
|
}
|
|
|
|
/**
|
|
* Returns list of [systemShortcuts] without the Widgets shortcut instance if found
|
|
* @param systemShortcuts list of SystemShortcuts to filter from
|
|
* @return systemShortcuts without the Widgets Shortcut
|
|
*/
|
|
private static List<SystemShortcut> getNonWidgetSystemShortcuts(
|
|
List<SystemShortcut> systemShortcuts) {
|
|
|
|
return systemShortcuts
|
|
.stream()
|
|
.filter(shortcut -> !(shortcut instanceof SystemShortcut.Widgets))
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
/**
|
|
* Inflates the given systemShortcutContainerLayout as a container, and populates with
|
|
* the systemShortcuts as views using the systemShortcutLayout
|
|
* @param systemShortcuts List of SystemShortcut to inflate as Views
|
|
* @param systemShortcutContainerLayout Layout Resource for the Container of shortcut Views
|
|
* @param systemShortcutLayout Layout Resource for the individual shortcut Views
|
|
*/
|
|
private void addSystemShortcuts(List<SystemShortcut> systemShortcuts,
|
|
@LayoutRes int systemShortcutContainerLayout, @LayoutRes int systemShortcutLayout) {
|
|
|
|
if (systemShortcuts.size() == 0) {
|
|
return;
|
|
}
|
|
mSystemShortcutContainer = inflateAndAdd(systemShortcutContainerLayout, this);
|
|
mWidgetContainer = mSystemShortcutContainer;
|
|
for (int i = 0; i < systemShortcuts.size(); i++) {
|
|
initializeSystemShortcut(
|
|
systemShortcutLayout,
|
|
mSystemShortcutContainer,
|
|
systemShortcuts.get(i),
|
|
i < systemShortcuts.size() - 1);
|
|
}
|
|
}
|
|
|
|
private void addSystemShortcutsIconsOnly(List<SystemShortcut> systemShortcuts) {
|
|
if (systemShortcuts.size() == 0) {
|
|
return;
|
|
}
|
|
|
|
mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this);
|
|
|
|
for (int i = 0; i < systemShortcuts.size(); i++) {
|
|
@LayoutRes int shortcutIconLayout = R.layout.system_shortcut_icon_only;
|
|
boolean shouldAppendSpacer = true;
|
|
|
|
if (i == 0) {
|
|
shortcutIconLayout = R.layout.system_shortcut_icon_only_start;
|
|
} else if (i == systemShortcuts.size() - 1) {
|
|
shortcutIconLayout = R.layout.system_shortcut_icon_only_end;
|
|
shouldAppendSpacer = false;
|
|
}
|
|
initializeSystemShortcut(
|
|
shortcutIconLayout,
|
|
mSystemShortcutContainer,
|
|
systemShortcuts.get(i),
|
|
shouldAppendSpacer);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inflates and adds [deepShortcutCount] number of DeepShortcutView for the to a new container
|
|
* @param deepShortcutCount number of DeepShortcutView instances to add
|
|
* @param currentHeight height of popup before adding deep shortcuts
|
|
*/
|
|
private void addDeepShortcuts(int deepShortcutCount, float currentHeight) {
|
|
mDeepShortcutContainer = inflateAndAdd(R.layout.deep_shortcut_container, this);
|
|
for (int i = deepShortcutCount; i > 0; i--) {
|
|
currentHeight += mShortcutHeight;
|
|
// when there is limited vertical screen space, limit total popup rows to fit
|
|
if (currentHeight >= mActivityContext.getDeviceProfile().availableHeightPx) break;
|
|
DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut,
|
|
mDeepShortcutContainer);
|
|
v.getLayoutParams().width = mContainerWidth;
|
|
mDeepShortcuts.add(v);
|
|
}
|
|
updateHiddenShortcuts();
|
|
}
|
|
|
|
protected BubbleTextView getOriginalIcon() {
|
|
return mOriginalIcon;
|
|
}
|
|
|
|
protected ViewGroup getSystemShortcutContainer() {
|
|
return mSystemShortcutContainer;
|
|
}
|
|
|
|
protected ViewGroup getWidgetContainer() {
|
|
return mWidgetContainer;
|
|
}
|
|
|
|
protected void setWidgetContainer(ViewGroup widgetContainer) {
|
|
mWidgetContainer = widgetContainer;
|
|
}
|
|
|
|
private String getTitleForAccessibility() {
|
|
return getContext().getString(R.string.action_deep_shortcut);
|
|
}
|
|
|
|
@Override
|
|
protected void getTargetObjectLocation(Rect outPos) {
|
|
getPopupContainer().getDescendantRectRelativeToSelf(mOriginalIcon, outPos);
|
|
outPos.top += mOriginalIcon.getPaddingTop();
|
|
outPos.left += mOriginalIcon.getPaddingLeft();
|
|
outPos.right -= mOriginalIcon.getPaddingRight();
|
|
outPos.bottom = outPos.top + (mOriginalIcon.getIcon() != null
|
|
? mOriginalIcon.getIcon().getBounds().height()
|
|
: mOriginalIcon.getHeight());
|
|
}
|
|
|
|
protected void updateHiddenShortcuts() {
|
|
int total = mDeepShortcuts.size();
|
|
for (int i = 0; i < total; i++) {
|
|
DeepShortcutView view = mDeepShortcuts.get(i);
|
|
view.setVisibility(i >= MAX_SHORTCUTS ? GONE : VISIBLE);
|
|
}
|
|
}
|
|
|
|
protected void initializeWidgetShortcut(ViewGroup container, SystemShortcut info) {
|
|
View view = initializeSystemShortcut(R.layout.system_shortcut, container, info, false);
|
|
view.getLayoutParams().width = mContainerWidth;
|
|
}
|
|
|
|
/**
|
|
* Initializes and adds View for given SystemShortcut to a container.
|
|
* @param resId Resource id to use for SystemShortcut View.
|
|
* @param container ViewGroup to add the shortcut View to as a parent
|
|
* @param info The SystemShortcut instance to create a View for.
|
|
* @param shouldAppendSpacer If True, will add a spacer after the shortcut, when showing the
|
|
* SystemShortcut as an icon only. Used to space the shortcut icons
|
|
* evenly.
|
|
* @return The view inflated for the SystemShortcut
|
|
*/
|
|
protected View initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info,
|
|
boolean shouldAppendSpacer) {
|
|
View view = inflateAndAdd(resId, container);
|
|
if (view instanceof DeepShortcutView) {
|
|
// System shortcut takes entire row with icon and text
|
|
final DeepShortcutView shortcutView = (DeepShortcutView) view;
|
|
info.setIconAndLabelFor(shortcutView.getIconView(), shortcutView.getBubbleText());
|
|
} else if (view instanceof ImageView) {
|
|
// System shortcut is just an icon
|
|
info.setIconAndContentDescriptionFor((ImageView) view);
|
|
if (shouldAppendSpacer) inflateAndAdd(R.layout.system_shortcut_spacer, container);
|
|
view.setTooltipText(view.getContentDescription());
|
|
}
|
|
view.setTag(info);
|
|
view.setOnClickListener(info);
|
|
return view;
|
|
}
|
|
|
|
/**
|
|
* Determines when the deferred drag should be started.
|
|
*
|
|
* Current behavior:
|
|
* - Start the drag if the touch passes a certain distance from the original touch down.
|
|
*/
|
|
public DragOptions.PreDragCondition createPreDragCondition(boolean updateIconUi) {
|
|
return new DragOptions.PreDragCondition() {
|
|
|
|
@Override
|
|
public boolean shouldStartDrag(double distanceDragged) {
|
|
return distanceDragged > mStartDragThreshold;
|
|
}
|
|
|
|
@Override
|
|
public void onPreDragStart(DropTarget.DragObject dragObject) {
|
|
if (!updateIconUi) {
|
|
return;
|
|
}
|
|
if (mIsAboveIcon) {
|
|
// Hide only the icon, keep the text visible.
|
|
mOriginalIcon.setIconVisible(false);
|
|
mOriginalIcon.setVisibility(VISIBLE);
|
|
} else {
|
|
// Hide both the icon and text.
|
|
mOriginalIcon.setVisibility(INVISIBLE);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
|
|
if (!updateIconUi) {
|
|
return;
|
|
}
|
|
mOriginalIcon.setIconVisible(true);
|
|
if (dragStarted) {
|
|
// Make sure we keep the original icon hidden while it is being dragged.
|
|
mOriginalIcon.setVisibility(INVISIBLE);
|
|
} else {
|
|
// TODO: add WW logging if want to add logging for long press on popup
|
|
// container.
|
|
// mLauncher.getUserEventDispatcher().logDeepShortcutsOpen(mOriginalIcon);
|
|
if (!mIsAboveIcon) {
|
|
// Show the icon but keep the text hidden.
|
|
mOriginalIcon.setVisibility(VISIBLE);
|
|
mOriginalIcon.setTextVisibility(false);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void onDropCompleted(View target, DragObject d, boolean success) { }
|
|
|
|
@Override
|
|
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
|
|
// Either the original icon or one of the shortcuts was dragged.
|
|
// Hide the container, but don't remove it yet because that interferes with touch events.
|
|
mDeferContainerRemoval = true;
|
|
animateClose();
|
|
}
|
|
|
|
@Override
|
|
public void onDragEnd() {
|
|
if (!mIsOpen) {
|
|
if (mOpenCloseAnimator != null) {
|
|
// Close animation is running.
|
|
mDeferContainerRemoval = false;
|
|
} else {
|
|
// Close animation is not running.
|
|
if (mDeferContainerRemoval) {
|
|
closeComplete();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onCreateCloseAnimation(AnimatorSet anim) {
|
|
// Animate original icon's text back in.
|
|
anim.play(mOriginalIcon.createTextAlphaAnimator(true /* fadeIn */));
|
|
mOriginalIcon.setForceHideDot(false);
|
|
}
|
|
|
|
@Override
|
|
protected void closeComplete() {
|
|
super.closeComplete();
|
|
if (mActivityContext.getDragController() != null) {
|
|
mActivityContext.getDragController().removeDragListener(this);
|
|
}
|
|
PopupContainerWithArrow openPopup = getOpen(mActivityContext);
|
|
if (openPopup == null || openPopup.mOriginalIcon != mOriginalIcon) {
|
|
mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible());
|
|
mOriginalIcon.setForceHideDot(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a PopupContainerWithArrow which is already open or null
|
|
*/
|
|
public static <T extends Context & ActivityContext> PopupContainerWithArrow getOpen(T context) {
|
|
return getOpenView(context, TYPE_ACTION_POPUP);
|
|
}
|
|
|
|
/**
|
|
* Dismisses the popup if it is no longer valid
|
|
*/
|
|
public static void dismissInvalidPopup(BaseDraggingActivity activity) {
|
|
PopupContainerWithArrow popup = getOpen(activity);
|
|
if (popup != null && (!popup.mOriginalIcon.isAttachedToWindow()
|
|
|| !ShortcutUtil.supportsShortcuts((ItemInfo) popup.mOriginalIcon.getTag()))) {
|
|
popup.animateClose();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handler to control drag-and-drop for popup items
|
|
*/
|
|
public interface PopupItemDragHandler extends OnLongClickListener, OnTouchListener { }
|
|
|
|
/**
|
|
* Drag and drop handler for popup items in Launcher activity
|
|
*/
|
|
public static class LauncherPopupItemDragHandler implements PopupItemDragHandler {
|
|
|
|
protected final Point mIconLastTouchPos = new Point();
|
|
private final Launcher mLauncher;
|
|
private final PopupContainerWithArrow mContainer;
|
|
|
|
LauncherPopupItemDragHandler(Launcher launcher, PopupContainerWithArrow container) {
|
|
mLauncher = launcher;
|
|
mContainer = container;
|
|
}
|
|
|
|
@Override
|
|
public boolean onTouch(View v, MotionEvent ev) {
|
|
// Touched a shortcut, update where it was touched so we can drag from there on
|
|
// long click.
|
|
switch (ev.getAction()) {
|
|
case MotionEvent.ACTION_DOWN:
|
|
case MotionEvent.ACTION_MOVE:
|
|
mIconLastTouchPos.set((int) ev.getX(), (int) ev.getY());
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean onLongClick(View v) {
|
|
if (!ItemLongClickListener.canStartDrag(mLauncher)) return false;
|
|
// Return early if not the correct view
|
|
if (!(v.getParent() instanceof DeepShortcutView)) return false;
|
|
|
|
// Long clicked on a shortcut.
|
|
DeepShortcutView sv = (DeepShortcutView) v.getParent();
|
|
sv.setWillDrawIcon(false);
|
|
|
|
// Move the icon to align with the center-top of the touch point
|
|
Point iconShift = new Point();
|
|
iconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x;
|
|
iconShift.y = mIconLastTouchPos.y - mLauncher.getDeviceProfile().iconSizePx;
|
|
|
|
DraggableView draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_ICON);
|
|
WorkspaceItemInfo itemInfo = sv.getFinalInfo();
|
|
itemInfo.container = CONTAINER_SHORTCUTS;
|
|
DragView dv = mLauncher.getWorkspace().beginDragShared(sv.getIconView(), draggableView,
|
|
mContainer, itemInfo,
|
|
new ShortcutDragPreviewProvider(sv.getIconView(), iconShift),
|
|
new DragOptions());
|
|
dv.animateShift(-iconShift.x, -iconShift.y);
|
|
|
|
// TODO: support dragging from within folder without having to close it
|
|
AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_FOLDER);
|
|
return false;
|
|
}
|
|
}
|
|
}
|