All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.jetbrains.datalore.plot.builder.defaultTheme.ThemeValuesAccess.kt Maven / Gradle / Ivy

There is a newer version: 4.5.3-alpha1
Show newest version
/*
 * Copyright (c) 2021. 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.defaultTheme

import jetbrains.datalore.base.values.Color
import jetbrains.datalore.base.values.Colors
import jetbrains.datalore.base.values.FontFace
import jetbrains.datalore.base.values.FontFamily
import jetbrains.datalore.plot.builder.defaultTheme.values.ThemeOption.Elem
import jetbrains.datalore.plot.builder.layout.Margins
import jetbrains.datalore.plot.builder.layout.TextJustification
import jetbrains.datalore.plot.builder.presentation.FontFamilyRegistry
import jetbrains.datalore.plot.builder.theme.ThemeTextStyle

internal open class ThemeValuesAccess(
    private val values: Map,
    private val fontFamilyRegistry: FontFamilyRegistry
) {
    private val mem: MutableMap = HashMap()

    protected operator fun get(key: String): Any? = values[key]
    protected fun getValue(key: String): Any = values.getValue(key)

    /**
     * @param key List of option names: the most specific - first.
     */
    private fun getValue(key: List): Any {
        val specificOption = key.first()
        return mem.getOrPut(specificOption) {
            return key.firstNotNullOfOrNull { values[it] }
                ?: throw IllegalStateException("No theme value found. Key : $key.")
        }
    }

    protected fun getNumber(key: List): Double {
        val value = getValue(key)
        return (value as? Number)?.toDouble()
            ?: throw IllegalStateException("Theme value is not a number: $value. Key : $key.")
    }

    protected fun getBoolean(key: List): Boolean {
        val value = getValue(key)
        return (value as? Boolean)
            ?: throw IllegalStateException("Theme value is not boolean: $value. Key : $key.")
    }

    /**
     * @param key List of option names: the most specific - first.
     */
    protected fun getElemValue(key: List): Map {
        val specificOption = key.first()
        @Suppress("UNCHECKED_CAST")
        return mem.getOrPut(specificOption) {
            return key.asReversed().map { values[it] }
                .fold(HashMap()) { acc, v ->
                    if (v != null) {
                        acc.putAll(v as Map)
                    }
                    acc
                }
        } as Map
    }

    protected fun isElemBlank(key: List): Boolean {
        val blankValue = getElemValue(key)[Elem.BLANK]
        return blankValue != null && blankValue as Boolean
    }

    protected fun getNumber(elem: Map, key: String): Double {
        return (elem.getValue(key) as Number).toDouble()
    }

    protected fun getColor(elem: Map, key: String): Color {
        return when (val value = elem.getValue(key)) {
            is Color -> value
            else -> Colors.parseColor(value as String)
        }
    }

    protected fun getFontFace(elem: Map): FontFace {
        return when (val value = elem.getValue(Elem.FONT_FACE)) {
            is FontFace -> value
            is String -> FontFace.fromString(value)
            else -> FontFace.NORMAL
        }
    }

    private fun getFontFamily(elem: Map): FontFamily {
//        val monospaced = getMonospaced(elem)
        val value = elem.getValue(Elem.FONT_FAMILY) as? String
        return value?.let {
//            FontFamily(it, monospaced)
            fontFamilyRegistry.get(value)
        } ?: throw IllegalStateException("Theme value '${Elem.FONT_FAMILY}' is not a string. Elem : $elem.")
    }

//    private fun getMonospaced(elem: Map): Boolean {
//        val value = elem.getValue(Elem.FONT_MONOSPACED)
//        return (value as? Boolean)
//            ?: throw IllegalStateException("Theme value '${Elem.FONT_MONOSPACED}'  is not a boolean. Elem : $elem.")
//    }

    // element_text(family, face, size, color)
    protected fun getTextStyle(elem: Map): ThemeTextStyle {
        return ThemeTextStyle(
            family = getFontFamily(elem),
            face = getFontFace(elem),
            size = getNumber(elem, Elem.SIZE),
            color = getColor(elem, Elem.COLOR)
        )
    }

    protected fun getTextJustification(elem: Map): TextJustification {
        val hjust = getNumber(elem, Elem.HJUST)
        val vjust = getNumber(elem, Elem.VJUST)
        return TextJustification(hjust, vjust)
    }

    protected fun getMargins(elem: Map): Margins {
        return Margins(
            top = getNumber(elem, Elem.Margin.TOP),
            right = getNumber(elem, Elem.Margin.RIGHT),
            bottom = getNumber(elem, Elem.Margin.BOTTOM),
            left = getNumber(elem, Elem.Margin.LEFT),
        )
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy