net.peanuuutz.fork.ui.preset.TooltipArea.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fork-ui Show documentation
Show all versions of fork-ui Show documentation
Comprehensive API designed for Minecraft modders
The newest version!
/*
* Copyright 2020 The Android Open Source Project
* Modifications Copyright 2022 Peanuuutz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.peanuuutz.fork.ui.preset
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.NonRestartableComposable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import net.peanuuutz.fork.ui.foundation.draw.BorderStroke
import net.peanuuutz.fork.ui.foundation.draw.background
import net.peanuuutz.fork.ui.foundation.draw.border
import net.peanuuutz.fork.ui.foundation.layout.BasicTooltipArea
import net.peanuuutz.fork.ui.foundation.layout.Box
import net.peanuuutz.fork.ui.foundation.layout.PaddingValues
import net.peanuuutz.fork.ui.foundation.layout.padding
import net.peanuuutz.fork.ui.foundation.layout.popup.rememberPointerPopupPositioner
import net.peanuuutz.fork.ui.foundation.layout.sizeIn
import net.peanuuutz.fork.ui.preset.theme.Theme
import net.peanuuutz.fork.ui.ui.context.LocalWindowInfo
import net.peanuuutz.fork.ui.ui.context.UIContext
import net.peanuuutz.fork.ui.ui.draw.Painter
import net.peanuuutz.fork.ui.ui.layout.Constraints.Companion.Unlimited
import net.peanuuutz.fork.ui.ui.layout.EmptyContentBlock
import net.peanuuutz.fork.ui.ui.layout.PopupPositioner
import net.peanuuutz.fork.ui.ui.modifier.Modifier
import net.peanuuutz.fork.ui.ui.unit.IntSize
import net.peanuuutz.fork.util.common.Color
@Composable
fun TooltipArea(
tooltip: (@Composable () -> Unit)?,
context: UIContext,
modifier: Modifier = Modifier,
tooltipAreaStyle: TooltipAreaStyle = Theme.tooltipArea,
tooltipPadding: PaddingValues = TooltipAreaDefaults.TooltipAreaPadding,
positioner: PopupPositioner = rememberPointerPopupPositioner(),
content: @Composable () -> Unit
) {
val resolvedTooltip: @Composable () -> Unit = if (tooltip != null) {
remember(tooltip, tooltipAreaStyle, tooltipPadding) {
@Composable {
val border by tooltipAreaStyle.border()
val background by tooltipAreaStyle.background()
val windowHeight = LocalWindowInfo.current?.size?.height ?: Unlimited
Box(
modifier = Modifier
.sizeIn(
minWidth = TooltipAreaDefaults.TooltipAreaMinSize.width,
maxWidth = TooltipAreaDefaults.TooltipAreaMaxWidth,
minHeight = TooltipAreaDefaults.TooltipAreaMinSize.height,
maxHeight = windowHeight
)
.border(border)
.background(background)
.padding(tooltipPadding)
) {
val contentColor by tooltipAreaStyle.content()
CompositionLocalProvider(
LocalContentColor provides contentColor,
content = tooltip
)
}
}
}
} else {
EmptyContentBlock
}
BasicTooltipArea(
tooltip = resolvedTooltip,
context = context,
modifier = modifier,
positioner = positioner,
content = content
)
}
object TooltipAreaDefaults {
val TooltipAreaMinSize: IntSize = IntSize(4, 14)
const val TooltipAreaMaxWidth: Int = 200
val TooltipAreaPadding: PaddingValues = PaddingValues(2)
}
@Stable
interface TooltipAreaStyle {
@Composable
fun border(): State
@Composable
fun background(): State
@Composable
fun content(): State
@Stable
abstract class Delegated(
val delegate: TooltipAreaStyle
) : TooltipAreaStyle by delegate
}
val Theme.tooltipArea: TooltipAreaStyle
@ReadOnlyComposable
@Composable
get() = LocalTooltipArea.current
@NonRestartableComposable
@Composable
fun TooltipAreaStyleProvider(
tooltipAreaStyle: TooltipAreaStyle,
content: @Composable () -> Unit
) {
CompositionLocalProvider(
LocalTooltipArea provides tooltipAreaStyle,
content = content
)
}
@Stable
class DefaultTooltipAreaStyle(
val border: BorderStroke,
val background: Painter,
val content: Color
) : TooltipAreaStyle {
@Composable
override fun border(): State {
return rememberUpdatedState(border)
}
@Composable
override fun background(): State {
return rememberUpdatedState(background)
}
@Composable
override fun content(): State {
return rememberUpdatedState(content)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is DefaultTooltipAreaStyle) return false
if (border != other.border) return false
if (background != other.background) return false
if (content != other.content) return false
return true
}
override fun hashCode(): Int {
var result = border.hashCode()
result = 31 * result + background.hashCode()
result = 31 * result + content.hashCode()
return result
}
override fun toString(): String {
return "DefaultTooltipAreaStyle(border=$border, background=$background, content=$content)"
}
}