io.docops.asciidoc.buttons.AbstractButtonRenderer.kt Maven / Gradle / Ivy
package io.docops.asciidoc.buttons
import io.docops.asciidoc.buttons.models.Button
import io.docops.asciidoc.buttons.theme.Theme
import kotlin.time.times
abstract class AbstractButtonRenderer {
fun makeButtons(buttons: MutableList>, theme: Theme): String {
val svgBuilder = StringBuilder()
svgBuilder.append(startSvg(height = height(buttons = buttons, theme = theme), width = width(theme = theme), theme = theme))
svgBuilder.append(makeDefs(buttons, theme))
svgBuilder.append(drawButtons(buttonList = buttons, theme = theme))
svgBuilder.append(endSvg())
return joinXmlLines(svgBuilder.toString())
}
abstract fun drawButtons(buttonList: MutableList>, theme: Theme): String
private fun startSvg(height: Float, width: Float, theme: Theme): String {
return """"
}
open fun height(buttons: MutableList>, theme: Theme): Float {
if (buttons.size > 1) {
return (buttons.size * BUTTON_HEIGHT + (buttons.size * 10)) * theme.scale
}
val h = BUTTON_HEIGHT + 20
return h * theme.scale
}
open fun width(theme: Theme): Float {
return (theme.columns * BUTTON_WIDTH + theme.columns * BUTTON_PADDING + theme.columns * BUTTON_PADDING) * theme.scale
}
private fun makeDefs(buttons: MutableList>, theme: Theme): String {
val btnGrad = StringBuilder()
buttons.forEach { button ->
button.forEach { item ->
theme.buttonTextColor(item)
btnGrad.append(theme.buildGradientStyle(item))
}
}
var linear = ""
theme.gradientStyle?.let { linear = it.gradientIdToXml() }
val btnDef = StringBuilder("")
buttons.forEach { btn ->
btn.forEach {
btnDef.append(theme.buildGradientDef(it))
}
}
val filters = """
"""
var str = ""
theme.buttonStyleMap.forEach { (t, u) ->
str += "#${theme.id} .$u {$t}\n"
}
//language="html"
val style = """
"""
return """
$filters
$linear
$btnDef
${theme.defs}
$style
""".trimIndent()
}
private fun joinXmlLines(str: String): String {
val sb = StringBuilder()
str.lines().forEach {
sb.append(it.trim())
}
return sb.toString()
}
companion object {
const val BUTTON_HEIGHT: Int = 30
const val BUTTON_WIDTH = 300
const val BUTTON_PADDING = 5
const val BUTTON_SPACING = 10
}
}
fun generateRectPathData(width: Float, height: Float, topLetRound:Float, topRightRound:Float, bottomRightRound:Float, bottomLeftRound:Float): String {
return """M 0 $topLetRound A $topLetRound $topLetRound 0 0 1 $topLetRound 0 L ${(width - topRightRound)} 0 A $topRightRound $topRightRound 0 0 1 $width $topRightRound L $width ${(height - bottomRightRound)} A $bottomRightRound $bottomRightRound 0 0 1 ${(width - bottomRightRound)} $height L $bottomLeftRound $height A $bottomLeftRound $bottomLeftRound 0 0 1 0 ${(height - bottomLeftRound)} Z"""
}
fun wrapText(text: String, width: Float) : MutableList {
val sb = StringBuilder()
val words = text.split(" ")
var rowText = ""
val lines = mutableListOf()
words.forEachIndexed { index, s ->
if(rowText.length + s.length > width) {
lines.add(rowText)
rowText = s
//close tspan, initialize rowtext and set s
} else {
rowText += " $s"
}
}
if(rowText.trim().isNotEmpty()) {
lines.add(rowText)
}
return lines
}
fun linesToMultiLineText(lines: MutableList, dy: Int, x: Int): String {
var text = StringBuilder()
lines.forEach {
text.append("""$it """)
}
return text.toString()
}