blob: 44a1414d21dc11e5bbf79d08d34291d50837462f [file] [log] [blame]
Sebastian Franco09589322022-11-02 15:25:58 -07001/*
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 */
16package com.android.launcher3;
17
18import android.content.Context;
19import android.graphics.Canvas;
20import android.graphics.Rect;
21import android.graphics.drawable.Drawable;
22import android.util.AttributeSet;
23import android.view.View;
24
25import com.android.launcher3.celllayout.CellLayoutLayoutParams;
Sebastian Francoe4c03452022-12-27 14:50:02 -060026import com.android.launcher3.celllayout.MulticellReorderAlgorithm;
Sebastian Franco09589322022-11-02 15:25:58 -070027import com.android.launcher3.util.CellAndSpan;
28import com.android.launcher3.util.GridOccupancy;
29
Sebastian Franco09589322022-11-02 15:25:58 -070030/**
31 * CellLayout that simulates a split in the middle for use in foldable devices.
32 */
33public class MultipageCellLayout extends CellLayout {
34
35 private final Drawable mLeftBackground;
36 private final Drawable mRightBackground;
37
Sebastian Franco317c4fa2023-02-21 17:01:24 -080038 private boolean mSeamWasAdded = false;
39
Sebastian Franco09589322022-11-02 15:25:58 -070040 public MultipageCellLayout(Context context) {
41 this(context, null);
42 }
43
44 public MultipageCellLayout(Context context, AttributeSet attrs) {
45 this(context, attrs, 0);
46 }
47
Sebastian Franco96c46e72023-05-08 10:04:44 -060048 @Override
49 protected int[] findNearestArea(int relativeXPos, int relativeYPos, int minSpanX, int minSpanY,
50 int spanX, int spanY, boolean ignoreOccupied, int[] result, int[] resultSpan) {
51 return createReorderAlgorithm().simulateSeam(
52 () -> super.findNearestArea(relativeXPos, relativeYPos, minSpanX, minSpanY, spanX,
53 spanY, ignoreOccupied, result, resultSpan));
54 }
55
56 @Override
57 public void getDirectionVectorForDrop(int dragViewCenterX, int dragViewCenterY, int spanX,
58 int spanY, View dragView, int[] resultDirection) {
59 createReorderAlgorithm().simulateSeam(
60 () -> {
61 super.getDirectionVectorForDrop(dragViewCenterX, dragViewCenterY, spanX, spanY,
62 dragView, resultDirection);
63 return 0;
64 });
65 }
66
67 @Override
68 public boolean isNearestDropLocationOccupied(int pixelX, int pixelY, int spanX, int spanY,
69 View dragView, int[] result) {
70 return createReorderAlgorithm().simulateSeam(
71 () -> super.isNearestDropLocationOccupied(pixelX, pixelY, spanX, spanY, dragView,
72 result));
73 }
74
Sebastian Franco09589322022-11-02 15:25:58 -070075 public MultipageCellLayout(Context context, AttributeSet attrs, int defStyle) {
76 super(context, attrs, defStyle);
77 mLeftBackground = getContext().getDrawable(R.drawable.bg_celllayout);
78 mLeftBackground.setCallback(this);
79 mLeftBackground.setAlpha(0);
80
81 mRightBackground = getContext().getDrawable(R.drawable.bg_celllayout);
82 mRightBackground.setCallback(this);
83 mRightBackground.setAlpha(0);
84
85 DeviceProfile deviceProfile = mActivity.getDeviceProfile();
86
87 mCountX = deviceProfile.inv.numColumns * 2;
88 mCountY = deviceProfile.inv.numRows;
Sebastian Franco09589322022-11-02 15:25:58 -070089 setGridSize(mCountX, mCountY);
90 }
91
92 @Override
Sebastian Franco317c4fa2023-02-21 17:01:24 -080093 boolean createAreaForResize(int cellX, int cellY, int spanX, int spanY, View dragView,
94 int[] direction, boolean commit) {
Sebastian Francoee1baba2023-02-22 11:23:41 -080095 // Add seam to x position
Sebastian Francoc515d022023-03-01 12:51:12 -080096 if (cellX >= mCountX / 2) {
Sebastian Francoee1baba2023-02-22 11:23:41 -080097 cellX++;
98 }
99 int finalCellX = cellX;
Sebastian Franco96c46e72023-05-08 10:04:44 -0600100 return createReorderAlgorithm().simulateSeam(
Sebastian Francoee1baba2023-02-22 11:23:41 -0800101 () -> super.createAreaForResize(finalCellX, cellY, spanX, spanY, dragView,
102 direction, commit));
Sebastian Franco317c4fa2023-02-21 17:01:24 -0800103 }
104
105 @Override
Sebastian Franco96c46e72023-05-08 10:04:44 -0600106 int[] performReorder(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
107 View dragView, int[] result, int[] resultSpan, int mode) {
108 if (pixelX >= getWidth() / 2) {
109 pixelX += getCellWidth();
110 }
111 return super.performReorder(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, dragView,
112 result, resultSpan, mode);
113 }
114
115 @Override
116 public MulticellReorderAlgorithm createReorderAlgorithm() {
Sebastian Francoe4c03452022-12-27 14:50:02 -0600117 return new MulticellReorderAlgorithm(this);
Sebastian Franco09589322022-11-02 15:25:58 -0700118 }
119
120 @Override
Sebastian Francoe4c03452022-12-27 14:50:02 -0600121 public void copyCurrentStateToSolution(ItemConfiguration solution, boolean temp) {
Sebastian Franco09589322022-11-02 15:25:58 -0700122 int childCount = mShortcutsAndWidgets.getChildCount();
123 for (int i = 0; i < childCount; i++) {
124 View child = mShortcutsAndWidgets.getChildAt(i);
125 CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
126 int seamOffset = lp.getCellX() >= mCountX / 2 && lp.canReorder ? 1 : 0;
127 CellAndSpan c = new CellAndSpan(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan,
128 lp.cellVSpan);
129 solution.add(child, c);
130 }
131 }
132
133 @Override
Sebastian Franco25423862023-03-10 10:50:37 -0800134 public int getUnusedHorizontalSpace() {
135 return (int) Math.ceil(
136 (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - (mCountX * mCellWidth)
137 - ((mCountX - 1) * mBorderSpace.x)) / 2f);
138 }
139
140 @Override
Sebastian Franco09589322022-11-02 15:25:58 -0700141 protected void onDraw(Canvas canvas) {
142 if (mLeftBackground.getAlpha() > 0) {
143 mLeftBackground.setState(mBackground.getState());
144 mLeftBackground.draw(canvas);
145 }
146 if (mRightBackground.getAlpha() > 0) {
147 mRightBackground.setState(mBackground.getState());
148 mRightBackground.draw(canvas);
149 }
150
151 super.onDraw(canvas);
152 }
153
154 @Override
155 protected void updateBgAlpha() {
156 mLeftBackground.setAlpha((int) (mSpringLoadedProgress * 255));
157 mRightBackground.setAlpha((int) (mSpringLoadedProgress * 255));
158 }
159
160 @Override
161 protected void onLayout(boolean changed, int l, int t, int r, int b) {
162 super.onLayout(changed, l, t, r, b);
163 Rect rect = mBackground.getBounds();
164 mLeftBackground.setBounds(rect.left, rect.top, rect.right / 2 - 20, rect.bottom);
165 mRightBackground.setBounds(rect.right / 2 + 20, rect.top, rect.right, rect.bottom);
166 }
Sebastian Francoe4c03452022-12-27 14:50:02 -0600167
168 public void setCountX(int countX) {
169 mCountX = countX;
170 }
171
172 public void setCountY(int countY) {
173 mCountY = countY;
174 }
175
176 public void setOccupied(GridOccupancy occupied) {
177 mOccupied = occupied;
178 }
179
180 public boolean isSeamWasAdded() {
181 return mSeamWasAdded;
182 }
183
184 public void setSeamWasAdded(boolean seamWasAdded) {
185 mSeamWasAdded = seamWasAdded;
186 }
Sebastian Franco09589322022-11-02 15:25:58 -0700187}