1 /*
2  * Copyright (C) 2019 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.touch;
18 
19 import static android.view.Gravity.BOTTOM;
20 import static android.view.Gravity.CENTER_VERTICAL;
21 import static android.view.Gravity.END;
22 import static android.view.Gravity.START;
23 import static android.view.Gravity.TOP;
24 
25 import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
26 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
27 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
28 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
29 
30 import android.content.res.Resources;
31 import android.graphics.PointF;
32 import android.graphics.Rect;
33 import android.util.Pair;
34 import android.view.Surface;
35 import android.view.View;
36 import android.widget.FrameLayout;
37 import android.widget.LinearLayout;
38 
39 import com.android.launcher3.DeviceProfile;
40 import com.android.launcher3.R;
41 import com.android.launcher3.Utilities;
42 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
43 import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
44 import com.android.launcher3.views.BaseDragLayer;
45 
46 import java.util.Collections;
47 import java.util.List;
48 
49 public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
50 
51     @Override
getSecondaryTranslationDirectionFactor()52     public int getSecondaryTranslationDirectionFactor() {
53         return -1;
54     }
55 
56     @Override
getSplitTranslationDirectionFactor(int stagePosition, DeviceProfile deviceProfile)57     public int getSplitTranslationDirectionFactor(int stagePosition, DeviceProfile deviceProfile) {
58         if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
59             return -1;
60         } else {
61             return 1;
62         }
63     }
64 
65     @Override
getRecentsRtlSetting(Resources resources)66     public boolean getRecentsRtlSetting(Resources resources) {
67         return Utilities.isRtl(resources);
68     }
69 
70     @Override
getDegreesRotated()71     public float getDegreesRotated() {
72         return 270;
73     }
74 
75     @Override
getRotation()76     public int getRotation() {
77         return Surface.ROTATION_270;
78     }
79 
80     @Override
adjustFloatingIconStartVelocity(PointF velocity)81     public void adjustFloatingIconStartVelocity(PointF velocity) {
82         float oldX = velocity.x;
83         float oldY = velocity.y;
84         velocity.set(oldY, -oldX);
85     }
86 
87     @Override
getTaskMenuX(float x, View thumbnailView, int overScroll, DeviceProfile deviceProfile)88     public float getTaskMenuX(float x, View thumbnailView, int overScroll,
89             DeviceProfile deviceProfile) {
90         return x;
91     }
92 
93     @Override
getTaskMenuY(float y, View thumbnailView, int overScroll)94     public float getTaskMenuY(float y, View thumbnailView, int overScroll) {
95         return y + overScroll +
96                 (thumbnailView.getMeasuredHeight() + thumbnailView.getMeasuredWidth()) / 2f;
97     }
98 
99     @Override
setTaskMenuAroundTaskView(LinearLayout taskView, float margin)100     public void setTaskMenuAroundTaskView(LinearLayout taskView, float margin) {
101         BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskView.getLayoutParams();
102         lp.bottomMargin += margin;
103     }
104 
105     @Override
getAdditionalInsetForTaskMenu(float margin)106     public PointF getAdditionalInsetForTaskMenu(float margin) {
107         return new PointF(-margin, margin);
108     }
109 
110     @Override
setDwbLayoutParamsAndGetTranslations(int taskViewWidth, int taskViewHeight, StagedSplitBounds splitBounds, DeviceProfile deviceProfile, View[] thumbnailViews, int desiredTaskId, View banner)111     public Pair<Float, Float> setDwbLayoutParamsAndGetTranslations(int taskViewWidth,
112             int taskViewHeight, StagedSplitBounds splitBounds, DeviceProfile deviceProfile,
113             View[] thumbnailViews, int desiredTaskId, View banner) {
114         float translationX = 0;
115         float translationY = 0;
116         FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams();
117         banner.setPivotX(0);
118         banner.setPivotY(0);
119         banner.setRotation(getDegreesRotated());
120         FrameLayout.LayoutParams snapshotParams =
121                 (FrameLayout.LayoutParams) thumbnailViews[0]
122                         .getLayoutParams();
123         bannerParams.gravity = BOTTOM | END;
124         translationX = taskViewWidth - banner.getHeight();
125         if (splitBounds == null) {
126             // Single, fullscreen case
127             bannerParams.width = taskViewHeight - snapshotParams.topMargin;
128             translationY = banner.getHeight();
129             return new Pair<>(translationX, translationY);
130         }
131 
132         // Set correct width
133         if (desiredTaskId == splitBounds.leftTopTaskId) {
134             bannerParams.width = thumbnailViews[1].getMeasuredHeight();
135         } else {
136             bannerParams.width = thumbnailViews[0].getMeasuredHeight();
137         }
138 
139         // Set translations
140         if (desiredTaskId == splitBounds.rightBottomTaskId) {
141             translationY = -(taskViewHeight - snapshotParams.topMargin)
142                     * (1f - splitBounds.leftTaskPercent)
143                     + banner.getHeight();
144         }
145         if (desiredTaskId == splitBounds.leftTopTaskId) {
146             translationY = banner.getHeight();
147         }
148         return new Pair<>(translationX, translationY);
149     }
150 
151     @Override
getDistanceToBottomOfRect(DeviceProfile dp, Rect rect)152     public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) {
153         return dp.widthPx - rect.right;
154     }
155 
156     @Override
getSplitPositionOptions(DeviceProfile dp)157     public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
158         // Add "right" option which is actually the top
159         return Collections.singletonList(new SplitPositionOption(
160                 R.drawable.ic_split_right, R.string.split_screen_position_right,
161                 STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
162     }
163 
164     @Override
setIconAndSnapshotParams(View mIconView, int taskIconMargin, int taskIconHeight, FrameLayout.LayoutParams snapshotParams, boolean isRtl)165     public void setIconAndSnapshotParams(View mIconView, int taskIconMargin, int taskIconHeight,
166             FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
167         FrameLayout.LayoutParams iconParams =
168                 (FrameLayout.LayoutParams) mIconView.getLayoutParams();
169         iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
170         iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
171         iconParams.rightMargin = 0;
172         iconParams.topMargin = snapshotParams.topMargin / 2;
173     }
174 
175     @Override
setSplitIconParams(View primaryIconView, View secondaryIconView, int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight, boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig)176     public void setSplitIconParams(View primaryIconView, View secondaryIconView,
177             int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
178             boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
179         super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight,
180                 primarySnapshotWidth, primarySnapshotHeight, isRtl, deviceProfile, splitConfig);
181         FrameLayout.LayoutParams primaryIconParams =
182                 (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
183         FrameLayout.LayoutParams secondaryIconParams =
184                 (FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
185 
186         primaryIconParams.gravity = (isRtl ? END : START) | TOP;
187         secondaryIconParams.gravity = (isRtl ? END : START) | TOP;
188         primaryIconView.setLayoutParams(primaryIconParams);
189         secondaryIconView.setLayoutParams(secondaryIconParams);
190     }
191 
192     /* ---------- The following are only used by TaskViewTouchHandler. ---------- */
193 
194     @Override
getUpDownSwipeDirection()195     public SingleAxisSwipeDetector.Direction getUpDownSwipeDirection() {
196         return HORIZONTAL;
197     }
198 
199     @Override
getUpDirection(boolean isRtl)200     public int getUpDirection(boolean isRtl) {
201         return isRtl ? SingleAxisSwipeDetector.DIRECTION_POSITIVE
202                 : SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
203     }
204 
205     @Override
isGoingUp(float displacement, boolean isRtl)206     public boolean isGoingUp(float displacement, boolean isRtl) {
207         return isRtl ? displacement > 0 : displacement < 0;
208     }
209 
210     @Override
getTaskDragDisplacementFactor(boolean isRtl)211     public int getTaskDragDisplacementFactor(boolean isRtl) {
212         return isRtl ? -1 : 1;
213     }
214 
215     /* -------------------- */
216 }
217