commonMain.jetbrains.datalore.plot.builder.interact.GeomInteractionBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lets-plot-common Show documentation
Show all versions of lets-plot-common Show documentation
Lets-Plot JVM package without rendering part
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.plot.builder.interact
import jetbrains.datalore.plot.base.Aes
import jetbrains.datalore.plot.base.interact.GeomTargetLocator.LookupSpace
import jetbrains.datalore.plot.base.interact.GeomTargetLocator.LookupStrategy
import jetbrains.datalore.plot.builder.tooltip.TooltipSpecification
import jetbrains.datalore.plot.builder.tooltip.TooltipLine
import jetbrains.datalore.plot.builder.tooltip.ValueSource
import jetbrains.datalore.plot.builder.tooltip.MappingValue
import jetbrains.datalore.plot.builder.tooltip.ConstantValue
class GeomInteractionBuilder(private val mySupportedAesList: List>) {
private var myIgnoreInvisibleTargets: Boolean = false
lateinit var locatorLookupSpace: LookupSpace
private set
lateinit var locatorLookupStrategy: LookupStrategy
private set
private var myAxisTooltipVisibilityFromFunctionKind: Boolean = false
private var myAxisTooltipVisibilityFromConfig: Boolean? = null
private var myAxisAesFromFunctionKind: List>? = null
private lateinit var myTooltipAxisAes: List>
private lateinit var myTooltipAes: List>
private lateinit var myTooltipOutlierAesList: List>
private var myTooltipConstantsAesList: Map, Any>? = null
private var myUserTooltipSpec: TooltipSpecification? = null
private var myIsCrosshairEnabled: Boolean = false
val getAxisFromFunctionKind: List>
get() = myAxisAesFromFunctionKind ?: emptyList()
val isAxisTooltipEnabled: Boolean
get() = if (myAxisTooltipVisibilityFromConfig == null)
myAxisTooltipVisibilityFromFunctionKind
else
myAxisTooltipVisibilityFromConfig!!
val tooltipLines: List
get() = prepareTooltipValueSources()
val tooltipProperties: TooltipSpecification.TooltipProperties
get() = myUserTooltipSpec?.tooltipProperties ?: TooltipSpecification.TooltipProperties.NONE
val isCrosshairEnabled: Boolean
get() = myIsCrosshairEnabled
fun showAxisTooltip(isTrue: Boolean): GeomInteractionBuilder {
myAxisTooltipVisibilityFromConfig = isTrue
return this
}
fun tooltipAes(aes: List>): GeomInteractionBuilder {
myTooltipAes = aes
return this
}
fun axisAes(axisAes: List>): GeomInteractionBuilder {
myTooltipAxisAes = axisAes
return this
}
fun tooltipOutliers(aes: List>): GeomInteractionBuilder {
myTooltipOutlierAesList = aes
return this
}
fun tooltipConstants(constantsMap: Map, Any>): GeomInteractionBuilder {
myTooltipConstantsAesList = constantsMap
return this
}
fun tooltipLinesSpec(tooltipSpec: TooltipSpecification): GeomInteractionBuilder {
myUserTooltipSpec = tooltipSpec
return this
}
fun setIsCrosshairEnabled(isTrue: Boolean): GeomInteractionBuilder {
myIsCrosshairEnabled = isTrue
return this
}
fun multilayerLookupStrategy(): GeomInteractionBuilder {
locatorLookupStrategy = LookupStrategy.NEAREST
locatorLookupSpace = LookupSpace.XY
return this
}
fun univariateFunction(lookupStrategy: LookupStrategy): GeomInteractionBuilder {
myAxisAesFromFunctionKind = AES_X
locatorLookupStrategy = lookupStrategy
myAxisTooltipVisibilityFromFunctionKind = true
locatorLookupSpace = LookupSpace.X
initDefaultTooltips()
return this
}
fun bivariateFunction(area: Boolean): GeomInteractionBuilder {
myAxisAesFromFunctionKind = AES_XY
if (area) {
locatorLookupStrategy = LookupStrategy.HOVER
myAxisTooltipVisibilityFromFunctionKind = false
} else {
locatorLookupStrategy = LookupStrategy.NEAREST
myAxisTooltipVisibilityFromFunctionKind = true
}
locatorLookupSpace = LookupSpace.XY
initDefaultTooltips()
return this
}
fun none(): GeomInteractionBuilder {
myAxisAesFromFunctionKind = ArrayList(mySupportedAesList)
locatorLookupStrategy = LookupStrategy.NONE
myAxisTooltipVisibilityFromFunctionKind = true
locatorLookupSpace = LookupSpace.NONE
initDefaultTooltips()
return this
}
private fun initDefaultTooltips() {
myTooltipAxisAes = if (!isAxisTooltipEnabled) emptyList() else getAxisFromFunctionKind
myTooltipAes = mySupportedAesList - getAxisFromFunctionKind
myTooltipOutlierAesList = emptyList()
}
private fun prepareTooltipValueSources(): List {
return when {
myUserTooltipSpec == null -> {
// No user tooltip specification => use default tooltips
defaultValueSourceTooltipLines(
myTooltipAes,
myTooltipAxisAes,
myTooltipOutlierAesList,
userDefinedValueSources = null,
constantsMap = myTooltipConstantsAesList
)
}
myUserTooltipSpec!!.tooltipLinePatterns == null -> {
// No user line patterns => use default tooltips with the given formatted valueSources
defaultValueSourceTooltipLines(
myTooltipAes,
myTooltipAxisAes,
myTooltipOutlierAesList,
myUserTooltipSpec!!.valueSources,
myTooltipConstantsAesList
)
}
myUserTooltipSpec!!.tooltipLinePatterns!!.isEmpty() -> {
// User list is empty => not show tooltips
emptyList()
}
else -> {
// Form value sources: user list + axis + outliers
val geomOutliers = myTooltipOutlierAesList.toMutableList()
// Remove outlier tooltip if the mappedAes is used in the general tooltip
myUserTooltipSpec!!.tooltipLinePatterns!!.forEach { line ->
val userDataAesList = line.fields.filterIsInstance().map { it.aes }
geomOutliers.removeAll(userDataAesList)
}
val axisValueSources = myTooltipAxisAes.map { aes -> MappingValue(aes, isOutlier = true, isAxis = true) }
val geomOutlierValueSources = geomOutliers.map { aes ->
val formatted = myUserTooltipSpec!!.valueSources.filterIsInstance().find { it.aes == aes }
formatted?.toOutlier() ?: MappingValue(aes, isOutlier = true)
}
myUserTooltipSpec!!.tooltipLinePatterns!! + (axisValueSources + geomOutlierValueSources).map(TooltipLine.Companion::defaultLineForValueSource)
}
}
}
fun build(): GeomInteraction {
return GeomInteraction(this)
}
fun ignoreInvisibleTargets(isTrue: Boolean): GeomInteractionBuilder {
myIgnoreInvisibleTargets = isTrue
return this
}
fun isIgnoringInvisibleTargets(): Boolean {
return myIgnoreInvisibleTargets
}
companion object {
const val AREA_GEOM = true
const val NON_AREA_GEOM = false
private val AES_X = listOf(Aes.X)
private val AES_XY = listOf(Aes.X, Aes.Y)
fun defaultValueSourceTooltipLines(
aesListForTooltip: List>,
axisAes: List>,
outliers: List>,
userDefinedValueSources: List? = null,
constantsMap: Map, Any>? = null
): List {
val axisValueSources = axisAes.map { aes -> MappingValue(aes, isOutlier = true, isAxis = true) }
val outlierValueSources = outliers.map { aes ->
val userDefined = userDefinedValueSources?.filterIsInstance()?.find { it.aes == aes }
userDefined?.toOutlier() ?: MappingValue(aes, isOutlier = true)
}
val aesValueSources = aesListForTooltip.map { aes ->
val userDefined = userDefinedValueSources?.filterIsInstance()?.find { it.aes == aes }
userDefined ?: MappingValue(aes)
}
val constantValues = constantsMap?.map { (_, value) -> ConstantValue(value, format = null) } ?: emptyList()
return (aesValueSources + axisValueSources + outlierValueSources + constantValues).map(TooltipLine.Companion::defaultLineForValueSource)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy