blob: d671c7d165a54a9860946acc15d3937f14ee0f82 [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;
26import com.android.launcher3.util.CellAndSpan;
27import com.android.launcher3.util.GridOccupancy;
28
29import java.util.function.Supplier;
30
31/**
32 * CellLayout that simulates a split in the middle for use in foldable devices.
33 */
34public class MultipageCellLayout extends CellLayout {
35
36 private final Drawable mLeftBackground;
37 private final Drawable mRightBackground;
38
39 private View mSeam;
40
41 public MultipageCellLayout(Context context) {
42 this(context, null);
43 }
44
45 public MultipageCellLayout(Context context, AttributeSet attrs) {
46 this(context, attrs, 0);
47 }
48
49 public MultipageCellLayout(Context context, AttributeSet attrs, int defStyle) {
50 super(context, attrs, defStyle);
51 mLeftBackground = getContext().getDrawable(R.drawable.bg_celllayout);
52 mLeftBackground.setCallback(this);
53 mLeftBackground.setAlpha(0);
54
55 mRightBackground = getContext().getDrawable(R.drawable.bg_celllayout);
56 mRightBackground.setCallback(this);
57 mRightBackground.setAlpha(0);
58
59 DeviceProfile deviceProfile = mActivity.getDeviceProfile();
60
61 mCountX = deviceProfile.inv.numColumns * 2;
62 mCountY = deviceProfile.inv.numRows;
63 mSeam = new View(getContext());
64 setGridSize(mCountX, mCountY);
65 }
66
67 @Override
68 ItemConfiguration closestEmptySpaceReorder(int pixelX, int pixelY, int minSpanX, int minSpanY,
69 int spanX, int spanY) {
70 return simulateSeam(
71 () -> super.closestEmptySpaceReorder(pixelX, pixelY, minSpanX, minSpanY, spanX,
72 spanY));
73 }
74
75 @Override
76 protected ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX,
77 int minSpanY, int spanX, int spanY, int[] direction, View dragView, boolean decX,
78 ItemConfiguration solution) {
79 return simulateSeam(
80 () -> super.findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY,
81 direction, dragView, decX, solution));
82 }
83
84 @Override
85 public ItemConfiguration dropInPlaceSolution(int pixelX, int pixelY, int spanX, int spanY,
86 View dragView) {
87 return simulateSeam(
88 () -> super.dropInPlaceSolution(pixelX, pixelY, spanX, spanY, dragView));
89 }
90
91 protected ItemConfiguration simulateSeam(Supplier<ItemConfiguration> f) {
92 CellLayoutLayoutParams lp = new CellLayoutLayoutParams(mCountX / 2, 0, 1, mCountY);
93 lp.canReorder = false;
94 mCountX++;
95 mShortcutsAndWidgets.addViewInLayout(mSeam, lp);
96 GridOccupancy auxGrid = mOccupied;
97 mOccupied = createGridOccupancy();
98 mTmpOccupied = new GridOccupancy(mCountX, mCountY);
99
100 ItemConfiguration res = removeSeamFromSolution(f.get());
101
102 mCountX--;
103 mShortcutsAndWidgets.removeViewInLayout(mSeam);
104 mOccupied = auxGrid;
105 mTmpOccupied = new GridOccupancy(mCountX, mCountY);
106 return res;
107 }
108
109 private ItemConfiguration removeSeamFromSolution(ItemConfiguration solution) {
110 solution.map.forEach((view, cell) -> cell.cellX = cell.cellX > mCountX / 2
111 ? cell.cellX - 1 : cell.cellX);
112 solution.cellX = solution.cellX > mCountX / 2 ? solution.cellX - 1 : solution.cellX;
113 return solution;
114 }
115
116 GridOccupancy createGridOccupancy() {
117 GridOccupancy grid = new GridOccupancy(mCountX, mCountY);
118 for (int i = 0; i < mShortcutsAndWidgets.getChildCount(); i++) {
119 View view = mShortcutsAndWidgets.getChildAt(i);
120 CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams();
121 int seamOffset = lp.getCellX() >= mCountX / 2 && lp.canReorder ? 1 : 0;
122 grid.markCells(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, lp.cellVSpan,
123 true);
124 }
125 return grid;
126 }
127
128 @Override
129 protected void copyCurrentStateToSolution(ItemConfiguration solution, boolean temp) {
130 int childCount = mShortcutsAndWidgets.getChildCount();
131 for (int i = 0; i < childCount; i++) {
132 View child = mShortcutsAndWidgets.getChildAt(i);
133 CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
134 int seamOffset = lp.getCellX() >= mCountX / 2 && lp.canReorder ? 1 : 0;
135 CellAndSpan c = new CellAndSpan(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan,
136 lp.cellVSpan);
137 solution.add(child, c);
138 }
139 }
140
141 @Override
142 protected void onDraw(Canvas canvas) {
143 if (mLeftBackground.getAlpha() > 0) {
144 mLeftBackground.setState(mBackground.getState());
145 mLeftBackground.draw(canvas);
146 }
147 if (mRightBackground.getAlpha() > 0) {
148 mRightBackground.setState(mBackground.getState());
149 mRightBackground.draw(canvas);
150 }
151
152 super.onDraw(canvas);
153 }
154
155 @Override
156 protected void updateBgAlpha() {
157 mLeftBackground.setAlpha((int) (mSpringLoadedProgress * 255));
158 mRightBackground.setAlpha((int) (mSpringLoadedProgress * 255));
159 }
160
161 @Override
162 protected void onLayout(boolean changed, int l, int t, int r, int b) {
163 super.onLayout(changed, l, t, r, b);
164 Rect rect = mBackground.getBounds();
165 mLeftBackground.setBounds(rect.left, rect.top, rect.right / 2 - 20, rect.bottom);
166 mRightBackground.setBounds(rect.right / 2 + 20, rect.top, rect.right, rect.bottom);
167 }
168}