1 /*
2  * Copyright (C) 2023 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.wallpaper.picker.preview.ui.view
17 
18 import android.content.Context
19 import android.graphics.Point
20 import android.util.AttributeSet
21 import android.widget.FrameLayout
22 import com.android.wallpaper.picker.preview.ui.util.CropSizeUtil.findMaxRectWithRatioIn
23 
24 /**
25  * A [FrameLayout] that scales to largest possible on current display with the size preserving
26  * target display aspect ratio.
27  *
28  * Acts as [FrameLayout] if the current and target display size were not set by the time of
29  * [onMeasure].
30  */
31 class FullPreviewFrameLayout(context: Context, attrs: AttributeSet? = null) :
32     FrameLayout(context, attrs) {
33 
34     // Current display size represents the size of the currently used display. There is only one
35     // size for handheld and tablet devices, but there are 2 sizes for foldable devices.
36     private var currentDisplaySize: Point? = null
37 
38     // Target display size represents the size of the display that a wallpaper aims to be set to.
39     private var targetDisplaySize: Point? = null
40 
onMeasurenull41     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
42         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
43 
44         val currentSize = currentDisplaySize
45         val targetSize = targetDisplaySize
46 
47         if (currentSize == null || targetSize == null) {
48             setMeasuredDimension(widthMeasureSpec, heightMeasureSpec)
49             return
50         }
51 
52         val maxRect = targetSize.findMaxRectWithRatioIn(currentSize)
53         val width = maxRect.x.toInt()
54         val height = maxRect.y.toInt()
55         measureChildren(
56             MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
57             MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
58         )
59     }
60 
61     /**
62      * Sets the target display size and the current display size.
63      *
64      * The view size is maxed out within current display size while preserving the aspect ratio of
65      * the target display size. On a single display device the current display size is always the
66      * target display size.
67      *
68      * @param currentSize current display size used as the max bound of this view.
69      * @param targetSize target display size to get and preserve it's aspect ratio.
70      */
setCurrentAndTargetDisplaySizenull71     fun setCurrentAndTargetDisplaySize(currentSize: Point, targetSize: Point) {
72         currentDisplaySize = currentSize
73         targetDisplaySize = targetSize
74     }
75 }
76