/* * Copyright (C) 2015 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.accessibility; import android.text.TextUtils; import android.view.View; import com.android.launcher3.AppInfo; import com.android.launcher3.CellLayout; import com.android.launcher3.FolderInfo; import com.android.launcher3.ItemInfo; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DragType; import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; /** * Implementation of {@link DragAndDropAccessibilityDelegate} to support DnD on workspace. */ public class WorkspaceAccessibilityHelper extends DragAndDropAccessibilityDelegate { public WorkspaceAccessibilityHelper(CellLayout layout) { super(layout); } /** * Find the virtual view id corresponding to the top left corner of any drop region by which * the passed id is contained. For an icon, this is simply */ @Override protected int intersectsValidDropTarget(int id) { int mCountX = mView.getCountX(); int mCountY = mView.getCountY(); int x = id % mCountX; int y = id / mCountX; LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo(); if (dragInfo.dragType == DragType.WIDGET && mView.isHotseat()) { return INVALID_POSITION; } if (dragInfo.dragType == DragType.WIDGET) { // For a widget, every cell must be vacant. In addition, we will return any valid // drop target by which the passed id is contained. boolean fits = false; // These represent the amount that we can back off if we hit a problem. They // get consumed as we move up and to the right, trying new regions. int spanX = dragInfo.info.spanX; int spanY = dragInfo.info.spanY; for (int m = 0; m < spanX; m++) { for (int n = 0; n < spanY; n++) { fits = true; int x0 = x - m; int y0 = y - n; if (x0 < 0 || y0 < 0) continue; for (int i = x0; i < x0 + spanX; i++) { if (!fits) break; for (int j = y0; j < y0 + spanY; j++) { if (i >= mCountX || j >= mCountY || mView.isOccupied(i, j)) { fits = false; break; } } } if (fits) { return x0 + mCountX * y0; } } } return INVALID_POSITION; } else { // For an icon, we simply check the view directly below View child = mView.getChildAt(x, y); if (child == null || child == dragInfo.item) { // Empty cell. Good for an icon or folder. return id; } else if (dragInfo.dragType != DragType.FOLDER) { // For icons, we can consider cells that have another icon or a folder. ItemInfo info = (ItemInfo) child.getTag(); if (info instanceof AppInfo || info instanceof FolderInfo || info instanceof ShortcutInfo) { return id; } } return INVALID_POSITION; } } @Override protected String getConfirmationForIconDrop(int id) { int x = id % mView.getCountX(); int y = id / mView.getCountX(); LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo(); View child = mView.getChildAt(x, y); if (child == null || child == dragInfo.item) { return mContext.getString(R.string.item_moved); } else { ItemInfo info = (ItemInfo) child.getTag(); if (info instanceof AppInfo || info instanceof ShortcutInfo) { return mContext.getString(R.string.folder_created); } else if (info instanceof FolderInfo) { return mContext.getString(R.string.added_to_folder); } } return ""; } @Override protected String getLocationDescriptionForIconDrop(int id) { int x = id % mView.getCountX(); int y = id / mView.getCountX(); LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo(); View child = mView.getChildAt(x, y); if (child == null || child == dragInfo.item) { if (mView.isHotseat()) { return mContext.getString(R.string.move_to_hotseat_position, id + 1); } else { return mContext.getString(R.string.move_to_empty_cell, y + 1, x + 1); } } else { ItemInfo info = (ItemInfo) child.getTag(); if (info instanceof ShortcutInfo) { return mContext.getString(R.string.create_folder_with, info.title); } else if (info instanceof FolderInfo) { if (TextUtils.isEmpty(info.title)) { // Find the first item in the folder. FolderInfo folder = (FolderInfo) info; ShortcutInfo firstItem = null; for (ShortcutInfo shortcut : folder.contents) { if (firstItem == null || firstItem.rank > shortcut.rank) { firstItem = shortcut; } } if (firstItem != null) { return mContext.getString(R.string.add_to_folder_with_app, firstItem.title); } } return mContext.getString(R.string.add_to_folder, info.title); } } return ""; } }