1 /*
2 * Copyright 2020 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.ui.focus
18
19 import androidx.compose.ui.Modifier
20 import androidx.compose.ui.internal.JvmDefaultWithCompatibility
21
22 /**
23 * A [modifier][Modifier.Element] that can be used to set a custom focus traversal order.
24 *
25 * @see Modifier.focusOrder
26 */
27 @Deprecated("Use Modifier.focusProperties() instead")
28 @JvmDefaultWithCompatibility
29 interface FocusOrderModifier : Modifier.Element {
30
31 /**
32 * Populates the [next][FocusOrder.next] / [left][FocusOrder.left] / [right][FocusOrder.right] /
33 * [up][FocusOrder.up] / [down][FocusOrder.down] items if you don't want to use the default
34 * focus traversal order.
35 */
populateFocusOrdernull36 @Suppress("DEPRECATION") fun populateFocusOrder(focusOrder: FocusOrder)
37 }
38
39 /**
40 * Specifies custom focus destinations that are used instead of the default focus traversal order.
41 *
42 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
43 */
44 @Deprecated("Use FocusProperties instead")
45 class FocusOrder internal constructor(private val focusProperties: FocusProperties) {
46 @Suppress("unused") constructor() : this(FocusPropertiesImpl())
47
48 /**
49 * A custom item to be used when the user requests a focus moves to the "next" item.
50 *
51 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
52 */
53 var next: FocusRequester
54 get() = focusProperties.next
55 set(next) {
56 focusProperties.next = next
57 }
58
59 /**
60 * A custom item to be used when the user requests a focus moves to the "previous" item.
61 *
62 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
63 */
64 var previous: FocusRequester
65 get() = focusProperties.previous
66 set(previous) {
67 focusProperties.previous = previous
68 }
69
70 /**
71 * A custom item to be used when the user moves focus "up".
72 *
73 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
74 */
75 var up: FocusRequester
76 get() = focusProperties.up
77 set(up) {
78 focusProperties.up = up
79 }
80
81 /**
82 * A custom item to be used when the user moves focus "down".
83 *
84 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
85 */
86 var down: FocusRequester
87 get() = focusProperties.down
88 set(down) {
89 focusProperties.down = down
90 }
91
92 /**
93 * A custom item to be used when the user requests a focus moves to the "left" item.
94 *
95 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
96 */
97 var left: FocusRequester
98 get() = focusProperties.left
99 set(left) {
100 focusProperties.left = left
101 }
102
103 /**
104 * A custom item to be used when the user requests a focus moves to the "right" item.
105 *
106 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
107 */
108 var right: FocusRequester
109 get() = focusProperties.right
110 set(right) {
111 focusProperties.right = right
112 }
113
114 /**
115 * A custom item to be used when the user requests a focus moves to the "left" in LTR mode and
116 * "right" in RTL mode.
117 *
118 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
119 */
120 var start: FocusRequester
121 get() = focusProperties.start
122 set(start) {
123 focusProperties.start = start
124 }
125
126 /**
127 * A custom item to be used when the user requests a focus moves to the "right" in LTR mode and
128 * "left" in RTL mode.
129 *
130 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
131 */
132 var end: FocusRequester
133 get() = focusProperties.end
134 set(end) {
135 focusProperties.end = end
136 }
137 }
138
139 /**
140 * Use this modifier to specify a custom focus traversal order.
141 *
142 * @param focusOrderReceiver Specifies [FocusRequester]s that are used when the user wants to move
143 * the current focus to the [next][FocusOrder.next] item, or wants to move focus
144 * [left][FocusOrder.left], [right][FocusOrder.right], [up][FocusOrder.up] or
145 * [down][FocusOrder.down].
146 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
147 */
148 @Deprecated(
149 "Use focusProperties() instead",
150 ReplaceWith(
151 "this.focusProperties(focusOrderReceiver)",
152 "androidx.compose.ui.focus.focusProperties"
153 )
154 )
Modifiernull155 fun Modifier.focusOrder(
156 @Suppress("DEPRECATION") focusOrderReceiver: FocusOrder.() -> Unit
157 ): Modifier {
158 val scope = FocusOrderToProperties(focusOrderReceiver)
159 return focusProperties { scope.apply(this) }
160 }
161
162 /**
163 * A modifier that lets you specify a [FocusRequester] for the current composable so that this
164 * [focusRequester] can be used by another composable to specify a custom focus order.
165 *
166 * @sample androidx.compose.ui.samples.CustomFocusOrderSample
167 */
168 @Deprecated(
169 "Use focusRequester() instead",
170 ReplaceWith("this.focusRequester(focusRequester)", "androidx.compose.ui.focus.focusRequester")
171 )
Modifiernull172 fun Modifier.focusOrder(focusRequester: FocusRequester): Modifier = focusRequester(focusRequester)
173
174 /**
175 * A modifier that lets you specify a [FocusRequester] for the current composable along with
176 * [focusOrder].
177 */
178 @Deprecated(
179 "Use focusProperties() and focusRequester() instead",
180 ReplaceWith(
181 "this.focusRequester(focusRequester).focusProperties(focusOrderReceiver)",
182 "androidx.compose.ui.focus.focusProperties, androidx.compose.ui.focus.focusRequester"
183 )
184 )
185 fun Modifier.focusOrder(
186 focusRequester: FocusRequester,
187 @Suppress("DEPRECATION") focusOrderReceiver: FocusOrder.() -> Unit
188 ): Modifier {
189 val scope = FocusOrderToProperties(focusOrderReceiver)
190 return this.focusRequester(focusRequester).focusProperties { scope.apply(this) }
191 }
192
193 @Suppress("DEPRECATION")
194 internal class FocusOrderToProperties(val focusOrderReceiver: FocusOrder.() -> Unit) :
195 FocusPropertiesScope {
applynull196 override fun apply(focusProperties: FocusProperties) {
197 focusOrderReceiver(FocusOrder(focusProperties))
198 }
199 }
200
201 // Note: Implementing function interface is prohibited in K/JS (class A: () -> Unit)
202 // therefore we workaround this limitation by inheriting a fun interface instead
203 internal fun interface FocusPropertiesScope {
applynull204 fun apply(focusProperties: FocusProperties)
205 }
206