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 Launcher mLauncher; 48 49 private boolean mInvertIfRtl = false; 50 51 public ShortcutAndWidgetContainer(Context context) { 52 super(context); 53 mLauncher = (Launcher) context; 54 mWallpaperManager = WallpaperManager.getInstance(context); 55 } 56 57 public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap, 58 int countX, int countY) { 59 mCellWidth = cellWidth; 60 mCellHeight = cellHeight; 61 mWidthGap = widthGap; 62 mHeightGap = heightGap; 63 mCountX = countX; 64 mCountY = countY; 65 } 66 67 public View getChildAt(int x, int y) { 68 final int count = getChildCount(); 69 for (int i = 0; i < count; i++) { 70 View child = getChildAt(i); 71 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 72 73 if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) && 74 (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) { 75 return child; 76 } 77 } 78 return null; 79 } 80 81 @Override 82 protected void dispatchDraw(Canvas canvas) { 83 @SuppressWarnings("all") // suppress dead code warning 84 final boolean debug = false; 85 if (debug) { 86 // Debug drawing for hit space 87 Paint p = new Paint(); 88 p.setColor(0x6600FF00); 89 for (int i = getChildCount() - 1; i >= 0; i--) { 90 final View child = getChildAt(i); 91 final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 92 93 canvas.drawRect(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height, p); 94 } 95 } 96 super.dispatchDraw(canvas); 97 } 98 99 @Override 100 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 101 int count = getChildCount(); 102 103 int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 104 int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 105 setMeasuredDimension(widthSpecSize, heightSpecSize); 106 107 for (int i = 0; i < count; i++) { 108 View child = getChildAt(i); 109 if (child.getVisibility() != GONE) { 110 measureChild(child); 111 } 112 } 113 } 114 115 public void setupLp(CellLayout.LayoutParams lp) { 116 lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(), 117 mCountX); 118 } 119 120 // Set whether or not to invert the layout horizontally if the layout is in RTL mode. 121 public void setInvertIfRtl(boolean invert) { 122 mInvertIfRtl = invert; 123 } 124 125 public void setIsHotseat(boolean isHotseat) { 126 mIsHotseatLayout = isHotseat; 127 } 128 129 int getCellContentWidth() { 130 final DeviceProfile grid = mLauncher.getDeviceProfile(); 131 return Math.min(getMeasuredHeight(), mIsHotseatLayout ? 132 grid.hotseatCellWidthPx: grid.cellWidthPx); 133 } 134 135 int getCellContentHeight() { 136 final DeviceProfile grid = mLauncher.getDeviceProfile(); 137 return Math.min(getMeasuredHeight(), mIsHotseatLayout ? 138 grid.hotseatCellHeightPx : grid.cellHeightPx); 139 } 140 141 public void measureChild(View child) { 142 final DeviceProfile grid = mLauncher.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, MeasureSpec.EXACTLY); 167 child.measure(childWidthMeasureSpec, childheightMeasureSpec); 168 } 169 170 public boolean invertLayoutHorizontally() { 171 return mInvertIfRtl && Utilities.isRtl(getResources()); 172 } 173 174 @Override 175 protected void onLayout(boolean changed, int l, int t, int r, int b) { 176 int count = getChildCount(); 177 for (int i = 0; i < count; i++) { 178 final View child = getChildAt(i); 179 if (child.getVisibility() != GONE) { 180 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 181 int childLeft = lp.x; 182 int childTop = lp.y; 183 child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height); 184 185 if (lp.dropped) { 186 lp.dropped = false; 187 188 final int[] cellXY = mTmpCellXY; 189 getLocationOnScreen(cellXY); 190 mWallpaperManager.sendWallpaperCommand(getWindowToken(), 191 WallpaperManager.COMMAND_DROP, 192 cellXY[0] + childLeft + lp.width / 2, 193 cellXY[1] + childTop + lp.height / 2, 0, null); 194 } 195 } 196 } 197 } 198 199 @Override 200 public boolean shouldDelayChildPressedState() { 201 return false; 202 } 203 204 @Override 205 public void requestChildFocus(View child, View focused) { 206 super.requestChildFocus(child, focused); 207 if (child != null) { 208 Rect r = new Rect(); 209 child.getDrawingRect(r); 210 requestRectangleOnScreen(r); 211 } 212 } 213 214 @Override 215 public void cancelLongPress() { 216 super.cancelLongPress(); 217 218 // Cancel long press for all children 219 final int count = getChildCount(); 220 for (int i = 0; i < count; i++) { 221 final View child = getChildAt(i); 222 child.cancelLongPress(); 223 } 224 } 225 226 @Override 227 protected void setChildrenDrawingCacheEnabled(boolean enabled) { 228 final int count = getChildCount(); 229 for (int i = 0; i < count; i++) { 230 final View view = getChildAt(i); 231 view.setDrawingCacheEnabled(enabled); 232 // Update the drawing caches 233 if (!view.isHardwareAccelerated() && enabled) { 234 view.buildDrawingCache(true); 235 } 236 } 237 } 238 239 @Override 240 protected void setChildrenDrawnWithCacheEnabled(boolean enabled) { 241 super.setChildrenDrawnWithCacheEnabled(enabled); 242 } 243 } 244