1 /*
2  * Copyright (C) 2022 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 package com.android.launcher3.celllayout;
17 
18 import android.content.Context;
19 import android.graphics.Point;
20 import android.graphics.Rect;
21 import android.util.AttributeSet;
22 import android.view.ViewDebug;
23 import android.view.ViewGroup;
24 
25 import androidx.annotation.Nullable;
26 
27 /**
28  * Represents the logic of where a view is in a CellLayout and its size
29  */
30 public class CellLayoutLayoutParams extends ViewGroup.MarginLayoutParams {
31 
32     @ViewDebug.ExportedProperty
33     private int mCellX;
34 
35     @ViewDebug.ExportedProperty
36     private int mCellY;
37 
38     private int mTmpCellX;
39 
40     private int mTmpCellY;
41 
42     /**
43      * Indicates that the temporary coordinates should be used to layout the items
44      */
45     public boolean useTmpCoords;
46 
47     /**
48      * Number of cells spanned horizontally by the item.
49      */
50     @ViewDebug.ExportedProperty
51     public int cellHSpan;
52 
53     /**
54      * Number of cells spanned vertically by the item.
55      */
56     @ViewDebug.ExportedProperty
57     public int cellVSpan;
58 
59     /**
60      * Indicates whether the item will set its x, y, width and height parameters freely,
61      * or whether these will be computed based on cellX, cellY, cellHSpan and cellVSpan.
62      */
63     public boolean isLockedToGrid = true;
64 
65     /**
66      * Indicates whether this item can be reordered. Always true except in the case of the
67      * the AllApps button and QSB place holder.
68      */
69     public boolean canReorder = true;
70 
71     // X coordinate of the view in the layout.
72     @ViewDebug.ExportedProperty
73     public int x;
74     // Y coordinate of the view in the layout.
75     @ViewDebug.ExportedProperty
76     public int y;
77 
78     public boolean dropped;
79 
CellLayoutLayoutParams(Context c, AttributeSet attrs)80     public CellLayoutLayoutParams(Context c, AttributeSet attrs) {
81         super(c, attrs);
82         cellHSpan = 1;
83         cellVSpan = 1;
84     }
85 
CellLayoutLayoutParams(ViewGroup.LayoutParams source)86     public CellLayoutLayoutParams(ViewGroup.LayoutParams source) {
87         super(source);
88         cellHSpan = 1;
89         cellVSpan = 1;
90     }
91 
CellLayoutLayoutParams(CellLayoutLayoutParams source)92     public CellLayoutLayoutParams(CellLayoutLayoutParams source) {
93         super(source);
94         this.mCellX = source.getCellX();
95         this.mCellY = source.getCellY();
96         this.cellHSpan = source.cellHSpan;
97         this.cellVSpan = source.cellVSpan;
98         this.mTmpCellX = source.getTmpCellX();
99         this.mTmpCellY = source.getTmpCellY();
100         this.useTmpCoords = source.useTmpCoords;
101     }
102 
CellLayoutLayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan)103     public CellLayoutLayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
104         super(CellLayoutLayoutParams.MATCH_PARENT, CellLayoutLayoutParams.MATCH_PARENT);
105         this.mCellX = cellX;
106         this.mCellY = cellY;
107         this.cellHSpan = cellHSpan;
108         this.cellVSpan = cellVSpan;
109     }
110 
111     /**
112      * Updates the {@link CellLayoutLayoutParams} with the right measures using their
113      * full/invariant device profile sizes.
114      */
setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount, int rowCount, Point borderSpace)115     public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount,
116             int rowCount, Point borderSpace) {
117         setup(cellWidth, cellHeight, invertHorizontally, colCount, rowCount, 1.0f, 1.0f,
118                 borderSpace, null);
119     }
120 
121     /**
122      * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, Point)},
123      * if the view needs to be scaled.
124      *
125      * ie. In multi-window mode, we setup widgets so that they are measured and laid out
126      * using their full/invariant device profile sizes.
127      */
setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount, int rowCount, float cellScaleX, float cellScaleY, Point borderSpace, @Nullable Rect inset)128     public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount,
129             int rowCount, float cellScaleX, float cellScaleY, Point borderSpace,
130             @Nullable Rect inset) {
131         if (isLockedToGrid) {
132             final int myCellHSpan = cellHSpan;
133             final int myCellVSpan = cellVSpan;
134             int myCellX = useTmpCoords ? getTmpCellX() : getCellX();
135             int myCellY = useTmpCoords ? getTmpCellY() : getCellY();
136 
137             if (invertHorizontally) {
138                 myCellX = colCount - myCellX - cellHSpan;
139             }
140 
141             int hBorderSpacing = (myCellHSpan - 1) * borderSpace.x;
142             int vBorderSpacing = (myCellVSpan - 1) * borderSpace.y;
143 
144             float myCellWidth = ((myCellHSpan * cellWidth) + hBorderSpacing) / cellScaleX;
145             float myCellHeight = ((myCellVSpan * cellHeight) + vBorderSpacing) / cellScaleY;
146 
147             width = Math.round(myCellWidth) - leftMargin - rightMargin;
148             height = Math.round(myCellHeight) - topMargin - bottomMargin;
149             x = leftMargin + (myCellX * cellWidth) + (myCellX * borderSpace.x);
150             y = topMargin + (myCellY * cellHeight) + (myCellY * borderSpace.y);
151 
152             if (inset != null) {
153                 x += inset.left;
154                 y += inset.top;
155                 width -= inset.left + inset.right;
156                 height -= inset.top + inset.bottom;
157             }
158         }
159     }
160 
161     /**
162      * Sets the position to the provided point
163      */
setCellXY(Point point)164     public void setCellXY(Point point) {
165         setCellX(point.x);
166         setCellY(point.y);
167     }
168 
169     /**
170      * @return the string representation of the position of the {@link CellLayoutLayoutParams}
171      */
toString()172     public String toString() {
173         return "(" + this.getCellX() + ", " + this.getCellY() + ")";
174     }
175 
176     /**
177      * Horizontal location of the item in the grid.
178      */
getCellX()179     public int getCellX() {
180         return mCellX;
181     }
182 
setCellX(int cellX)183     public void setCellX(int cellX) {
184         this.mCellX = cellX;
185     }
186 
187     /**
188      * Vertical location of the item in the grid.
189      */
getCellY()190     public int getCellY() {
191         return mCellY;
192     }
193 
setCellY(int cellY)194     public void setCellY(int cellY) {
195         this.mCellY = cellY;
196     }
197 
198     /**
199      * Temporary horizontal location of the item in the grid during reorder
200      */
getTmpCellX()201     public int getTmpCellX() {
202         return mTmpCellX;
203     }
204 
setTmpCellX(int tmpCellX)205     public void setTmpCellX(int tmpCellX) {
206         this.mTmpCellX = tmpCellX;
207     }
208 
209     /**
210      * Temporary vertical location of the item in the grid during reorder
211      */
getTmpCellY()212     public int getTmpCellY() {
213         return mTmpCellY;
214     }
215 
setTmpCellY(int tmpCellY)216     public void setTmpCellY(int tmpCellY) {
217         this.mTmpCellY = tmpCellY;
218     }
219 }
220