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.ui.focus.FocusDirection
20 import androidx.compose.ui.focus.FocusManager
21 import androidx.compose.ui.platform.SoftwareKeyboardController
22 import androidx.compose.ui.text.input.ImeAction
23 import androidx.compose.ui.text.input.ImeAction.Companion.Default
24 import androidx.compose.ui.text.input.ImeAction.Companion.Done
25 import androidx.compose.ui.text.input.ImeAction.Companion.Go
26 import androidx.compose.ui.text.input.ImeAction.Companion.Next
27 import androidx.compose.ui.text.input.ImeAction.Companion.None
28 import androidx.compose.ui.text.input.ImeAction.Companion.Previous
29 import androidx.compose.ui.text.input.ImeAction.Companion.Search
30 import androidx.compose.ui.text.input.ImeAction.Companion.Send
31 
32 /** This class can be used to run keyboard actions when the user triggers an IME action. */
33 internal class KeyboardActionRunner(private val keyboardController: SoftwareKeyboardController?) :
34     KeyboardActionScope {
35 
36     /** The developer specified [KeyboardActions]. */
37     lateinit var keyboardActions: KeyboardActions
38 
39     /** A reference to the [FocusManager] composition local. */
40     lateinit var focusManager: FocusManager
41 
42     /**
43      * Run the keyboard action corresponding to the specified imeAction. If a keyboard action is not
44      * specified, use the default implementation provided by [defaultKeyboardAction].
45      *
46      * @return Whether an action was actually performed.
47      */
runActionnull48     fun runAction(imeAction: ImeAction): Boolean {
49         val keyboardAction =
50             when (imeAction) {
51                 Done -> keyboardActions.onDone
52                 Go -> keyboardActions.onGo
53                 Next -> keyboardActions.onNext
54                 Previous -> keyboardActions.onPrevious
55                 Search -> keyboardActions.onSearch
56                 Send -> keyboardActions.onSend
57                 Default,
58                 None -> null
59                 else -> error("invalid ImeAction")
60             }
61         if (keyboardAction != null) {
62             keyboardAction()
63             return true
64         } else return defaultKeyboardActionWithResult(imeAction)
65     }
66 
67     /**
68      * Performs the default keyboard action for the given [imeAction], if any.
69      *
70      * @return whether an action was actually performed.
71      */
defaultKeyboardActionWithResultnull72     private fun defaultKeyboardActionWithResult(imeAction: ImeAction): Boolean {
73         return when (imeAction) {
74             Next -> {
75                 focusManager.moveFocus(FocusDirection.Next)
76                 true
77             }
78             Previous -> {
79                 focusManager.moveFocus(FocusDirection.Previous)
80                 true
81             }
82             Done -> {
83                 if (keyboardController != null) {
84                     keyboardController.hide()
85                     true
86                 } else false
87             }
88             else -> false
89         }
90     }
91 
92     /** Default implementations for [KeyboardActions]. */
defaultKeyboardActionnull93     override fun defaultKeyboardAction(imeAction: ImeAction) {
94         defaultKeyboardActionWithResult(imeAction)
95     }
96 }
97