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.contextmenu 18 19 import androidx.compose.foundation.contextmenu.ContextMenuState.Status 20 import androidx.compose.foundation.internal.checkPrecondition 21 import androidx.compose.runtime.getValue 22 import androidx.compose.runtime.mutableStateOf 23 import androidx.compose.runtime.setValue 24 import androidx.compose.ui.geometry.Offset 25 import androidx.compose.ui.geometry.isSpecified 26 27 private const val UNSPECIFIED_OFFSET_ERROR_MESSAGE = 28 "ContextMenuState.Status should never be open with an unspecified offset. " + 29 "Use ContextMenuState.Status.Closed instead." 30 31 /** Holds state related to the context menu. */ 32 internal class ContextMenuState internal constructor(initialStatus: Status = Status.Closed) { 33 var status by mutableStateOf(initialStatus) 34 toStringnull35 override fun toString(): String = "ContextMenuState(status=$status)" 36 37 override fun hashCode(): Int = status.hashCode() 38 39 override fun equals(other: Any?): Boolean { 40 if (other === this) return true 41 if (other !is ContextMenuState) return false 42 return other.status == this.status 43 } 44 45 /** The status of the context menu. Can be [Open] or [Closed]. */ 46 sealed class Status { 47 /** An open context menu [Status]. */ 48 class Open( 49 /** The offset to open the menu at. It must be specified. */ 50 val offset: Offset 51 ) : Status() { 52 init { <lambda>null53 checkPrecondition(offset.isSpecified) { UNSPECIFIED_OFFSET_ERROR_MESSAGE } 54 } 55 toStringnull56 override fun toString(): String = "Open(offset=$offset)" 57 58 override fun hashCode(): Int = offset.hashCode() 59 60 override fun equals(other: Any?): Boolean { 61 if (other === this) return true 62 if (other !is Open) return false 63 return this.offset == other.offset 64 } 65 } 66 67 /** A closed context menu [Status]. */ 68 object Closed : Status() { toStringnull69 override fun toString(): String = "Closed" 70 } 71 } 72 } 73 74 /** Convenience method to set the state's status to [Status.Closed]. */ 75 internal fun ContextMenuState.close() { 76 status = Status.Closed 77 } 78