1 /*
2  * Copyright 2021 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.foundation.text
18 
19 import androidx.compose.runtime.Stable
20 import androidx.compose.ui.text.input.ImeAction
21 
22 /**
23  * The [KeyboardActions] class allows developers to specify actions that will be triggered in
24  * response to users triggering IME action on the software keyboard.
25  */
26 @Stable
27 class KeyboardActions(
28     /**
29      * This is run when the user triggers the [Done][ImeAction.Done] action. A null value indicates
30      * that the default implementation if any, should be executed.
31      */
32     val onDone: (KeyboardActionScope.() -> Unit)? = null,
33 
34     /**
35      * This is run when the user triggers the [Go][ImeAction.Go] action. A null value indicates that
36      * the default implementation if any, should be executed.
37      */
38     val onGo: (KeyboardActionScope.() -> Unit)? = null,
39 
40     /**
41      * This is run when the user triggers the [Next][ImeAction.Next] action. A null value indicates
42      * that the default implementation should be executed. The default implementation moves focus to
43      * the next item in the focus traversal order.
44      *
45      * See [Modifier.focusProperties()][androidx.compose.ui.focus.focusProperties] for more details
46      * on how to specify a custom focus order if needed.
47      */
48     val onNext: (KeyboardActionScope.() -> Unit)? = null,
49 
50     /**
51      * This is run when the user triggers the [Previous][ImeAction.Previous] action. A null value
52      * indicates that the default implementation should be executed. The default implementation
53      * moves focus to the previous item in the focus traversal order.
54      *
55      * See [Modifier.focusProperties()][androidx.compose.ui.focus.focusProperties] for more details
56      * on how to specify a custom focus order if needed.
57      */
58     val onPrevious: (KeyboardActionScope.() -> Unit)? = null,
59 
60     /**
61      * This is run when the user triggers the [Search][ImeAction.Search] action. A null value
62      * indicates that the default implementation if any, should be executed.
63      */
64     val onSearch: (KeyboardActionScope.() -> Unit)? = null,
65 
66     /**
67      * This is run when the user triggers the [Send][ImeAction.Send] action. A null value indicates
68      * that the default implementation if any, should be executed.
69      */
70     val onSend: (KeyboardActionScope.() -> Unit)? = null
71 ) {
72 
equalsnull73     override fun equals(other: Any?): Boolean {
74         if (this === other) return true
75         if (other !is KeyboardActions) return false
76 
77         return onDone === other.onDone &&
78             onGo === other.onGo &&
79             onNext === other.onNext &&
80             onPrevious === other.onPrevious &&
81             onSearch === other.onSearch &&
82             onSend === other.onSend
83     }
84 
hashCodenull85     override fun hashCode(): Int {
86         var result = onDone?.hashCode() ?: 0
87         result = 31 * result + (onGo?.hashCode() ?: 0)
88         result = 31 * result + (onNext?.hashCode() ?: 0)
89         result = 31 * result + (onPrevious?.hashCode() ?: 0)
90         result = 31 * result + (onSearch?.hashCode() ?: 0)
91         result = 31 * result + (onSend?.hashCode() ?: 0)
92         return result
93     }
94 
95     companion object {
96         /**
97          * Use this default value if you don't want to specify any action but want to use the
98          * default action implementations.
99          */
100         @Stable val Default: KeyboardActions = KeyboardActions()
101     }
102 }
103 
104 /** Creates an instance of [KeyboardActions] that uses the specified lambda for all [ImeAction]s. */
KeyboardActionsnull105 fun KeyboardActions(onAny: KeyboardActionScope.() -> Unit): KeyboardActions =
106     KeyboardActions(
107         onDone = onAny,
108         onGo = onAny,
109         onNext = onAny,
110         onPrevious = onAny,
111         onSearch = onAny,
112         onSend = onAny
113     )
114 
115 /** This scope can be used to execute the default action implementation. */
116 interface KeyboardActionScope {
117     /** Runs the default implementation for the specified [action][ImeAction]. */
118     fun defaultKeyboardAction(imeAction: ImeAction)
119 }
120