blob: 4255fa46647e866fafb4bc3c4951f6458bf60c92 [file] [log] [blame]
Sunny Goyal71b5c0b2015-01-08 16:59:04 -08001package com.android.launcher3;
2
3import android.annotation.TargetApi;
Adam Cohenc9735cf2015-01-23 16:11:55 -08004import android.graphics.Rect;
Sunny Goyal71b5c0b2015-01-08 16:59:04 -08005import android.os.Build;
6import android.os.Bundle;
Sunny Goyal1a70cef2015-04-22 11:29:51 -07007import android.text.TextUtils;
Sunny Goyal71b5c0b2015-01-08 16:59:04 -08008import android.util.SparseArray;
9import android.view.View;
10import android.view.View.AccessibilityDelegate;
11import android.view.accessibility.AccessibilityNodeInfo;
12import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
13
14import com.android.launcher3.LauncherModel.ScreenPosProvider;
Adam Cohen091440a2015-03-18 14:16:05 -070015import com.android.launcher3.util.Thunk;
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080016
17import java.util.ArrayList;
18
19@TargetApi(Build.VERSION_CODES.LOLLIPOP)
20public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
21
22 public static final int REMOVE = R.id.action_remove;
23 public static final int INFO = R.id.action_info;
24 public static final int UNINSTALL = R.id.action_uninstall;
25 public static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
Adam Cohenc9735cf2015-01-23 16:11:55 -080026 public static final int MOVE = R.id.action_move;
27
Sunny Goyale9b651e2015-04-24 11:44:51 -070028 public enum DragType {
Adam Cohenc9735cf2015-01-23 16:11:55 -080029 ICON,
30 FOLDER,
31 WIDGET
32 }
33
34 public static class DragInfo {
Sunny Goyale9b651e2015-04-24 11:44:51 -070035 public DragType dragType;
36 public ItemInfo info;
37 public View item;
Adam Cohenc9735cf2015-01-23 16:11:55 -080038 }
39
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080040 private final SparseArray<AccessibilityAction> mActions =
41 new SparseArray<AccessibilityAction>();
Adam Cohen091440a2015-03-18 14:16:05 -070042 @Thunk final Launcher mLauncher;
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080043
Sunny Goyale9b651e2015-04-24 11:44:51 -070044 private DragInfo mDragInfo = null;
45 private AccessibilityDragSource mDragSource = null;
46
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080047 public LauncherAccessibilityDelegate(Launcher launcher) {
48 mLauncher = launcher;
49
50 mActions.put(REMOVE, new AccessibilityAction(REMOVE,
51 launcher.getText(R.string.delete_target_label)));
52 mActions.put(INFO, new AccessibilityAction(INFO,
53 launcher.getText(R.string.info_target_label)));
54 mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
55 launcher.getText(R.string.delete_target_uninstall_label)));
56 mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
57 launcher.getText(R.string.action_add_to_workspace)));
Adam Cohenc9735cf2015-01-23 16:11:55 -080058 mActions.put(MOVE, new AccessibilityAction(MOVE,
59 launcher.getText(R.string.action_move)));
60
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080061 }
62
63 @Override
64 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
65 super.onInitializeAccessibilityNodeInfo(host, info);
66 if (!(host.getTag() instanceof ItemInfo)) return;
67 ItemInfo item = (ItemInfo) host.getTag();
68
Sunny Goyal1a70cef2015-04-22 11:29:51 -070069 if (DeleteDropTarget.supportsDrop(item)) {
70 info.addAction(mActions.get(REMOVE));
71 }
72 if (UninstallDropTarget.supportsDrop(host.getContext(), item)) {
73 info.addAction(mActions.get(UNINSTALL));
74 }
75 if (InfoDropTarget.supportsDrop(host.getContext(), item)) {
76 info.addAction(mActions.get(INFO));
77 }
78
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080079 if ((item instanceof ShortcutInfo)
80 || (item instanceof LauncherAppWidgetInfo)
81 || (item instanceof FolderInfo)) {
Adam Cohenc9735cf2015-01-23 16:11:55 -080082 info.addAction(mActions.get(MOVE));
Sunny Goyal1a70cef2015-04-22 11:29:51 -070083 } if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) {
Sunny Goyal71b5c0b2015-01-08 16:59:04 -080084 info.addAction(mActions.get(ADD_TO_WORKSPACE));
85 }
86 }
87
88 @Override
89 public boolean performAccessibilityAction(View host, int action, Bundle args) {
90 if ((host.getTag() instanceof ItemInfo)
91 && performAction(host, (ItemInfo) host.getTag(), action)) {
92 return true;
93 }
94 return super.performAccessibilityAction(host, action, args);
95 }
96
97 public boolean performAction(View host, ItemInfo item, int action) {
98 if (action == REMOVE) {
Adam Cohenc9735cf2015-01-23 16:11:55 -080099 if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) {
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700100 announceConfirmation(R.string.item_removed);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800101 return true;
102 }
103 return false;
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800104 } else if (action == INFO) {
105 InfoDropTarget.startDetailsActivityForInfo(item, mLauncher);
106 return true;
107 } else if (action == UNINSTALL) {
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700108 return UninstallDropTarget.startUninstallActivity(mLauncher, item);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800109 } else if (action == MOVE) {
110 beginAccessibleDrag(host, item);
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800111 } else if (action == ADD_TO_WORKSPACE) {
112 final int preferredPage = mLauncher.getWorkspace().getCurrentPage();
113 final ScreenPosProvider screenProvider = new ScreenPosProvider() {
114
115 @Override
116 public int getScreenIndex(ArrayList<Long> screenIDs) {
117 return preferredPage;
118 }
119 };
120 if (item instanceof AppInfo) {
121 final ArrayList<ItemInfo> addShortcuts = new ArrayList<ItemInfo>();
122 addShortcuts.add(((AppInfo) item).makeShortcut());
123 mLauncher.showWorkspace(true, new Runnable() {
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800124 @Override
125 public void run() {
Sunny Goyal18bf8e22015-04-08 18:13:46 -0700126 mLauncher.getModel().addAndBindAddedWorkspaceItems(
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800127 mLauncher, addShortcuts, screenProvider, 0, true);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800128 announceConfirmation(R.string.item_added_to_workspace);
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800129 }
130 });
131 return true;
132 } else if (item instanceof PendingAddItemInfo) {
133 mLauncher.getModel().addAndBindPendingItem(
134 mLauncher, (PendingAddItemInfo) item, screenProvider, 0);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800135 announceConfirmation(R.string.item_added_to_workspace);
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800136 return true;
137 }
138 }
139 return false;
140 }
Adam Cohenc9735cf2015-01-23 16:11:55 -0800141
Adam Cohen091440a2015-03-18 14:16:05 -0700142 @Thunk void announceConfirmation(int resId) {
Adam Cohenc9735cf2015-01-23 16:11:55 -0800143 announceConfirmation(mLauncher.getResources().getString(resId));
144 }
145
Adam Cohen091440a2015-03-18 14:16:05 -0700146 @Thunk void announceConfirmation(String confirmation) {
Adam Cohenc9735cf2015-01-23 16:11:55 -0800147 mLauncher.getDragLayer().announceForAccessibility(confirmation);
148
149 }
150
151 public boolean isInAccessibleDrag() {
152 return mDragInfo != null;
153 }
154
155 public DragInfo getDragInfo() {
156 return mDragInfo;
157 }
158
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700159 /**
160 * @param clickedTarget the actual view that was clicked
161 * @param dropLocation relative to {@param clickedTarget}. If provided, its center is used
162 * as the actual drop location otherwise the views center is used.
163 */
164 public void handleAccessibleDrop(View clickedTarget, Rect dropLocation,
Adam Cohenc9735cf2015-01-23 16:11:55 -0800165 String confirmation) {
166 if (!isInAccessibleDrag()) return;
167
168 int[] loc = new int[2];
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700169 if (dropLocation == null) {
170 loc[0] = clickedTarget.getWidth() / 2;
171 loc[1] = clickedTarget.getHeight() / 2;
172 } else {
173 loc[0] = dropLocation.centerX();
174 loc[1] = dropLocation.centerY();
175 }
Adam Cohenc9735cf2015-01-23 16:11:55 -0800176
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700177 mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(clickedTarget, loc);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800178 mLauncher.getDragController().completeAccessibleDrag(loc);
179
180 endAccessibleDrag();
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700181 if (!TextUtils.isEmpty(confirmation)) {
182 announceConfirmation(confirmation);
183 }
Adam Cohenc9735cf2015-01-23 16:11:55 -0800184 }
185
186 public void beginAccessibleDrag(View item, ItemInfo info) {
187 mDragInfo = new DragInfo();
188 mDragInfo.info = info;
189 mDragInfo.item = item;
190 mDragInfo.dragType = DragType.ICON;
191 if (info instanceof FolderInfo) {
192 mDragInfo.dragType = DragType.FOLDER;
193 } else if (info instanceof LauncherAppWidgetInfo) {
194 mDragInfo.dragType = DragType.WIDGET;
195 }
196
197 CellLayout.CellInfo cellInfo = new CellLayout.CellInfo(item, info);
198
199 Rect pos = new Rect();
200 mLauncher.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800201 mLauncher.getDragController().prepareAccessibleDrag(pos.centerX(), pos.centerY());
Sunny Goyale9b651e2015-04-24 11:44:51 -0700202
203 Workspace workspace = mLauncher.getWorkspace();
204
205 Folder folder = workspace.getOpenFolder();
206 if (folder != null) {
207 if (folder.getItemsInReadingOrder().contains(item)) {
208 mDragSource = folder;
209 } else {
210 mLauncher.closeFolder();
211 }
212 }
213 if (mDragSource == null) {
214 mDragSource = workspace;
215 }
216 mDragSource.enableAccessibleDrag(true);
217 mDragSource.startDrag(cellInfo, true);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800218 }
219
220 public boolean onBackPressed() {
221 if (isInAccessibleDrag()) {
222 cancelAccessibleDrag();
223 return true;
224 }
225 return false;
226 }
227
228 private void cancelAccessibleDrag() {
229 mLauncher.getDragController().cancelDrag();
230 endAccessibleDrag();
231 }
232
233 private void endAccessibleDrag() {
234 mDragInfo = null;
Sunny Goyale9b651e2015-04-24 11:44:51 -0700235 if (mDragSource != null) {
236 mDragSource.enableAccessibleDrag(false);
237 mDragSource = null;
238 }
239 }
240
241 public static interface AccessibilityDragSource {
242 void startDrag(CellLayout.CellInfo cellInfo, boolean accessible);
243
244 void enableAccessibleDrag(boolean enable);
Adam Cohenc9735cf2015-01-23 16:11:55 -0800245 }
Sunny Goyal71b5c0b2015-01-08 16:59:04 -0800246}