Loading res/values/config.xml +1 −0 Original line number Diff line number Diff line Loading @@ -102,4 +102,5 @@ <item type="id" name="action_move_to_workspace" /> <item type="id" name="action_move_screen_backwards" /> <item type="id" name="action_move_screen_forwards" /> <item type="id" name="action_resize" /> </resources> res/values/strings.xml +19 −0 Original line number Diff line number Diff line Loading @@ -252,4 +252,23 @@ <!-- Accessibility confirmation when a screen was moved [DO NOT TRANSLATE] --> <string name="screen_moved">Screen moved</string> <!-- Accessibility action to resize a widget [DO NOT TRANSLATE] --> <string name="action_resize">Resize</string> <!-- Accessibility action to increase width of a widget [DO NOT TRANSLATE] --> <string name="action_increase_width">Increase width</string> <!-- Accessibility action to increase height of a widget [DO NOT TRANSLATE] --> <string name="action_increase_height">Increase height</string> <!-- Accessibility action to decrease width of a widget [DO NOT TRANSLATE] --> <string name="action_decrease_width">Decrease width</string> <!-- Accessibility action to decrease height of a widget [DO NOT TRANSLATE] --> <string name="action_decrease_height">Decrease height</string> <!-- Accessibility confirmation for widget resize [DO NOT TRANSLATE]--> <string name="widget_resized">Widget resized to width <xliff:g id="number" example="2">%1$s</xliff:g> height <xliff:g id="number" example="1">%2$s</xliff:g></string> </resources> src/com/android/launcher3/CellLayout.java +17 −0 Original line number Diff line number Diff line Loading @@ -3051,4 +3051,21 @@ public class CellLayout extends ViewGroup { public boolean findVacantCell(int spanX, int spanY, int[] outXY) { return Utilities.findVacantCell(outXY, spanX, spanY, mCountX, mCountY, mOccupied); } public boolean isRegionVacant(int x, int y, int spanX, int spanY) { int x2 = x + spanX - 1; int y2 = y + spanY - 1; if (x < 0 || y < 0 || x2 >= mCountX || y2 >= mCountY) { return false; } for (int i = x; i <= x2; i++) { for (int j = y; j <= y2; j++) { if (mOccupied[i][j]) { return false; } } } return true; } } src/com/android/launcher3/LauncherAccessibilityDelegate.java +98 −1 Original line number Diff line number Diff line package com.android.launcher3; import android.annotation.TargetApi; import android.app.AlertDialog; import android.appwidget.AppWidgetProviderInfo; import android.content.DialogInterface; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; Loading Loading @@ -28,6 +31,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { private static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace; private static final int MOVE = R.id.action_move; private static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace; private static final int RESIZE = R.id.action_resize; public enum DragType { ICON, Loading Loading @@ -62,6 +66,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { launcher.getText(R.string.action_move))); mActions.put(MOVE_TO_WORKSPACE, new AccessibilityAction(MOVE_TO_WORKSPACE, launcher.getText(R.string.action_move_to_workspace))); mActions.put(RESIZE, new AccessibilityAction(RESIZE, launcher.getText(R.string.action_resize))); } @Override Loading @@ -87,6 +93,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { if (item.container >= 0) { info.addAction(mActions.get(MOVE_TO_WORKSPACE)); } else if (item instanceof LauncherAppWidgetInfo) { if (!getSupportedResizeActions(host, (LauncherAppWidgetInfo) item).isEmpty()) { info.addAction(mActions.get(RESIZE)); } } } if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) { info.addAction(mActions.get(ADD_TO_WORKSPACE)); Loading @@ -102,7 +112,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { return super.performAccessibilityAction(host, action, args); } public boolean performAction(View host, final ItemInfo item, int action) { public boolean performAction(final View host, final ItemInfo item, int action) { if (action == REMOVE) { if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) { announceConfirmation(R.string.item_removed); Loading Loading @@ -167,10 +177,97 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { announceConfirmation(R.string.item_moved); } }); } else if (action == RESIZE) { final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) item; final ArrayList<Integer> actions = getSupportedResizeActions(host, info); CharSequence[] labels = new CharSequence[actions.size()]; for (int i = 0; i < actions.size(); i++) { labels[i] = mLauncher.getText(actions.get(i)); } new AlertDialog.Builder(mLauncher) .setTitle(R.string.action_resize) .setItems(labels, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { performResizeAction(actions.get(which), host, info); dialog.dismiss(); } }) .show(); } return false; } private ArrayList<Integer> getSupportedResizeActions(View host, LauncherAppWidgetInfo info) { AppWidgetProviderInfo providerInfo = ((LauncherAppWidgetHostView) host).getAppWidgetInfo(); ArrayList<Integer> actions = new ArrayList<>(); CellLayout layout = (CellLayout) host.getParent().getParent(); if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) { if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) || layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) { actions.add(R.string.action_increase_width); } if (info.spanX > info.minSpanX && info.spanX > 1) { actions.add(R.string.action_decrease_width); } } if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) { if (layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1) || layout.isRegionVacant(info.cellX, info.cellY - 1, info.spanX, 1)) { actions.add(R.string.action_increase_height); } if (info.spanY > info.minSpanY && info.spanY > 1) { actions.add(R.string.action_decrease_height); } } return actions; } private void performResizeAction(int action, View host, LauncherAppWidgetInfo info) { CellLayout.LayoutParams lp = (CellLayout.LayoutParams) host.getLayoutParams(); CellLayout layout = (CellLayout) host.getParent().getParent(); layout.markCellsAsUnoccupiedForView(host); if (action == R.string.action_increase_width) { if (((host.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) && layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) || !layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY)) { lp.cellX --; info.cellX --; } lp.cellHSpan ++; info.spanX ++; } else if (action == R.string.action_decrease_width) { lp.cellHSpan --; info.spanX --; } else if (action == R.string.action_increase_height) { if (!layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1)) { lp.cellY --; info.cellY --; } lp.cellVSpan ++; info.spanY ++; } else if (action == R.string.action_decrease_height) { lp.cellVSpan --; info.spanY --; } layout.markCellsAsOccupiedForView(host); Rect sizeRange = new Rect(); AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, sizeRange); ((LauncherAppWidgetHostView) host).updateAppWidgetSize(null, sizeRange.left, sizeRange.top, sizeRange.right, sizeRange.bottom); host.requestLayout(); LauncherModel.updateItemInDatabase(mLauncher, info); announceConfirmation(mLauncher.getString(R.string.widget_resized, info.spanX, info.spanY)); } @Thunk void announceConfirmation(int resId) { announceConfirmation(mLauncher.getResources().getString(resId)); } Loading Loading
res/values/config.xml +1 −0 Original line number Diff line number Diff line Loading @@ -102,4 +102,5 @@ <item type="id" name="action_move_to_workspace" /> <item type="id" name="action_move_screen_backwards" /> <item type="id" name="action_move_screen_forwards" /> <item type="id" name="action_resize" /> </resources>
res/values/strings.xml +19 −0 Original line number Diff line number Diff line Loading @@ -252,4 +252,23 @@ <!-- Accessibility confirmation when a screen was moved [DO NOT TRANSLATE] --> <string name="screen_moved">Screen moved</string> <!-- Accessibility action to resize a widget [DO NOT TRANSLATE] --> <string name="action_resize">Resize</string> <!-- Accessibility action to increase width of a widget [DO NOT TRANSLATE] --> <string name="action_increase_width">Increase width</string> <!-- Accessibility action to increase height of a widget [DO NOT TRANSLATE] --> <string name="action_increase_height">Increase height</string> <!-- Accessibility action to decrease width of a widget [DO NOT TRANSLATE] --> <string name="action_decrease_width">Decrease width</string> <!-- Accessibility action to decrease height of a widget [DO NOT TRANSLATE] --> <string name="action_decrease_height">Decrease height</string> <!-- Accessibility confirmation for widget resize [DO NOT TRANSLATE]--> <string name="widget_resized">Widget resized to width <xliff:g id="number" example="2">%1$s</xliff:g> height <xliff:g id="number" example="1">%2$s</xliff:g></string> </resources>
src/com/android/launcher3/CellLayout.java +17 −0 Original line number Diff line number Diff line Loading @@ -3051,4 +3051,21 @@ public class CellLayout extends ViewGroup { public boolean findVacantCell(int spanX, int spanY, int[] outXY) { return Utilities.findVacantCell(outXY, spanX, spanY, mCountX, mCountY, mOccupied); } public boolean isRegionVacant(int x, int y, int spanX, int spanY) { int x2 = x + spanX - 1; int y2 = y + spanY - 1; if (x < 0 || y < 0 || x2 >= mCountX || y2 >= mCountY) { return false; } for (int i = x; i <= x2; i++) { for (int j = y; j <= y2; j++) { if (mOccupied[i][j]) { return false; } } } return true; } }
src/com/android/launcher3/LauncherAccessibilityDelegate.java +98 −1 Original line number Diff line number Diff line package com.android.launcher3; import android.annotation.TargetApi; import android.app.AlertDialog; import android.appwidget.AppWidgetProviderInfo; import android.content.DialogInterface; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; Loading Loading @@ -28,6 +31,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { private static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace; private static final int MOVE = R.id.action_move; private static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace; private static final int RESIZE = R.id.action_resize; public enum DragType { ICON, Loading Loading @@ -62,6 +66,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { launcher.getText(R.string.action_move))); mActions.put(MOVE_TO_WORKSPACE, new AccessibilityAction(MOVE_TO_WORKSPACE, launcher.getText(R.string.action_move_to_workspace))); mActions.put(RESIZE, new AccessibilityAction(RESIZE, launcher.getText(R.string.action_resize))); } @Override Loading @@ -87,6 +93,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { if (item.container >= 0) { info.addAction(mActions.get(MOVE_TO_WORKSPACE)); } else if (item instanceof LauncherAppWidgetInfo) { if (!getSupportedResizeActions(host, (LauncherAppWidgetInfo) item).isEmpty()) { info.addAction(mActions.get(RESIZE)); } } } if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) { info.addAction(mActions.get(ADD_TO_WORKSPACE)); Loading @@ -102,7 +112,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { return super.performAccessibilityAction(host, action, args); } public boolean performAction(View host, final ItemInfo item, int action) { public boolean performAction(final View host, final ItemInfo item, int action) { if (action == REMOVE) { if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) { announceConfirmation(R.string.item_removed); Loading Loading @@ -167,10 +177,97 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate { announceConfirmation(R.string.item_moved); } }); } else if (action == RESIZE) { final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) item; final ArrayList<Integer> actions = getSupportedResizeActions(host, info); CharSequence[] labels = new CharSequence[actions.size()]; for (int i = 0; i < actions.size(); i++) { labels[i] = mLauncher.getText(actions.get(i)); } new AlertDialog.Builder(mLauncher) .setTitle(R.string.action_resize) .setItems(labels, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { performResizeAction(actions.get(which), host, info); dialog.dismiss(); } }) .show(); } return false; } private ArrayList<Integer> getSupportedResizeActions(View host, LauncherAppWidgetInfo info) { AppWidgetProviderInfo providerInfo = ((LauncherAppWidgetHostView) host).getAppWidgetInfo(); ArrayList<Integer> actions = new ArrayList<>(); CellLayout layout = (CellLayout) host.getParent().getParent(); if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) { if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) || layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) { actions.add(R.string.action_increase_width); } if (info.spanX > info.minSpanX && info.spanX > 1) { actions.add(R.string.action_decrease_width); } } if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) { if (layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1) || layout.isRegionVacant(info.cellX, info.cellY - 1, info.spanX, 1)) { actions.add(R.string.action_increase_height); } if (info.spanY > info.minSpanY && info.spanY > 1) { actions.add(R.string.action_decrease_height); } } return actions; } private void performResizeAction(int action, View host, LauncherAppWidgetInfo info) { CellLayout.LayoutParams lp = (CellLayout.LayoutParams) host.getLayoutParams(); CellLayout layout = (CellLayout) host.getParent().getParent(); layout.markCellsAsUnoccupiedForView(host); if (action == R.string.action_increase_width) { if (((host.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) && layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) || !layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY)) { lp.cellX --; info.cellX --; } lp.cellHSpan ++; info.spanX ++; } else if (action == R.string.action_decrease_width) { lp.cellHSpan --; info.spanX --; } else if (action == R.string.action_increase_height) { if (!layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1)) { lp.cellY --; info.cellY --; } lp.cellVSpan ++; info.spanY ++; } else if (action == R.string.action_decrease_height) { lp.cellVSpan --; info.spanY --; } layout.markCellsAsOccupiedForView(host); Rect sizeRange = new Rect(); AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, sizeRange); ((LauncherAppWidgetHostView) host).updateAppWidgetSize(null, sizeRange.left, sizeRange.top, sizeRange.right, sizeRange.bottom); host.requestLayout(); LauncherModel.updateItemInDatabase(mLauncher, info); announceConfirmation(mLauncher.getString(R.string.widget_resized, info.spanX, info.spanY)); } @Thunk void announceConfirmation(int resId) { announceConfirmation(mLauncher.getResources().getString(resId)); } Loading