From d5b33bcbcca3d9ef512703a42a562770600e6836 Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Sun, 8 Oct 2017 20:03:45 +0200 Subject: Refactoring StyledComponent out of Widget Implementation of border, margin and padding properties --- src/main/kotlin/pl/treksoft/kvision/Showcase.kt | 32 +++- .../pl/treksoft/kvision/core/StyledComponent.kt | 198 +++++++++++++++++++++ src/main/kotlin/pl/treksoft/kvision/core/Types.kt | 21 --- src/main/kotlin/pl/treksoft/kvision/core/Widget.kt | 37 +--- src/main/kotlin/pl/treksoft/kvision/css/Css.kt | 62 +++++++ .../kotlin/pl/treksoft/kvision/panel/SplitPanel.kt | 2 +- src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt | 38 ++++ 7 files changed, 325 insertions(+), 65 deletions(-) create mode 100644 src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt delete mode 100644 src/main/kotlin/pl/treksoft/kvision/core/Types.kt create mode 100644 src/main/kotlin/pl/treksoft/kvision/css/Css.kt create mode 100644 src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt (limited to 'src/main') diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt index aa97a026..dc45e93b 100644 --- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt +++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt @@ -4,7 +4,9 @@ import pl.treksoft.kvision.basic.Label import pl.treksoft.kvision.core.Container import pl.treksoft.kvision.core.Img import pl.treksoft.kvision.core.Root -import pl.treksoft.kvision.core.UNIT +import pl.treksoft.kvision.css.BORDERSTYLE +import pl.treksoft.kvision.css.Border +import pl.treksoft.kvision.css.COLOR import pl.treksoft.kvision.dropdown.DD.* import pl.treksoft.kvision.dropdown.DropDown import pl.treksoft.kvision.html.* @@ -15,6 +17,7 @@ import pl.treksoft.kvision.modal.Confirm import pl.treksoft.kvision.modal.Modal import pl.treksoft.kvision.panel.* import pl.treksoft.kvision.routing.routing +import pl.treksoft.kvision.utils.px class Showcase : ApplicationBase() { @@ -76,12 +79,16 @@ class Showcase : ApplicationBase() { split.add(tabs) val split2 = SplitPanel(DIRECTION.HORIZONTAL) - split2.add(Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" + + val t1 = Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" + "\n" + - "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt.")) - split2.add(Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" + + "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt.") + t1.padding = 5.px() + split2.add(t1) + val t2 = Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" + "\n" + - "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt.")) + "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt.") + t2.padding = 10.px() + split2.add(t2) split.add(split2) root.add(split) split.setEventListener { @@ -94,6 +101,12 @@ class Showcase : ApplicationBase() { val p = Tag(TAG.P, "To jest prawo", align = ALIGN.RIGHT) p.title = "Tytuł" + p.border = Border(3.px(), BORDERSTYLE.SOLID) + p.borderTop = Border(4.px(), BORDERSTYLE.DASHED, COLOR.RED) + p.borderBottom = Border(4.px(), BORDERSTYLE.DASHED, 0x00ff00) + p.borderLeft = Border(4.px(), BORDERSTYLE.SOLID, 0xff00ff) + p.marginTop = 30.px() + p.paddingRight = 30.px() root.add(p) val del = Tag(TAG.DEL, "To jest deleted") root.add(del) @@ -162,13 +175,14 @@ class Showcase : ApplicationBase() { dock.add(Label("up"), SIDE.UP) dock.add(Label("down"), SIDE.DOWN) dock.add(Label("center"), SIDE.CENTER) + dock.border = Border(7.px(), BORDERSTYLE.INSET, 0xdddddd) // root.add(dock) val pa = HPanel(alignItems = FLEXALIGNITEMS.FLEXEND) - pa.add(Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus."),3) - pa.add(Image(Img("kotlin.png")),1) - pa.add(dock,2,alignSelf = FLEXALIGNITEMS.FLEXSTART) - dock.width = 400 to UNIT.px + pa.add(Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus."), 3) + pa.add(Image(Img("kotlin.png")), 1) + pa.add(dock, 2, alignSelf = FLEXALIGNITEMS.FLEXSTART) + dock.width = 400.px() root.add(pa) val modal = Modal("Test okienka") diff --git a/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt b/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt new file mode 100644 index 00000000..5dea72ef --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt @@ -0,0 +1,198 @@ +package pl.treksoft.kvision.core + +import pl.treksoft.kvision.css.Border +import pl.treksoft.kvision.css.CssSize +import pl.treksoft.kvision.snabbdom.StringPair + +abstract class StyledComponent : KVObject { + + var width: CssSize? = null + set(value) { + field = value + refresh() + } + var minWidth: CssSize? = null + set(value) { + field = value + refresh() + } + var maxWidth: CssSize? = null + set(value) { + field = value + refresh() + } + var height: CssSize? = null + set(value) { + field = value + refresh() + } + var minHeight: CssSize? = null + set(value) { + field = value + refresh() + } + var maxHeight: CssSize? = null + set(value) { + field = value + refresh() + } + var border: Border? = null + set(value) { + field = value + refresh() + } + var borderTop: Border? = null + set(value) { + field = value + refresh() + } + var borderRight: Border? = null + set(value) { + field = value + refresh() + } + var borderBottom: Border? = null + set(value) { + field = value + refresh() + } + var borderLeft: Border? = null + set(value) { + field = value + refresh() + } + var margin: CssSize? = null + set(value) { + field = value + refresh() + } + var marginTop: CssSize? = null + set(value) { + field = value + refresh() + } + var marginRight: CssSize? = null + set(value) { + field = value + refresh() + } + var marginBottom: CssSize? = null + set(value) { + field = value + refresh() + } + var marginLeft: CssSize? = null + set(value) { + field = value + refresh() + } + var padding: CssSize? = null + set(value) { + field = value + refresh() + } + var paddingTop: CssSize? = null + set(value) { + field = value + refresh() + } + var paddingRight: CssSize? = null + set(value) { + field = value + refresh() + } + var paddingBottom: CssSize? = null + set(value) { + field = value + refresh() + } + var paddingLeft: CssSize? = null + set(value) { + field = value + refresh() + } + + private var snStyleCache: List? = null + + protected open fun refresh(): StyledComponent { + snStyleCache = null + return this + } + + protected fun getSnStyleInternal(): List { + return snStyleCache ?: { + val s = getSnStyle() + snStyleCache = s + s + }() + } + + @Suppress("ComplexMethod") + protected open fun getSnStyle(): List { + val snstyle = mutableListOf() + width?.let { + snstyle.add("width" to it.first.toString() + it.second.unit) + } + minWidth?.let { + snstyle.add("min-width" to it.first.toString() + it.second.unit) + } + maxWidth?.let { + snstyle.add("max-width" to it.first.toString() + it.second.unit) + } + height?.let { + snstyle.add("height" to it.first.toString() + it.second.unit) + } + minHeight?.let { + snstyle.add("min-height" to it.first.toString() + it.second.unit) + } + maxHeight?.let { + snstyle.add("max-height" to it.first.toString() + it.second.unit) + } + border?.let { + snstyle.add("border" to it.asString()) + } + borderTop?.let { + snstyle.add("border-top" to it.asString()) + } + borderRight?.let { + snstyle.add("border-right" to it.asString()) + } + borderBottom?.let { + snstyle.add("border-bottom" to it.asString()) + } + borderLeft?.let { + snstyle.add("border-left" to it.asString()) + } + margin?.let { + snstyle.add("margin" to it.first.toString() + it.second.unit) + } + marginTop?.let { + snstyle.add("margin-top" to it.first.toString() + it.second.unit) + } + marginRight?.let { + snstyle.add("margin-right" to it.first.toString() + it.second.unit) + } + marginBottom?.let { + snstyle.add("margin-bottom" to it.first.toString() + it.second.unit) + } + marginLeft?.let { + snstyle.add("margin-left" to it.first.toString() + it.second.unit) + } + padding?.let { + snstyle.add("padding" to it.first.toString() + it.second.unit) + } + paddingTop?.let { + snstyle.add("padding-top" to it.first.toString() + it.second.unit) + } + paddingRight?.let { + snstyle.add("padding-right" to it.first.toString() + it.second.unit) + } + paddingBottom?.let { + snstyle.add("padding-bottom" to it.first.toString() + it.second.unit) + } + paddingLeft?.let { + snstyle.add("padding-left" to it.first.toString() + it.second.unit) + } + return snstyle + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Types.kt b/src/main/kotlin/pl/treksoft/kvision/core/Types.kt deleted file mode 100644 index df0eb98b..00000000 --- a/src/main/kotlin/pl/treksoft/kvision/core/Types.kt +++ /dev/null @@ -1,21 +0,0 @@ -package pl.treksoft.kvision.core - -@Suppress("EnumNaming", "EnumEntryName") -enum class UNIT(val unit: String) { - px("px"), - pt("pt"), - em("em"), - cm("cm"), - mm("mm"), - `in`("in"), - pc("pc"), - ch("ch"), - rem("rem"), - vw("vw"), - vh("vh"), - vmin("vmin"), - vmax("vmax"), - perc("%") -} - -typealias Length = Pair diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt index ff34186b..d56e7614 100644 --- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt +++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt @@ -18,7 +18,7 @@ import pl.treksoft.kvision.snabbdom.snOpt import pl.treksoft.kvision.snabbdom.snStyle @Suppress("TooManyFunctions") -open class Widget(classes: Set = setOf()) : KVObject { +open class Widget(classes: Set = setOf()) : StyledComponent() { val classes = classes.toMutableSet() val listeners = mutableListOf.() -> Unit>() @@ -47,21 +47,10 @@ open class Widget(classes: Set = setOf()) : KVObject { field = value refresh() } - var width: Length? = null - set(value) { - field = value - refresh() - } - var height: Length? = null - set(value) { - field = value - refresh() - } private var vnode: VNode? = null private var snAttrsCache: List? = null - private var snStyleCache: List? = null private var snClassCache: List? = null private var snOnCache: com.github.snabbdom.On? = null private var snHooksCache: com.github.snabbdom.Hooks? = null @@ -100,14 +89,6 @@ open class Widget(classes: Set = setOf()) : KVObject { }() } - private fun getSnStyleInternal(): List { - return snStyleCache ?: { - val s = getSnStyle() - snStyleCache = s - s - }() - } - private fun getSnClassInternal(): List { return snClassCache ?: { val s = getSnClass() @@ -132,22 +113,10 @@ open class Widget(classes: Set = setOf()) : KVObject { }() } - protected open fun getSnStyle(): List { - val snstyle = mutableListOf() - width?.let { - snstyle.add("width" to it.first.toString() + it.second.unit) - } - height?.let { - snstyle.add("height" to it.first.toString() + it.second.unit) - } - return snstyle - } - protected open fun getSnClass(): List { return classes.map { c -> c to true } + if (visible) listOf() else listOf("hidden" to true) } - protected open fun getSnAttrs(): List { val snattrs = mutableListOf() id?.let { @@ -249,9 +218,9 @@ open class Widget(classes: Set = setOf()) : KVObject { return this } - protected fun refresh(): Widget { + override fun refresh(): Widget { + super.refresh() snAttrsCache = null - snStyleCache = null snClassCache = null snOnCache = null snHooksCache = null diff --git a/src/main/kotlin/pl/treksoft/kvision/css/Css.kt b/src/main/kotlin/pl/treksoft/kvision/css/Css.kt new file mode 100644 index 00000000..14c242e8 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/css/Css.kt @@ -0,0 +1,62 @@ +package pl.treksoft.kvision.css + +import pl.treksoft.kvision.utils.Utils + +@Suppress("EnumNaming", "EnumEntryName") +enum class UNIT(val unit: String) { + px("px"), + pt("pt"), + em("em"), + cm("cm"), + mm("mm"), + `in`("in"), + pc("pc"), + ch("ch"), + rem("rem"), + vw("vw"), + vh("vh"), + vmin("vmin"), + vmax("vmax"), + perc("%") +} + +typealias CssSize = Pair + +enum class BORDERSTYLE(val borderStyle: String) { + NONE("none"), + HIDDEN("hidden"), + DOTTED("dotted"), + DASHED("dashed"), + SOLID("solid"), + DOUBLE("double"), + GROOVE("groove"), + RIDGE("ridge"), + INSET("inset"), + OUTSET("outset"), + INITIAL("initial"), + INHERIT("inherit") +} + +enum class COLOR(val color: String) { + RED("red"), + BLUE("blue"), + GREEN("green"), + BLACK("black"), + WHITE("white") +} + +class Border private constructor(private val width: CssSize? = null, private val style: BORDERSTYLE? = null, + private val color: String? = null) { + constructor(width: CssSize? = null, style: BORDERSTYLE? = null) : this(width, style, null) + constructor(width: CssSize? = null, style: BORDERSTYLE? = null, color: Int) : this(width, style, + "#" + Utils.intToHexString(color)) + + constructor(width: CssSize? = null, style: BORDERSTYLE? = null, color: COLOR) : this(width, style, color.color) + + fun asString(): String { + val w = width?.let { + it.first.toString() + it.second.unit + } + return w.orEmpty() + " " + style?.borderStyle.orEmpty() + " " + color.orEmpty() + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt index 06f9be59..9084742a 100644 --- a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt +++ b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt @@ -4,7 +4,7 @@ import com.github.snabbdom.VNode import pl.treksoft.jquery.JQuery import pl.treksoft.jquery.JQueryEventObject import pl.treksoft.kvision.core.Container -import pl.treksoft.kvision.core.UNIT +import pl.treksoft.kvision.css.UNIT import pl.treksoft.kvision.html.TAG import pl.treksoft.kvision.html.Tag import pl.treksoft.kvision.snabbdom.obj diff --git a/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt new file mode 100644 index 00000000..5a9bf5a6 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt @@ -0,0 +1,38 @@ +@file:Suppress("TooManyFunctions") +package pl.treksoft.kvision.utils + +import pl.treksoft.kvision.css.CssSize +import pl.treksoft.kvision.css.UNIT + +fun Int.px(): CssSize = Pair(this, UNIT.px) +fun Int.em(): CssSize = Pair(this, UNIT.em) +fun Int.pt(): CssSize = Pair(this, UNIT.pt) +fun Int.perc(): CssSize = Pair(this, UNIT.perc) +fun Int.rem(): CssSize = Pair(this, UNIT.rem) +fun Int.ch(): CssSize = Pair(this, UNIT.ch) +fun Int.cm(): CssSize = Pair(this, UNIT.cm) +fun Int.mm(): CssSize = Pair(this, UNIT.mm) +@Suppress("FunctionNaming") +fun Int.`in`(): CssSize = Pair(this, UNIT.`in`) +fun Int.pc(): CssSize = Pair(this, UNIT.pc) +fun Int.vh(): CssSize = Pair(this, UNIT.vh) +fun Int.vw(): CssSize = Pair(this, UNIT.vw) +fun Int.vmin(): CssSize = Pair(this, UNIT.vmin) +fun Int.vmax(): CssSize = Pair(this, UNIT.vmax) + +object Utils { + + private val hex = arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f") + + @Suppress("MagicNumber") + fun intToHexString(n: Int): String { + var result = "" + var num = n + for (i in 0 until 6) { + result = hex[num and 0xF] + result + num = num shr 4 + } + return result + } + +} -- cgit