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.Rect; 22 import android.view.View; 23 import android.view.ViewGroup; 24 25 import com.android.launcher3.CellLayout.ContainerType; 26 27 public class ShortcutAndWidgetContainer extends ViewGroup { 28 static final String TAG = "ShortcutAndWidgetContainer"; 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 @ContainerType private final int mContainerType; 35 private final WallpaperManager mWallpaperManager; 36 37 private int mCellWidth; 38 private int mCellHeight; 39 40 private int mCountX; 41 42 private Launcher mLauncher; 43 private boolean mInvertIfRtl = false; 44 ShortcutAndWidgetContainer(Context context, @ContainerType int containerType)45 public ShortcutAndWidgetContainer(Context context, @ContainerType int containerType) { 46 super(context); 47 mLauncher = Launcher.getLauncher(context); 48 mWallpaperManager = WallpaperManager.getInstance(context); 49 mContainerType = containerType; 50 } 51 setCellDimensions(int cellWidth, int cellHeight, int countX, int countY)52 public void setCellDimensions(int cellWidth, int cellHeight, int countX, int countY) { 53 mCellWidth = cellWidth; 54 mCellHeight = cellHeight; 55 mCountX = countX; 56 } 57 getChildAt(int x, int y)58 public View getChildAt(int x, int y) { 59 final int count = getChildCount(); 60 for (int i = 0; i < count; i++) { 61 View child = getChildAt(i); 62 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 63 64 if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) && 65 (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) { 66 return child; 67 } 68 } 69 return null; 70 } 71 72 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)73 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 74 int count = getChildCount(); 75 76 int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 77 int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 78 setMeasuredDimension(widthSpecSize, heightSpecSize); 79 80 for (int i = 0; i < count; i++) { 81 View child = getChildAt(i); 82 if (child.getVisibility() != GONE) { 83 measureChild(child); 84 } 85 } 86 } 87 setupLp(View child)88 public void setupLp(View child) { 89 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 90 if (child instanceof LauncherAppWidgetHostView) { 91 DeviceProfile profile = mLauncher.getDeviceProfile(); 92 lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, 93 profile.appWidgetScale.x, profile.appWidgetScale.y); 94 } else { 95 lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX); 96 } 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 getCellContentHeight()104 int getCellContentHeight() { 105 return Math.min(getMeasuredHeight(), 106 mLauncher.getDeviceProfile().getCellHeight(mContainerType)); 107 } 108 measureChild(View child)109 public void measureChild(View child) { 110 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 111 if (!lp.isFullscreen) { 112 final DeviceProfile profile = mLauncher.getDeviceProfile(); 113 114 if (child instanceof LauncherAppWidgetHostView) { 115 lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, 116 profile.appWidgetScale.x, profile.appWidgetScale.y); 117 // Widgets have their own padding 118 } else { 119 lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX); 120 // Center the icon/folder 121 int cHeight = getCellContentHeight(); 122 int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f)); 123 int cellPaddingX = (int) (profile.edgeMarginPx / 2f); 124 child.setPadding(cellPaddingX, cellPaddingY, cellPaddingX, 0); 125 } 126 } else { 127 lp.x = 0; 128 lp.y = 0; 129 lp.width = getMeasuredWidth(); 130 lp.height = getMeasuredHeight(); 131 } 132 int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); 133 int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); 134 child.measure(childWidthMeasureSpec, childheightMeasureSpec); 135 } 136 invertLayoutHorizontally()137 public boolean invertLayoutHorizontally() { 138 return mInvertIfRtl && Utilities.isRtl(getResources()); 139 } 140 141 @Override onLayout(boolean changed, int l, int t, int r, int b)142 protected void onLayout(boolean changed, int l, int t, int r, int b) { 143 int count = getChildCount(); 144 for (int i = 0; i < count; i++) { 145 final View child = getChildAt(i); 146 if (child.getVisibility() != GONE) { 147 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 148 149 if (child instanceof LauncherAppWidgetHostView) { 150 LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) child; 151 152 // Scale and center the widget to fit within its cells. 153 DeviceProfile profile = mLauncher.getDeviceProfile(); 154 float scaleX = profile.appWidgetScale.x; 155 float scaleY = profile.appWidgetScale.y; 156 157 lahv.setScaleToFit(Math.min(scaleX, scaleY)); 158 lahv.setTranslationForCentering(-(lp.width - (lp.width * scaleX)) / 2.0f, 159 -(lp.height - (lp.height * scaleY)) / 2.0f); 160 } 161 162 int childLeft = lp.x; 163 int childTop = lp.y; 164 child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height); 165 166 if (lp.dropped) { 167 lp.dropped = false; 168 169 final int[] cellXY = mTmpCellXY; 170 getLocationOnScreen(cellXY); 171 mWallpaperManager.sendWallpaperCommand(getWindowToken(), 172 WallpaperManager.COMMAND_DROP, 173 cellXY[0] + childLeft + lp.width / 2, 174 cellXY[1] + childTop + lp.height / 2, 0, null); 175 } 176 } 177 } 178 } 179 180 @Override shouldDelayChildPressedState()181 public boolean shouldDelayChildPressedState() { 182 return false; 183 } 184 185 @Override requestChildFocus(View child, View focused)186 public void requestChildFocus(View child, View focused) { 187 super.requestChildFocus(child, focused); 188 if (child != null) { 189 Rect r = new Rect(); 190 child.getDrawingRect(r); 191 requestRectangleOnScreen(r); 192 } 193 } 194 195 @Override cancelLongPress()196 public void cancelLongPress() { 197 super.cancelLongPress(); 198 199 // Cancel long press for all children 200 final int count = getChildCount(); 201 for (int i = 0; i < count; i++) { 202 final View child = getChildAt(i); 203 child.cancelLongPress(); 204 } 205 } 206 } 207