1 /*
2  * Copyright 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 
17 package androidx.compose.material3.adaptive.layout
18 
19 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
20 import androidx.compose.runtime.Stable
21 
22 /**
23  * Provides the information about how the associated pane should be adapted if not all panes can be
24  * displayed in the [PaneAdaptedValue.Expanded] state.
25  */
26 @ExperimentalMaterial3AdaptiveApi
27 @Stable
28 sealed interface AdaptStrategy {
29     /** Override this function to provide the resulted adapted state. */
30     @Deprecated(
31         "This function is deprecated in favor of directly using the info carried by the " +
32             "strategy instances to make adaptation decisions."
33     )
adaptnull34     fun adapt(): PaneAdaptedValue = PaneAdaptedValue.Hidden
35 
36     private class Simple(private val description: String) : AdaptStrategy {
37         override fun toString() = "AdaptStrategy[$description]"
38     }
39 
40     /**
41      * Indicate the associated pane should be reflowed when certain conditions are met. With the
42      * default calculation functions [calculateThreePaneScaffoldValue] we provide, when it's a
43      * single pane layout, a pane with the reflow strategy will be adapted to either:
44      * 1. [PaneAdaptedValue.Reflowed], when either the reflowed pane or the target pane it's
45      *    supposed to be reflowed to is the current destination; or
46      * 2. [PaneAdaptedValue.Hidden] otherwise.
47      *
48      * Note that if the current layout can have more than one horizontal partitions, the pane will
49      * never be reflowed.
50      *
51      * @param targetPane the target pane of the reflowing, i.e., the pane that the reflowed pane
52      *   will be put under.
53      */
54     // TODO(conradchen): Add usage samples.
55     class Reflow(val targetPane: Any) : AdaptStrategy {
toStringnull56         override fun toString() = "AdaptStrategy[Reflow to $targetPane]"
57 
58         override fun equals(other: Any?): Boolean {
59             if (this === other) return true
60             if (other !is Reflow) return false
61             return targetPane == other.targetPane
62         }
63 
hashCodenull64         override fun hashCode(): Int {
65             return targetPane.hashCode()
66         }
67     }
68 
69     companion object {
70         /**
71          * The default [AdaptStrategy] that suggests the layout to hide the associated pane when it
72          * has to be adapted, i.e., cannot be displayed in its [PaneAdaptedValue.Expanded] state.
73          */
74         val Hide: AdaptStrategy = Simple("Hide")
75     }
76 }
77