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.Paint; 22 import android.graphics.Rect; 23 import android.view.View; 24 import android.view.ViewGroup; 25 26 public class ShortcutAndWidgetContainer extends ViewGroup { 27 static final String TAG = "CellLayoutChildren"; 28 29 // These are temporary variables to prevent having to allocate a new object just to 30 // return an (x, y) value from helper functions. Do NOT use them to maintain other state. 31 private final int[] mTmpCellXY = new int[2]; 32 33 private final WallpaperManager mWallpaperManager; 34 35 private boolean mIsHotseatLayout; 36 37 private int mCellWidth; 38 private int mCellHeight; 39 40 private int mWidthGap; 41 private int mHeightGap; 42 43 private int mCountX; 44 45 private Launcher mLauncher; 46 47 private boolean mInvertIfRtl = false; 48 ShortcutAndWidgetContainer(Context context)49 public ShortcutAndWidgetContainer(Context context) { 50 super(context); 51 mLauncher = Launcher.getLauncher(context); 52 mWallpaperManager = WallpaperManager.getInstance(context); 53 } 54 setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap, int countX, int countY)55 public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap, 56 int countX, int countY) { 57 mCellWidth = cellWidth; 58 mCellHeight = cellHeight; 59 mWidthGap = widthGap; 60 mHeightGap = heightGap; 61 mCountX = countX; 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 onMeasure(int widthMeasureSpec, int heightMeasureSpec)79 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 80 int count = getChildCount(); 81 82 int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 83 int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 84 setMeasuredDimension(widthSpecSize, heightSpecSize); 85 86 for (int i = 0; i < count; i++) { 87 View child = getChildAt(i); 88 if (child.getVisibility() != GONE) { 89 measureChild(child); 90 } 91 } 92 } 93 setupLp(CellLayout.LayoutParams lp)94 public void setupLp(CellLayout.LayoutParams lp) { 95 lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(), 96 mCountX); 97 } 98 99 // Set whether or not to invert the layout horizontally if the layout is in RTL mode. setInvertIfRtl(boolean invert)100 public void setInvertIfRtl(boolean invert) { 101 mInvertIfRtl = invert; 102 } 103 setIsHotseat(boolean isHotseat)104 public void setIsHotseat(boolean isHotseat) { 105 mIsHotseatLayout = isHotseat; 106 } 107 getCellContentWidth()108 int getCellContentWidth() { 109 final DeviceProfile grid = mLauncher.getDeviceProfile(); 110 return Math.min(getMeasuredHeight(), mIsHotseatLayout ? 111 grid.hotseatCellWidthPx: grid.cellWidthPx); 112 } 113 getCellContentHeight()114 int getCellContentHeight() { 115 final DeviceProfile grid = mLauncher.getDeviceProfile(); 116 return Math.min(getMeasuredHeight(), mIsHotseatLayout ? 117 grid.hotseatCellHeightPx : grid.cellHeightPx); 118 } 119 measureChild(View child)120 public void measureChild(View child) { 121 final DeviceProfile grid = mLauncher.getDeviceProfile(); 122 final int cellWidth = mCellWidth; 123 final int cellHeight = mCellHeight; 124 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 125 if (!lp.isFullscreen) { 126 lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(), 127 mCountX); 128 129 if (child instanceof LauncherAppWidgetHostView) { 130 // Widgets have their own padding, so skip 131 } else { 132 // Otherwise, center the icon/folder 133 int cHeight = getCellContentHeight(); 134 int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f)); 135 int cellPaddingX = (int) (grid.edgeMarginPx / 2f); 136 child.setPadding(cellPaddingX, cellPaddingY, cellPaddingX, 0); 137 } 138 } else { 139 lp.x = 0; 140 lp.y = 0; 141 lp.width = getMeasuredWidth(); 142 lp.height = getMeasuredHeight(); 143 } 144 int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); 145 int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); 146 child.measure(childWidthMeasureSpec, childheightMeasureSpec); 147 } 148 invertLayoutHorizontally()149 public boolean invertLayoutHorizontally() { 150 return mInvertIfRtl && Utilities.isRtl(getResources()); 151 } 152 153 @Override onLayout(boolean changed, int l, int t, int r, int b)154 protected void onLayout(boolean changed, int l, int t, int r, int b) { 155 int count = getChildCount(); 156 for (int i = 0; i < count; i++) { 157 final View child = getChildAt(i); 158 if (child.getVisibility() != GONE) { 159 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 160 int childLeft = lp.x; 161 int childTop = lp.y; 162 child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height); 163 164 if (lp.dropped) { 165 lp.dropped = false; 166 167 final int[] cellXY = mTmpCellXY; 168 getLocationOnScreen(cellXY); 169 mWallpaperManager.sendWallpaperCommand(getWindowToken(), 170 WallpaperManager.COMMAND_DROP, 171 cellXY[0] + childLeft + lp.width / 2, 172 cellXY[1] + childTop + lp.height / 2, 0, null); 173 } 174 } 175 } 176 } 177 178 @Override shouldDelayChildPressedState()179 public boolean shouldDelayChildPressedState() { 180 return false; 181 } 182 183 @Override requestChildFocus(View child, View focused)184 public void requestChildFocus(View child, View focused) { 185 super.requestChildFocus(child, focused); 186 if (child != null) { 187 Rect r = new Rect(); 188 child.getDrawingRect(r); 189 requestRectangleOnScreen(r); 190 } 191 } 192 193 @Override cancelLongPress()194 public void cancelLongPress() { 195 super.cancelLongPress(); 196 197 // Cancel long press for all children 198 final int count = getChildCount(); 199 for (int i = 0; i < count; i++) { 200 final View child = getChildAt(i); 201 child.cancelLongPress(); 202 } 203 } 204 205 @Override setChildrenDrawingCacheEnabled(boolean enabled)206 protected void setChildrenDrawingCacheEnabled(boolean enabled) { 207 final int count = getChildCount(); 208 for (int i = 0; i < count; i++) { 209 final View view = getChildAt(i); 210 view.setDrawingCacheEnabled(enabled); 211 // Update the drawing caches 212 if (!view.isHardwareAccelerated() && enabled) { 213 view.buildDrawingCache(true); 214 } 215 } 216 } 217 setChildrenDrawnWithCacheEnabled(boolean enabled)218 protected void setChildrenDrawnWithCacheEnabled(boolean enabled) { 219 super.setChildrenDrawnWithCacheEnabled(enabled); 220 } 221 222 @Override setLayerType(int layerType, Paint paint)223 public void setLayerType(int layerType, Paint paint) { 224 // When clip children is disabled do not use hardware layer, 225 // as hardware layer forces clip children. 226 super.setLayerType(getClipChildren() ? layerType : LAYER_TYPE_NONE, paint); 227 } 228 } 229