1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3; 18 19 import android.app.WallpaperManager; 20 import android.content.Context; 21 import android.graphics.Canvas; 22 import android.graphics.Paint; 23 import android.graphics.Rect; 24 import android.view.View; 25 import android.view.ViewGroup; 26 27 public class ShortcutAndWidgetContainer extends ViewGroup { 28 static final String TAG = "CellLayoutChildren"; 29 30 // These are temporary variables to prevent having to allocate a new object just to 31 // return an (x, y) value from helper functions. Do NOT use them to maintain other state. 32 private final int[] mTmpCellXY = new int[2]; 33 34 private final WallpaperManager mWallpaperManager; 35 36 private boolean mIsHotseatLayout; 37 38 private int mCellWidth; 39 private int mCellHeight; 40 41 private int mWidthGap; 42 private int mHeightGap; 43 44 private int mCountX; 45 private int mCountY; 46 47 private boolean mInvertIfRtl = false; 48 ShortcutAndWidgetContainer(Context context)49 public ShortcutAndWidgetContainer(Context context) { 50 super(context); 51 mWallpaperManager = WallpaperManager.getInstance(context); 52 } 53 setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap, int countX, int countY)54 public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap, 55 int countX, int countY) { 56 mCellWidth = cellWidth; 57 mCellHeight = cellHeight; 58 mWidthGap = widthGap; 59 mHeightGap = heightGap; 60 mCountX = countX; 61 mCountY = countY; 62 } 63 getChildAt(int x, int y)64 public View getChildAt(int x, int y) { 65 final int count = getChildCount(); 66 for (int i = 0; i < count; i++) { 67 View child = getChildAt(i); 68 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 69 70 if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) && 71 (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) { 72 return child; 73 } 74 } 75 return null; 76 } 77 78 @Override dispatchDraw(Canvas canvas)79 protected void dispatchDraw(Canvas canvas) { 80 @SuppressWarnings("all") // suppress dead code warning 81 final boolean debug = false; 82 if (debug) { 83 // Debug drawing for hit space 84 Paint p = new Paint(); 85 p.setColor(0x6600FF00); 86 for (int i = getChildCount() - 1; i >= 0; i--) { 87 final View child = getChildAt(i); 88 final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 89 90 canvas.drawRect(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height, p); 91 } 92 } 93 super.dispatchDraw(canvas); 94 } 95 96 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)97 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 98 int count = getChildCount(); 99 100 int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 101 int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 102 setMeasuredDimension(widthSpecSize, heightSpecSize); 103 104 for (int i = 0; i < count; i++) { 105 View child = getChildAt(i); 106 if (child.getVisibility() != GONE) { 107 measureChild(child); 108 } 109 } 110 } 111 setupLp(CellLayout.LayoutParams lp)112 public void setupLp(CellLayout.LayoutParams lp) { 113 lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(), 114 mCountX); 115 } 116 117 // Set whether or not to invert the layout horizontally if the layout is in RTL mode. setInvertIfRtl(boolean invert)118 public void setInvertIfRtl(boolean invert) { 119 mInvertIfRtl = invert; 120 } 121 setIsHotseat(boolean isHotseat)122 public void setIsHotseat(boolean isHotseat) { 123 mIsHotseatLayout = isHotseat; 124 } 125 getCellContentWidth()126 int getCellContentWidth() { 127 final LauncherAppState app = LauncherAppState.getInstance(); 128 final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 129 return Math.min(getMeasuredHeight(), mIsHotseatLayout ? 130 grid.hotseatCellWidthPx: grid.cellWidthPx); 131 } 132 getCellContentHeight()133 int getCellContentHeight() { 134 final LauncherAppState app = LauncherAppState.getInstance(); 135 final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 136 return Math.min(getMeasuredHeight(), mIsHotseatLayout ? 137 grid.hotseatCellHeightPx : grid.cellHeightPx); 138 } 139 measureChild(View child)140 public void measureChild(View child) { 141 final LauncherAppState app = LauncherAppState.getInstance(); 142 final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 143 final int cellWidth = mCellWidth; 144 final int cellHeight = mCellHeight; 145 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 146 if (!lp.isFullscreen) { 147 lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(), 148 mCountX); 149 150 if (child instanceof LauncherAppWidgetHostView) { 151 // Widgets have their own padding, so skip 152 } else { 153 // Otherwise, center the icon 154 int cHeight = getCellContentHeight(); 155 int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f)); 156 int cellPaddingX = (int) (grid.edgeMarginPx / 2f); 157 child.setPadding(cellPaddingX, cellPaddingY, cellPaddingX, 0); 158 } 159 } else { 160 lp.x = 0; 161 lp.y = 0; 162 lp.width = getMeasuredWidth(); 163 lp.height = getMeasuredHeight(); 164 } 165 int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); 166 int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height, 167 MeasureSpec.EXACTLY); 168 child.measure(childWidthMeasureSpec, childheightMeasureSpec); 169 } 170 invertLayoutHorizontally()171 private boolean invertLayoutHorizontally() { 172 return mInvertIfRtl && isLayoutRtl(); 173 } 174 isLayoutRtl()175 public boolean isLayoutRtl() { 176 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 177 } 178 179 @Override onLayout(boolean changed, int l, int t, int r, int b)180 protected void onLayout(boolean changed, int l, int t, int r, int b) { 181 int count = getChildCount(); 182 for (int i = 0; i < count; i++) { 183 final View child = getChildAt(i); 184 if (child.getVisibility() != GONE) { 185 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 186 int childLeft = lp.x; 187 int childTop = lp.y; 188 child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height); 189 190 if (lp.dropped) { 191 lp.dropped = false; 192 193 final int[] cellXY = mTmpCellXY; 194 getLocationOnScreen(cellXY); 195 mWallpaperManager.sendWallpaperCommand(getWindowToken(), 196 WallpaperManager.COMMAND_DROP, 197 cellXY[0] + childLeft + lp.width / 2, 198 cellXY[1] + childTop + lp.height / 2, 0, null); 199 } 200 } 201 } 202 } 203 204 @Override shouldDelayChildPressedState()205 public boolean shouldDelayChildPressedState() { 206 return false; 207 } 208 209 @Override requestChildFocus(View child, View focused)210 public void requestChildFocus(View child, View focused) { 211 super.requestChildFocus(child, focused); 212 if (child != null) { 213 Rect r = new Rect(); 214 child.getDrawingRect(r); 215 requestRectangleOnScreen(r); 216 } 217 } 218 219 @Override cancelLongPress()220 public void cancelLongPress() { 221 super.cancelLongPress(); 222 223 // Cancel long press for all children 224 final int count = getChildCount(); 225 for (int i = 0; i < count; i++) { 226 final View child = getChildAt(i); 227 child.cancelLongPress(); 228 } 229 } 230 231 @Override setChildrenDrawingCacheEnabled(boolean enabled)232 protected void setChildrenDrawingCacheEnabled(boolean enabled) { 233 final int count = getChildCount(); 234 for (int i = 0; i < count; i++) { 235 final View view = getChildAt(i); 236 view.setDrawingCacheEnabled(enabled); 237 // Update the drawing caches 238 if (!view.isHardwareAccelerated() && enabled) { 239 view.buildDrawingCache(true); 240 } 241 } 242 } 243 244 @Override setChildrenDrawnWithCacheEnabled(boolean enabled)245 protected void setChildrenDrawnWithCacheEnabled(boolean enabled) { 246 super.setChildrenDrawnWithCacheEnabled(enabled); 247 } 248 } 249