1 /*
<lambda>null2  * Copyright 2022 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.internal
18 
19 import androidx.compose.foundation.interaction.InteractionSource
20 import androidx.compose.foundation.interaction.PressInteraction
21 import androidx.compose.ui.geometry.Offset
22 import kotlinx.coroutines.flow.map
23 
24 /**
25  * Adapts an [InteractionSource] from one component to another by mapping any interactions by a
26  * given offset. Namely used for the pill indicator in [NavigationBarItem] and [NavigationRailItem].
27  */
28 internal class MappedInteractionSource(
29     underlyingInteractionSource: InteractionSource,
30     private val delta: Offset
31 ) : InteractionSource {
32     private val mappedPresses = mutableMapOf<PressInteraction.Press, PressInteraction.Press>()
33 
34     override val interactions =
35         underlyingInteractionSource.interactions.map { interaction ->
36             when (interaction) {
37                 is PressInteraction.Press -> {
38                     val mappedPress = mapPress(interaction)
39                     mappedPresses[interaction] = mappedPress
40                     mappedPress
41                 }
42                 is PressInteraction.Cancel -> {
43                     val mappedPress = mappedPresses.remove(interaction.press)
44                     if (mappedPress == null) {
45                         interaction
46                     } else {
47                         PressInteraction.Cancel(mappedPress)
48                     }
49                 }
50                 is PressInteraction.Release -> {
51                     val mappedPress = mappedPresses.remove(interaction.press)
52                     if (mappedPress == null) {
53                         interaction
54                     } else {
55                         PressInteraction.Release(mappedPress)
56                     }
57                 }
58                 else -> interaction
59             }
60         }
61 
62     private fun mapPress(press: PressInteraction.Press): PressInteraction.Press =
63         PressInteraction.Press(press.pressPosition - delta)
64 }
65