1 /*
2  * Copyright (C) 2024 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.widget.util;
18 
19 import static com.android.launcher3.widget.util.WidgetSizes.getWidgetSizePx;
20 
21 import android.content.Context;
22 import android.util.Size;
23 
24 import androidx.annotation.Px;
25 
26 import com.android.launcher3.DeviceProfile;
27 import com.android.launcher3.R;
28 import com.android.launcher3.model.data.ItemInfo;
29 
30 /** Utility classes to evaluate widget scale during drag and drops. **/
31 public final class WidgetDragScaleUtils {
32     // Widgets are 5% scaled down relative to their size to have shadow display well inside the
33     // drop target frame (if its possible to scale it down within visible area under the finger).
34     private static final float WIDGET_SCALE_DOWN = 0.05f;
35 
36     /**
37      * Returns the scale to be applied to given dragged view to scale it down relative to the
38      * spring loaded workspace. Applies additional scale down offset to get it a little inside
39      * the drop target frame. If the relative scale is smaller than minimum size needed to keep the
40      * view visible under the finger, scale down is performed only until the minimum size.
41      */
42     @Px
getWidgetDragScalePx(Context context, DeviceProfile deviceProfile, @Px float draggedViewWidthPx, @Px float draggedViewHeightPx, ItemInfo itemInfo)43     public static float getWidgetDragScalePx(Context context, DeviceProfile deviceProfile,
44             @Px float draggedViewWidthPx, @Px float draggedViewHeightPx, ItemInfo itemInfo) {
45         int minSize = context.getResources().getDimensionPixelSize(
46                 R.dimen.widget_drag_view_min_scale_down_size);
47         Size widgetSizesPx = getWidgetSizePx(deviceProfile, itemInfo.spanX, itemInfo.spanY);
48 
49         // We add workspace spring load scale, since the widget's drop target is also scaled, so
50         // the widget size is essentially that smaller.
51         float desiredWidgetScale = deviceProfile.getWorkspaceSpringLoadScale(context)
52                 - WIDGET_SCALE_DOWN;
53         float desiredWidgetWidthPx = Math.max(minSize,
54                 (desiredWidgetScale * widgetSizesPx.getWidth()));
55         float desiredWidgetHeightPx = Math.max(minSize,
56                 desiredWidgetScale * widgetSizesPx.getHeight());
57 
58         final float bitmapAspectRatio = draggedViewWidthPx / draggedViewHeightPx;
59         final float containerAspectRatio = desiredWidgetWidthPx / desiredWidgetHeightPx;
60 
61         // This downscales large views to fit inside drop target frame. Smaller drawable views may
62         // be up-scaled if they are smaller than the min size;
63         final float scale = bitmapAspectRatio >= containerAspectRatio ? desiredWidgetWidthPx
64                 / draggedViewWidthPx : desiredWidgetHeightPx / draggedViewHeightPx;
65         // scale in terms of dp to be applied to the drag shadow during drag and drop
66         return (draggedViewWidthPx * scale) - draggedViewWidthPx;
67     }
68 }
69