1 /*
2  * Copyright 2024 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.contextmenu.provider
18 
19 import androidx.compose.foundation.text.contextmenu.data.TextContextMenuData
20 import androidx.compose.foundation.text.contextmenu.modifier.addTextContextMenuComponents
21 import androidx.compose.foundation.text.contextmenu.modifier.filterTextContextMenuComponents
22 import androidx.compose.runtime.CompositionLocalProvider
23 import androidx.compose.runtime.ProvidableCompositionLocal
24 import androidx.compose.runtime.compositionLocalOf
25 import androidx.compose.ui.geometry.Offset
26 import androidx.compose.ui.geometry.Rect
27 import androidx.compose.ui.layout.LayoutCoordinates
28 
29 /**
30  * The provider determines how the context menu is shown and its appearance.
31  *
32  * The context menu can be customized by providing another implementation of this to
33  * [LocalTextContextMenuDropdownProvider] or [LocalTextContextMenuToolbarProvider] via a
34  * [CompositionLocalProvider].
35  *
36  * If you want to modify the contents of the context menu, see
37  * [Modifier.addTextContextMenuComponents][addTextContextMenuComponents] and
38  * [Modifier.filterTextContextMenuComponents][filterTextContextMenuComponents]
39  */
40 // TODO(grantapher-cm-api-publicize) Make interface public
41 internal interface TextContextMenuProvider {
42     /**
43      * Shows the text context menu.
44      *
45      * This function suspends until the context menu is closed. If the coroutine is cancelled, the
46      * context menu will be closed.
47      *
48      * @param dataProvider provides the data necessary to show the text context menu.
49      */
showTextContextMenunull50     suspend fun showTextContextMenu(dataProvider: TextContextMenuDataProvider)
51 }
52 
53 /** Provide a [TextContextMenuProvider] to be used for the text context menu dropdown. */
54 // TODO(grantapher-cm-api-publicize) Make val public
55 internal val LocalTextContextMenuDropdownProvider:
56     ProvidableCompositionLocal<TextContextMenuProvider?> =
57     compositionLocalOf {
58         null
59     }
60 
61 /** Provide a [TextContextMenuProvider] to be used for the text context menu toolbar. */
62 // TODO(grantapher-cm-api-publicize) Make val public
63 internal val LocalTextContextMenuToolbarProvider:
64     ProvidableCompositionLocal<TextContextMenuProvider?> =
<lambda>null65     compositionLocalOf {
66         null
67     }
68 
69 /**
70  * Provides the data necessary to show the text context menu.
71  *
72  * All functions on this interface are expected to be snapshot-aware.
73  */
74 // TODO(grantapher-cm-api-publicize) Make interface public
75 internal interface TextContextMenuDataProvider {
76     /**
77      * Provides the position to place the context menu around. The position should be relative to
78      * the provided [destinationCoordinates].
79      *
80      * This function is snapshot-aware.
81      */
positionnull82     fun position(destinationCoordinates: LayoutCoordinates): Offset
83 
84     /**
85      * Provides a bounding box to place the context menu around. The position should be relative to
86      * the provided [destinationCoordinates].
87      *
88      * This function is snapshot-aware.
89      */
90     fun contentBounds(destinationCoordinates: LayoutCoordinates): Rect
91 
92     /**
93      * Provides the components used to fill the context menu.
94      *
95      * This function is snapshot-aware.
96      */
97     fun data(): TextContextMenuData
98 }
99