1ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song/* 2ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Copyright (C) 2015 The Android Open Source Project 3ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * 4ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Licensed under the Apache License, Version 2.0 (the "License"); 5ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * you may not use this file except in compliance with the License. 6ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * You may obtain a copy of the License at 7ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * 8ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * http://www.apache.org/licenses/LICENSE-2.0 9ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * 10ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Unless required by applicable law or agreed to in writing, software 11ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * distributed under the License is distributed on an "AS IS" BASIS, 12ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * See the License for the specific language governing permissions and 14ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * limitations under the License. 15ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 16ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 17ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Songpackage com.android.launcher3.util; 18ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 19ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Songimport android.util.Log; 20ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Songimport android.view.KeyEvent; 21fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyalimport android.view.View; 22ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Songimport android.view.ViewGroup; 23ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 24ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Songimport com.android.launcher3.CellLayout; 25ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Songimport com.android.launcher3.DeviceProfile; 262e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohenimport com.android.launcher3.Launcher; 27ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Songimport com.android.launcher3.LauncherAppState; 28fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyalimport com.android.launcher3.ShortcutAndWidgetContainer; 29fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal 30fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyalimport java.util.Arrays; 31ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 32ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song/** 33ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Calculates the next item that a {@link KeyEvent} should change the focus to. 34ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song *<p> 35ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Note, this utility class calculates everything regards to icon index and its (x,y) coordinates. 36ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Currently supports: 37ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * <ul> 38ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * <li> full matrix of cells that are 1x1 39ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * <li> sparse matrix of cells that are 1x1 40ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ 1][ ][ 2][ ] 41ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ ][ 3][ ] 42ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ 4][ ][ ] 43ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ 5][ 6][ 7] 44ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * </ul> 45ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * *<p> 46ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * For testing, one can use a BT keyboard, or use following adb command. 47ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * ex. $ adb shell input keyevent 20 // KEYCODE_DPAD_LEFT 48ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 49ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Songpublic class FocusLogic { 50ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 51ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song private static final String TAG = "FocusLogic"; 52ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static final boolean DEBUG = false; 53ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 54ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Item and page index related constant used by {@link #handleKeyEvent}. 55ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song public static final int NOOP = -1; 5631178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song 5738531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song public static final int PREVIOUS_PAGE_RIGHT_COLUMN = -2; 5838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song public static final int PREVIOUS_PAGE_FIRST_ITEM = -3; 5938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song public static final int PREVIOUS_PAGE_LAST_ITEM = -4; 60ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song public static final int PREVIOUS_PAGE_LEFT_COLUMN = -5; 6131178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song 62ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song public static final int CURRENT_PAGE_FIRST_ITEM = -6; 63ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song public static final int CURRENT_PAGE_LAST_ITEM = -7; 6431178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song 65ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song public static final int NEXT_PAGE_FIRST_ITEM = -8; 66ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song public static final int NEXT_PAGE_LEFT_COLUMN = -9; 67ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song public static final int NEXT_PAGE_RIGHT_COLUMN = -10; 68ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 69ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Matrix related constant. 70ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song public static final int EMPTY = -1; 7138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song public static final int PIVOT = 100; 72ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 73ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song /** 74ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Returns true only if this utility class handles the key code. 75ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 76ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song public static boolean shouldConsume(int keyCode) { 77fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal return (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || 78ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN || 79ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song keyCode == KeyEvent.KEYCODE_MOVE_HOME || keyCode == KeyEvent.KEYCODE_MOVE_END || 8031178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song keyCode == KeyEvent.KEYCODE_PAGE_UP || keyCode == KeyEvent.KEYCODE_PAGE_DOWN || 81fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL); 82ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 83ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 842e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen public static int handleKeyEvent(int keyCode, int cntX, int cntY, 852e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen int [][] map, int iconIdx, int pageIndex, int pageCount, boolean isRtl) { 86ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 87ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 88ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, String.format( 89ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song "handleKeyEvent START: cntX=%d, cntY=%d, iconIdx=%d, pageIdx=%d, pageCnt=%d", 90ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song cntX, cntY, iconIdx, pageIndex, pageCount)); 91ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 92ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 93ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int newIndex = NOOP; 94ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song switch (keyCode) { 95ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_DPAD_LEFT: 96ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/); 972e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen if (isRtl && newIndex == NOOP && pageIndex > 0) { 9838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song newIndex = PREVIOUS_PAGE_RIGHT_COLUMN; 992e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen } else if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) { 100ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song newIndex = NEXT_PAGE_RIGHT_COLUMN; 101ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 102ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 103ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_DPAD_RIGHT: 104ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/); 1052e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) { 10638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song newIndex = NEXT_PAGE_LEFT_COLUMN; 1072e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen } else if (isRtl && newIndex == NOOP && pageIndex > 0) { 108ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song newIndex = PREVIOUS_PAGE_LEFT_COLUMN; 109ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 110ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 111ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_DPAD_DOWN: 112ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handleDpadVertical(iconIdx, cntX, cntY, map, 1 /*increment*/); 113ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 114ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_DPAD_UP: 115ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handleDpadVertical(iconIdx, cntX, cntY, map, -1 /*increment*/); 116ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 117ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_MOVE_HOME: 118ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handleMoveHome(); 119ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 120ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_MOVE_END: 121ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handleMoveEnd(); 122ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 123ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_PAGE_DOWN: 124ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handlePageDown(pageIndex, pageCount); 125ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 126ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case KeyEvent.KEYCODE_PAGE_UP: 127ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIndex = handlePageUp(pageIndex); 128ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 129ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song default: 130ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song break; 131ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 132ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 133ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 134ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, String.format("handleKeyEvent FINISH: index [%d -> %s]", 135ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song iconIdx, getStringIndex(newIndex))); 136ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 137ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIndex; 138ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 139ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 140ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song /** 141fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal * Returns a matrix of size (m x n) that has been initialized with {@link #EMPTY}. 142ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * 143ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * @param m number of columns in the matrix 144ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * @param n number of rows in the matrix 145ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 146ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // TODO: get rid of dynamic matrix creation. 147fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal private static int[][] createFullMatrix(int m, int n) { 148ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int[][] matrix = new int [m][n]; 149ada50984dc149c1f4337f965fbb59bdeaac8d09fHyunyoung Song 150ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i=0; i < m;i++) { 151fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal Arrays.fill(matrix[i], EMPTY); 152ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 153ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return matrix; 154ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 155ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 156ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song /** 157ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Returns a matrix of size same as the {@link CellLayout} dimension that is initialized with the 158ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * index of the child view. 159ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 160ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // TODO: get rid of the dynamic matrix creation 161ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song public static int[][] createSparseMatrix(CellLayout layout) { 162fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal ShortcutAndWidgetContainer parent = layout.getShortcutsAndWidgets(); 163ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song final int m = layout.getCountX(); 164ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song final int n = layout.getCountY(); 165fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal final boolean invert = parent.invertLayoutHorizontally(); 166ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 167fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal int[][] matrix = createFullMatrix(m, n); 168ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 169ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Iterate thru the children. 170ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i = 0; i < parent.getChildCount(); i++ ) { 171ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int cx = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellX; 172ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int cy = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellY; 173fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal matrix[invert ? (m - cx - 1) : cx][cy] = i; 174ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 175ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 17638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song printMatrix(matrix); 177ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 178ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return matrix; 179ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 180ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 181ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song /** 182ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Creates a sparse matrix that merges the icon and hotseat view group using the cell layout. 183ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * The size of the returning matrix is [icon column count x (icon + hotseat row count)] 184ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * in portrait orientation. In landscape, [(icon + hotseat) column count x (icon row count)] 185ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 18631178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song // TODO: get rid of the dynamic matrix creation 187ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song public static int[][] createSparseMatrix(CellLayout iconLayout, CellLayout hotseatLayout, 18818bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song boolean isHorizontal, int allappsiconRank, boolean includeAllappsicon) { 189ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 190ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song ViewGroup iconParent = iconLayout.getShortcutsAndWidgets(); 191ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song ViewGroup hotseatParent = hotseatLayout.getShortcutsAndWidgets(); 192ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 193ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int m, n; 19418bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song if (isHorizontal) { 195ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song m = iconLayout.getCountX(); 196ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song n = iconLayout.getCountY() + hotseatLayout.getCountY(); 19718bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song } else { 198ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song m = iconLayout.getCountX() + hotseatLayout.getCountX(); 199ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song n = iconLayout.getCountY(); 200ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 201fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal int[][] matrix = createFullMatrix(m, n); 202ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 203ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Iterate thru the children of the top parent. 204ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i = 0; i < iconParent.getChildCount(); i++) { 205ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX; 206ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY; 207ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song matrix[cx][cy] = i; 208ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 209ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 210ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Iterate thru the children of the bottom parent 21131178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song // The hotseat view group contains one more item than iconLayout column count. 21231178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song // If {@param allappsiconRank} not negative, then the last icon in the hotseat 21331178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song // is truncated. If it is negative, then all apps icon index is not inserted. 21431178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song for(int i = hotseatParent.getChildCount() - 1; i >= (includeAllappsicon ? 0 : 1); i--) { 21531178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song int delta = 0; 21618bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song if (isHorizontal) { 217ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int cx = ((CellLayout.LayoutParams) 218ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song hotseatParent.getChildAt(i).getLayoutParams()).cellX; 21931178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song if ((includeAllappsicon && cx >= allappsiconRank) || 22031178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song (!includeAllappsicon && cx > allappsiconRank)) { 22131178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song delta = -1; 222ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 22331178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song matrix[cx + delta][iconLayout.getCountY()] = iconParent.getChildCount() + i; 22418bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song } else { 225ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int cy = ((CellLayout.LayoutParams) 226ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song hotseatParent.getChildAt(i).getLayoutParams()).cellY; 22731178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song if ((includeAllappsicon && cy >= allappsiconRank) || 22831178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song (!includeAllappsicon && cy > allappsiconRank)) { 22931178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song delta = -1; 230ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 23131178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song matrix[iconLayout.getCountX()][cy + delta] = iconParent.getChildCount() + i; 232ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 233ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 234ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 23538531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song printMatrix(matrix); 23638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 23738531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song return matrix; 23838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 23938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 24038531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song /** 24138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * Creates a sparse matrix that merges the icon of previous/next page and last column of 24238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * current page. When left key is triggered on the leftmost column, sparse matrix is created 24338531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * that combines previous page matrix and an extra column on the right. Likewise, when right 24438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * key is triggered on the rightmost column, sparse matrix is created that combines this column 24538531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * on the 0th column and the next page matrix. 24638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * 24738531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * @param pivotX x coordinate of the focused item in the current page 24838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * @param pivotY y coordinate of the focused item in the current page 24938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song */ 25038531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song // TODO: get rid of the dynamic matrix creation 25138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song public static int[][] createSparseMatrix(CellLayout iconLayout, int pivotX, int pivotY) { 25238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 25338531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song ViewGroup iconParent = iconLayout.getShortcutsAndWidgets(); 25438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 255fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal int[][] matrix = createFullMatrix(iconLayout.getCountX() + 1, iconLayout.getCountY()); 25638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 25738531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song // Iterate thru the children of the top parent. 25838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song for (int i = 0; i < iconParent.getChildCount(); i++) { 25938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX; 26038531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY; 26138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song if (pivotX < 0) { 26238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song matrix[cx - pivotX][cy] = i; 26338531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } else { 26438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song matrix[cx][cy] = i; 26538531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 26638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 26738531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 26838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song if (pivotX < 0) { 26938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song matrix[0][pivotY] = PIVOT; 27038531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } else { 27138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song matrix[pivotX][pivotY] = PIVOT; 27238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 27338531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song if (DEBUG) { 27438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song printMatrix(matrix); 275ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 276ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return matrix; 277ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 278ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 279ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // 280ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // key event handling methods. 281ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // 282ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 283ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song /** 284ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Calculates icon that has is closest to the horizontal axis in reference to the cur icon. 285ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * 286ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Example of the check order for KEYCODE_DPAD_RIGHT: 287ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ ][13][14][15] 288ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ 6][ 8][10][12] 289ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ X][ 1][ 2][ 3][ 4] 290ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ 5][ 7][ 9][11] 291ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 292ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // TODO: add unit tests to verify all permutation. 293ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int handleDpadHorizontal(int iconIdx, int cntX, int cntY, 294ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int[][] matrix, int increment) { 295ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if(matrix == null) { 296ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song throw new IllegalStateException("Dpad navigation requires a matrix."); 297ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 298ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int newIconIndex = NOOP; 299ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 300ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int xPos = -1; 301ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int yPos = -1; 302ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Figure out the location of the icon. 303ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i = 0; i < cntX; i++) { 304ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int j = 0; j < cntY; j++) { 305ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (matrix[i][j] == iconIdx) { 306ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song xPos = i; 307ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song yPos = j; 308ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 309ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 310ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 311ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 312ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, String.format("\thandleDpadHorizontal: \t[x, y]=[%d, %d] iconIndex=%d", 313ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song xPos, yPos, iconIdx)); 314ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 315ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 316ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Rule1: check first in the horizontal direction 317ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i = xPos + increment; 0 <= i && i < cntX; i = i + increment) { 31831178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song if ((newIconIndex = inspectMatrix(i, yPos, cntX, cntY, matrix)) != NOOP) { 319ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 320ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 321ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 322ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 323ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Rule2: check (x1-n, yPos + increment), (x1-n, yPos - increment) 324ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // (x2-n, yPos + 2*increment), (x2-n, yPos - 2*increment) 325ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int nextYPos1; 326ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int nextYPos2; 327ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int i = -1; 328ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int coeff = 1; coeff < cntY; coeff++) { 329ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song nextYPos1 = yPos + coeff * increment; 330ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song nextYPos2 = yPos - coeff * increment; 331ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (i = xPos + increment * coeff; 0 <= i && i < cntX; i = i + increment) { 332ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if ((newIconIndex = inspectMatrix(i, nextYPos1, cntX, cntY, matrix)) != NOOP) { 333ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 334ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 335ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if ((newIconIndex = inspectMatrix(i, nextYPos2, cntX, cntY, matrix)) != NOOP) { 336ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 337ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 338ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 339ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 340ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 341ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 342ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 343ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song /** 344ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Calculates icon that is closest to the vertical axis in reference to the current icon. 345ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * 346ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * Example of the check order for KEYCODE_DPAD_DOWN: 347ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ ][ ][ X][ ][ ][ ] 348ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][ ][ 5][ 1][ 4][ ][ ] 349ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [ ][10][ 7][ 2][ 6][ 9][ ] 350ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song * [14][12][ 9][ 3][ 8][11][13] 351ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song */ 352ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // TODO: add unit tests to verify all permutation. 353ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int handleDpadVertical(int iconIndex, int cntX, int cntY, 354ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int [][] matrix, int increment) { 355ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int newIconIndex = NOOP; 356ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if(matrix == null) { 357ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song throw new IllegalStateException("Dpad navigation requires a matrix."); 358ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 359ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 360ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int xPos = -1; 361ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int yPos = -1; 362ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Figure out the location of the icon. 363ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i = 0; i< cntX; i++) { 364ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int j = 0; j < cntY; j++) { 365ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (matrix[i][j] == iconIndex) { 366ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song xPos = i; 367ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song yPos = j; 368ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 369ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 370ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 371ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 372ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 373ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, String.format("\thandleDpadVertical: \t[x, y]=[%d, %d] iconIndex=%d", 374ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song xPos, yPos, iconIndex)); 375ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 376ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 377ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Rule1: check first in the dpad direction 378ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int j = yPos + increment; 0 <= j && j <cntY && 0 <= j; j = j + increment) { 37931178b8237ccb6af666df60ef60c116c8afdf316Hyunyoung Song if ((newIconIndex = inspectMatrix(xPos, j, cntX, cntY, matrix)) != NOOP) { 380ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 381ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 382ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 383ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 384ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Rule2: check (xPos + increment, y_(1-n)), (xPos - increment, y_(1-n)) 385ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // (xPos + 2*increment, y_(2-n))), (xPos - 2*increment, y_(2-n)) 386ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int nextXPos1; 387ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int nextXPos2; 388ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int j = -1; 389ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int coeff = 1; coeff < cntX; coeff++) { 390ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song nextXPos1 = xPos + coeff * increment; 391ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song nextXPos2 = xPos - coeff * increment; 392ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (j = yPos + increment * coeff; 0 <= j && j < cntY; j = j + increment) { 393ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if ((newIconIndex = inspectMatrix(nextXPos1, j, cntX, cntY, matrix)) != NOOP) { 394ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 395ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 396ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if ((newIconIndex = inspectMatrix(nextXPos2, j, cntX, cntY, matrix)) != NOOP) { 397ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 398ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 399ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 400ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 401ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 402ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 403ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 404ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int handleMoveHome() { 405ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return CURRENT_PAGE_FIRST_ITEM; 406ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 407ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 408ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int handleMoveEnd() { 409ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return CURRENT_PAGE_LAST_ITEM; 410ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 411ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 412ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int handlePageDown(int pageIndex, int pageCount) { 413ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (pageIndex < pageCount -1) { 414ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return NEXT_PAGE_FIRST_ITEM; 415ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 416ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return CURRENT_PAGE_LAST_ITEM; 417ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 418ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 419ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int handlePageUp(int pageIndex) { 420ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (pageIndex > 0) { 421ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return PREVIOUS_PAGE_FIRST_ITEM; 422ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } else { 423ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return CURRENT_PAGE_FIRST_ITEM; 424ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 425ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 426ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 427ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // 428ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // Helper methods. 429ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song // 430ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 431ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static boolean isValid(int xPos, int yPos, int countX, int countY) { 432ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return (0 <= xPos && xPos < countX && 0 <= yPos && yPos < countY); 433ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 434ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 435ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static int inspectMatrix(int x, int y, int cntX, int cntY, int[][] matrix) { 436ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song int newIconIndex = NOOP; 437ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (isValid(x, y, cntX, cntY)) { 438ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (matrix[x][y] != -1) { 439ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song newIconIndex = matrix[x][y]; 440ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song if (DEBUG) { 441ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, String.format("\t\tinspect: \t[x, y]=[%d, %d] %d", 442ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song x, y, matrix[x][y])); 443ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 444ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 445ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 446ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 447ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return newIconIndex; 448ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 449ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 45038531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song /** 45138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * Only used for debugging. 45238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song */ 453ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song private static String getStringIndex(int index) { 454ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song switch(index) { 455ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case NOOP: return "NOOP"; 456ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case PREVIOUS_PAGE_FIRST_ITEM: return "PREVIOUS_PAGE_FIRST"; 457ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case PREVIOUS_PAGE_LAST_ITEM: return "PREVIOUS_PAGE_LAST"; 45838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song case PREVIOUS_PAGE_RIGHT_COLUMN:return "PREVIOUS_PAGE_RIGHT_COLUMN"; 459ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case CURRENT_PAGE_FIRST_ITEM: return "CURRENT_PAGE_FIRST"; 460ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case CURRENT_PAGE_LAST_ITEM: return "CURRENT_PAGE_LAST"; 461ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song case NEXT_PAGE_FIRST_ITEM: return "NEXT_PAGE_FIRST"; 46238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song case NEXT_PAGE_LEFT_COLUMN: return "NEXT_PAGE_LEFT_COLUMN"; 463ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song default: 464ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song return Integer.toString(index); 465ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 466ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 467ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song 46838531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song /** 46938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song * Only used for debugging. 47038531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song */ 47138531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song private static void printMatrix(int[][] matrix) { 472ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, "\tprintMap:"); 47338531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song int m = matrix.length; 47438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song int n = matrix[0].length; 47538531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 476ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int j=0; j < n; j++) { 477ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song String colY = "\t\t"; 478ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song for (int i=0; i < m; i++) { 479ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song colY += String.format("%3d",matrix[i][j]); 480ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 481ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song Log.v(TAG, colY); 482ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 483ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song } 48438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song 48538531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song /** 486fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal * @param edgeColumn the column of the new icon. either {@link #NEXT_PAGE_LEFT_COLUMN} or 487fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal * {@link #NEXT_PAGE_RIGHT_COLUMN} 488fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal * @return the view adjacent to {@param oldView} in the {@param nextPage}. 48938531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song */ 490fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal public static View getAdjacentChildInNextPage( 491fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal ShortcutAndWidgetContainer nextPage, View oldView, int edgeColumn) { 492fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal final int newRow = ((CellLayout.LayoutParams) oldView.getLayoutParams()).cellY; 493fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal 494fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal int column = (edgeColumn == NEXT_PAGE_LEFT_COLUMN) ^ nextPage.invertLayoutHorizontally() 495fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal ? 0 : (((CellLayout) nextPage.getParent()).getCountX() - 1); 496fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal 497fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal for (; column >= 0; column--) { 498fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal for (int row = newRow; row >= 0; row--) { 499fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal View newView = nextPage.getChildAt(column, row); 500fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal if (newView != null) { 501fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal return newView; 50238531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 50338531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 50438531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 505fc3c1edf7bbc3f7cb23e79520731d13ccc2da046Sunny Goyal return null; 50638531719636eba7c924e3e71c583ebce2c89a1d0Hyunyoung Song } 507ee3e6a7b777e58552a26ab8a10641886588e9196Hyunyoung Song} 508