aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/pl/treksoft/kvision/panel
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2017-10-07 02:19:47 +0200
committerRobert Jaros <rjaros@finn.pl>2017-10-07 02:19:47 +0200
commit381f872a4daab133ed53e85526281b6e29873007 (patch)
treeed0a39ef917ccdb43b8ed0ed9b616eaf4f2bf9bf /src/main/kotlin/pl/treksoft/kvision/panel
parenta61948c5b79d2fb3402e14ee69a9a8f2a18c02b4 (diff)
downloadkvision-381f872a4daab133ed53e85526281b6e29873007.tar.gz
kvision-381f872a4daab133ed53e85526281b6e29873007.tar.bz2
kvision-381f872a4daab133ed53e85526281b6e29873007.zip
New grid component (old renamed to ResponsiveGridPanel). Flex, HPanel, VPanel and DockPanel components. Cache for components attributes.
Diffstat (limited to 'src/main/kotlin/pl/treksoft/kvision/panel')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt114
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/FlexPanel.kt157
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt298
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt34
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt117
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt2
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/StackPanel.kt8
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt4
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt28
9 files changed, 584 insertions, 178 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt
new file mode 100644
index 00000000..6d86727c
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt
@@ -0,0 +1,114 @@
+package pl.treksoft.kvision.panel
+
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.Widget
+
+enum class SIDE {
+ LEFT,
+ RIGHT,
+ CENTER,
+ UP,
+ DOWN
+}
+
+open class DockPanel(classes: Set<String> = setOf()) : Container(classes = classes) {
+ protected var left: Widget? = null
+ protected var center: Widget? = null
+ protected var right: Widget? = null
+ protected var up: Widget? = null
+ protected var down: Widget? = null
+
+ protected val mainContainer = FlexPanel(direction = FLEXDIR.COLUMN, justify = FLEXJUSTIFY.SPACEBETWEEN,
+ alignItems = FLEXALIGNITEMS.STRETCH)
+ protected val subContainer = FlexPanel(justify = FLEXJUSTIFY.SPACEBETWEEN, alignItems = FLEXALIGNITEMS.CENTER)
+
+ init {
+ this.addInternal(mainContainer)
+ mainContainer.add(subContainer, 2)
+ }
+
+ @Suppress("MagicNumber")
+ open fun add(widget: Widget, position: SIDE): DockPanel {
+ when (position) {
+ SIDE.UP -> {
+ up?.let { mainContainer.remove(it) }
+ up = widget
+ mainContainer.add(widget, 1, alignSelf = FLEXALIGNITEMS.CENTER)
+ }
+ SIDE.CENTER -> {
+ center?.let { subContainer.remove(it) }
+ center = widget
+ subContainer.add(widget, 2)
+ }
+ SIDE.LEFT -> {
+ left?.let { subContainer.remove(it) }
+ left = widget
+ subContainer.add(widget, 1)
+ }
+ SIDE.RIGHT -> {
+ right?.let { subContainer.remove(it) }
+ right = widget
+ subContainer.add(widget, 3)
+ }
+ SIDE.DOWN -> {
+ down?.let { mainContainer.remove(it) }
+ down = widget
+ mainContainer.add(widget, 3, alignSelf = FLEXALIGNITEMS.CENTER)
+ }
+ }
+ return this
+ }
+
+ override fun add(child: Widget): Container {
+ return this.add(child, SIDE.CENTER)
+ }
+
+ override fun addAll(children: List<Widget>): Container {
+ children.forEach { this.add(it) }
+ return this
+ }
+
+ override fun remove(child: Widget): Container {
+ if (child == left) removeAt(SIDE.LEFT)
+ if (child == center) removeAt(SIDE.CENTER)
+ if (child == right) removeAt(SIDE.RIGHT)
+ if (child == up) removeAt(SIDE.UP)
+ if (child == down) removeAt(SIDE.DOWN)
+ return this
+ }
+
+ open fun removeAt(position: SIDE): Container {
+ when (position) {
+ SIDE.UP -> {
+ up?.let { mainContainer.remove(it) }
+ up = null
+ }
+ SIDE.CENTER -> {
+ center?.let { subContainer.remove(it) }
+ center = null
+ }
+ SIDE.LEFT -> {
+ left?.let { subContainer.remove(it) }
+ left = null
+ }
+ SIDE.RIGHT -> {
+ right?.let { subContainer.remove(it) }
+ right = null
+ }
+ SIDE.DOWN -> {
+ down?.let { mainContainer.remove(it) }
+ down = null
+ }
+ }
+ return this
+ }
+
+ override fun removeAll(): Container {
+ removeAt(SIDE.LEFT)
+ removeAt(SIDE.CENTER)
+ removeAt(SIDE.RIGHT)
+ removeAt(SIDE.UP)
+ removeAt(SIDE.DOWN)
+ return this
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/FlexPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/FlexPanel.kt
new file mode 100644
index 00000000..781f8dcd
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/FlexPanel.kt
@@ -0,0 +1,157 @@
+package pl.treksoft.kvision.panel
+
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.core.WidgetWrapper
+import pl.treksoft.kvision.snabbdom.StringPair
+
+enum class FLEXDIR(val dir: String) {
+ ROW("row"),
+ ROWREV("row-reverse"),
+ COLUMN("column"),
+ COLUMNREV("column-reverse")
+}
+
+enum class FLEXWRAP(val wrap: String) {
+ NOWRAP("nowrap"),
+ WRAP("wrap"),
+ WRAPREV("wrap-reverse")
+}
+
+enum class FLEXJUSTIFY(val justify: String) {
+ FLEXSTART("flex-start"),
+ FLEXEND("flex-end"),
+ CENTER("center"),
+ SPACEBETWEEN("space-between"),
+ SPACEAROUND("space-around"),
+ SPACEEVENLY("space-evenly")
+}
+
+enum class FLEXALIGNITEMS(val alignItems: String) {
+ FLEXSTART("flex-start"),
+ FLEXEND("flex-end"),
+ CENTER("center"),
+ BASELINE("baseline"),
+ STRETCH("stretch")
+}
+
+enum class FLEXALIGNCONTENT(val alignContent: String) {
+ FLEXSTART("flex-start"),
+ FLEXEND("flex-end"),
+ CENTER("center"),
+ SPACEBETWEEN("space-between"),
+ SPACEAROUND("space-around"),
+ STRETCH("stretch")
+}
+
+open class FlexPanel(direction: FLEXDIR? = null, wrap: FLEXWRAP? = null, justify: FLEXJUSTIFY? = null,
+ alignItems: FLEXALIGNITEMS? = null, alignContent: FLEXALIGNCONTENT? = null,
+ classes: Set<String> = setOf()) : Container(classes) {
+ var direction = direction
+ set(value) {
+ field = value
+ refresh()
+ }
+ var wrap = wrap
+ set(value) {
+ field = value
+ refresh()
+ }
+ var justify = justify
+ set(value) {
+ field = value
+ refresh()
+ }
+ var alignItems = alignItems
+ set(value) {
+ field = value
+ refresh()
+ }
+ var alignContent = alignContent
+ set(value) {
+ field = value
+ refresh()
+ }
+
+ @Suppress("LongParameterList")
+ fun add(child: Widget, order: Int? = null, grow: Int? = null, shrink: Int? = null,
+ basis: Int? = null, alignSelf: FLEXALIGNITEMS? = null, classes: Set<String> = setOf()): Container {
+ return addInternal(FlexWrapper(child, order, grow, shrink, basis, alignSelf, classes))
+ }
+
+ override fun add(child: Widget): Container {
+ return add(child, null)
+ }
+
+ override fun addAll(children: List<Widget>): Container {
+ children.forEach { add(it, null) }
+ return this
+ }
+
+ override fun remove(child: Widget): Container {
+ children.find { (it as FlexWrapper).delegate == child }?.let {
+ super.remove(it)
+ it.dispose()
+ }
+ return this
+ }
+
+ override fun removeAll(): Container {
+ children.map {
+ it.clearParent()
+ it.dispose()
+ }
+ children.clear()
+ refresh()
+ return this
+ }
+
+ override fun getSnStyle(): List<StringPair> {
+ val snstyle = super.getSnStyle().toMutableList()
+ snstyle.add("display" to "flex")
+ direction?.let {
+ snstyle.add("flex-direction" to it.dir)
+ }
+ wrap?.let {
+ snstyle.add("flex-wrap" to it.wrap)
+ }
+ justify?.let {
+ snstyle.add("justify-content" to it.justify)
+ }
+ alignItems?.let {
+ snstyle.add("align-items" to it.alignItems)
+ }
+ alignContent?.let {
+ snstyle.add("align-content" to it.alignContent)
+ }
+ println("abc")
+ return snstyle
+ }
+}
+
+class FlexWrapper(delegate: Widget, private val order: Int? = null, private val grow: Int? = null,
+ private val shrink: Int? = null, private val basis: Int? = null,
+ private val alignSelf: FLEXALIGNITEMS? = null,
+ classes: Set<String> = setOf()) : WidgetWrapper(delegate, classes) {
+
+ override fun getSnStyle(): List<StringPair> {
+ val snstyle = super.getSnStyle().toMutableList()
+ order?.let {
+ snstyle.add("order" to "$it")
+ }
+ grow?.let {
+ snstyle.add("flex-grow" to "$it")
+ }
+ shrink?.let {
+ snstyle.add("flex-shrink" to "$it")
+ }
+ basis?.let {
+ snstyle.add("flex-basis" to "$it%")
+ }
+ alignSelf?.let {
+ snstyle.add("align-self" to it.alignItems)
+ }
+ return snstyle
+ }
+
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt
index f7adfe8f..44ba509f 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt
@@ -1,152 +1,226 @@
package pl.treksoft.kvision.panel
-import com.github.snabbdom.VNode
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.core.WidgetWrapper
-import pl.treksoft.kvision.html.ALIGN
-import pl.treksoft.kvision.html.TAG
-import pl.treksoft.kvision.html.Tag
+import pl.treksoft.kvision.snabbdom.StringPair
-enum class GRIDTYPE {
- BOOTSTRAP,
- DSG
+enum class GRIDJUSTIFY(val justify: String) {
+ START("start"),
+ END("end"),
+ CENTER("center"),
+ STRETCH("stretch")
}
-enum class GRIDSIZE(val size: String) {
- XS("xs"),
- SM("sm"),
- MD("md"),
- LG("lg")
+enum class GRIDALIGN(val align: String) {
+ START("start"),
+ END("end"),
+ CENTER("center"),
+ STRETCH("stretch")
}
-const val FULLPERCENT = 100
-const val MAX_COLUMNS = 12
+enum class GRIDJUSTIFYCONTENT(val justifyContent: String) {
+ START("start"),
+ END("end"),
+ CENTER("center"),
+ STRETCH("stretch"),
+ SPACEAROUND("space-around"),
+ SPACEBETWEEN("space-between"),
+ SPACEEVENLY("space-evenly")
+}
-internal data class WidgetParam(val widget: Widget, val size: Int, val offset: Int)
+enum class GRIDALIGNCONTENT(val alignContent: String) {
+ START("start"),
+ END("end"),
+ CENTER("center"),
+ STRETCH("stretch"),
+ SPACEAROUND("space-around"),
+ SPACEBETWEEN("space-between"),
+ SPACEEVENLY("space-evenly")
+}
-open class GridPanel(private val gridtype: GRIDTYPE = GRIDTYPE.BOOTSTRAP, private val gridsize: GRIDSIZE = GRIDSIZE.MD,
- protected var rows: Int = 0, protected var cols: Int = 0, align: ALIGN = ALIGN.NONE,
- classes: Set<String> = setOf()) : Container(classes) {
- private var align = align
+enum class GRIDFLOW(val flow: String) {
+ ROW("row"),
+ COLUMN("column"),
+ ROWDENSE("row dense"),
+ COLUMNDENSE("column dense")
+}
+
+open class GridPanel(autoColumns: String? = null, autoRows: String? = null, autoFlow: GRIDFLOW? = null,
+ templateColumns: String? = null, templateRows: String? = null, templateAreas: List<String>? = null,
+ columnGap: Int? = null, rowGap: Int? = null, justifyItems: GRIDJUSTIFY? = null,
+ alignItems: GRIDALIGN? = null, justifyContent: GRIDJUSTIFYCONTENT? = null,
+ alignContent: GRIDALIGNCONTENT? = null, classes: Set<String> = setOf()) : Container(classes) {
+ var autoColumns = autoColumns
+ set(value) {
+ field = value
+ refresh()
+ }
+ var autoRows = autoRows
+ set(value) {
+ field = value
+ refresh()
+ }
+ var autoFlow = autoFlow
+ set(value) {
+ field = value
+ refresh()
+ }
+ var templateColumns = templateColumns
+ set(value) {
+ field = value
+ refresh()
+ }
+ var templateRows = templateRows
+ set(value) {
+ field = value
+ refresh()
+ }
+ var templateAreas = templateAreas
+ set(value) {
+ field = value
+ refresh()
+ }
+ var columnGap = columnGap
+ set(value) {
+ field = value
+ refresh()
+ }
+ var rowGap = rowGap
+ set(value) {
+ field = value
+ refresh()
+ }
+ var justifyItems = justifyItems
+ set(value) {
+ field = value
+ refresh()
+ }
+ var alignItems = alignItems
+ set(value) {
+ field = value
+ refresh()
+ }
+ var justifyContent = justifyContent
+ set(value) {
+ field = value
+ refresh()
+ }
+ var alignContent = alignContent
set(value) {
field = value
refresh()
}
- internal val map = mutableMapOf<Int, MutableMap<Int, WidgetParam>>()
- private var auto: Boolean = true
-
- open fun add(child: Widget, row: Int, col: Int, size: Int = 0, offset: Int = 0): Container {
- val cRow = if (row < 0) 0 else row
- val cCol = if (col < 0) 0 else col
- if (row > rows - 1) rows = cRow + 1
- if (col > cols - 1) cols = cCol + 1
- map.getOrPut(cRow, { mutableMapOf() }).put(cCol, WidgetParam(child, size, offset))
- if (size > 0 || offset > 0) auto = false
- return this
+ @Suppress("LongParameterList")
+ fun add(child: Widget, columnStart: Int? = null, rowStart: Int? = null,
+ columnEnd: String? = null, rowEnd: String? = null, area: String? = null, justifySelf: GRIDJUSTIFY? = null,
+ alignSelf: GRIDALIGN? = null, classes: Set<String> = setOf()): Container {
+ return addInternal(GridWrapper(child, columnStart, rowStart, columnEnd, rowEnd, area, justifySelf,
+ alignSelf, classes))
}
override fun add(child: Widget): Container {
- return this.add(child, 0, this.cols)
+ return add(child, null, null)
}
override fun addAll(children: List<Widget>): Container {
- children.forEach { this.add(it) }
+ children.forEach { add(it, null, null) }
return this
}
override fun remove(child: Widget): Container {
- for (i in 0 until rows) {
- val row = map[i]
- if (row != null) {
- for (j in 0 until cols) {
- val wp = row[j]
- if (wp != null) {
- if (wp.widget == child) row.remove(j)
- }
- }
- }
+ children.find { (it as GridWrapper).delegate == child }?.let {
+ super.remove(it)
+ it.dispose()
}
return this
}
- open fun removeAt(row: Int, col: Int): Container {
- map[row]?.remove(col)
+ override fun removeAll(): Container {
+ children.map {
+ it.clearParent()
+ it.dispose()
+ }
+ children.clear()
+ refresh()
return this
}
- override fun removeAt(index: Int): Container {
- return this.removeAt(0, index)
- }
-
- override fun childrenVNodes(): Array<VNode> {
- return if (gridtype == GRIDTYPE.BOOTSTRAP) {
- childrenVNodesBts()
- } else {
- childrenVNodesDsg()
+ @Suppress("ComplexMethod")
+ override fun getSnStyle(): List<StringPair> {
+ val snstyle = super.getSnStyle().toMutableList()
+ snstyle.add("display" to "grid")
+ autoColumns?.let {
+ snstyle.add("grid-auto-columns" to it)
+ }
+ autoRows?.let {
+ snstyle.add("grid-auto-rows" to it)
+ }
+ autoFlow?.let {
+ snstyle.add("grid-auto-flow" to it.flow)
+ }
+ templateColumns?.let {
+ snstyle.add("grid-template-columns" to it)
}
+ templateRows?.let {
+ snstyle.add("grid-template-rows" to it)
+ }
+ templateAreas?.let {
+ snstyle.add("grid-template-areas" to it.joinToString("\n"))
+ }
+ columnGap?.let {
+ snstyle.add("grid-column-gap" to "${it}px")
+ }
+ rowGap?.let {
+ snstyle.add("grid-row-gap" to "${it}px")
+ }
+ justifyItems?.let {
+ snstyle.add("justify-items" to it.justify)
+ }
+ alignItems?.let {
+ snstyle.add("align-items" to it.align)
+ }
+ justifyContent?.let {
+ snstyle.add("justify-content" to it.justifyContent)
+ }
+ alignContent?.let {
+ snstyle.add("align-content" to it.alignContent)
+ }
+ return snstyle
}
+}
- @Suppress("NestedBlockDepth", "LoopToCallChain")
- protected open fun childrenVNodesDsg(): Array<VNode> {
- val ret = mutableListOf<VNode>()
- val num = FULLPERCENT / cols
- for (i in 0 until rows) {
- val rowContainer = Container(setOf("dsgrow"))
- val row = map[i]
- if (row != null) {
- for (j in 0 until cols) {
- val wp = row[j]
- val widget = wp?.widget?.let { WidgetWrapper(it, setOf("dsgcol")) } ?:
- Tag(TAG.DIV, classes = setOf("dsgcol"))
- widget.widthPercent = num
- if (align != ALIGN.NONE) {
- widget.addCssClass(align.className)
- }
- rowContainer.add(widget)
- }
- }
- ret.add(rowContainer.render())
- }
- return ret.toTypedArray()
- }
+class GridWrapper(delegate: Widget, private val columnStart: Int? = null, private val rowStart: Int? = null,
+ private val columnEnd: String? = null, private val rowEnd: String? = null,
+ private val area: String? = null, private val justifySelf: GRIDJUSTIFY? = null,
+ private val alignSelf: GRIDALIGN? = null,
+ classes: Set<String> = setOf()) : WidgetWrapper(delegate, classes) {
- @Suppress("NestedBlockDepth", "LoopToCallChain")
- private fun childrenVNodesBts(): Array<VNode> {
- val ret = mutableListOf<VNode>()
- val num = MAX_COLUMNS / cols
- for (i in 0 until rows) {
- val rowContainer = Container(setOf("row"))
- val row = map[i]
- if (row != null) {
- for (j in 0 until cols) {
- val wp = row[j]
- if (auto) {
- val widget = wp?.widget?.let {
- WidgetWrapper(it, setOf("col-" + gridsize.size + "-" + num))
- } ?: Tag(TAG.DIV, classes = setOf("col-" + gridsize.size + "-" + num))
- if (align != ALIGN.NONE) {
- widget.addCssClass(align.className)
- }
- rowContainer.add(widget)
- } else {
- if (wp != null) {
- val s = if (wp.size > 0) wp.size else num
- val widget = WidgetWrapper(wp.widget, setOf("col-" + gridsize.size + "-" + s))
- if (wp.offset > 0) {
- widget.addCssClass("col-" + gridsize.size + "-offset-" + wp.offset)
- }
- if (align != ALIGN.NONE) {
- widget.addCssClass(align.className)
- }
- rowContainer.add(widget)
- }
- }
- }
- }
- ret.add(rowContainer.render())
- }
- return ret.toTypedArray()
+ override fun getSnStyle(): List<StringPair> {
+ val snstyle = super.getSnStyle().toMutableList()
+ columnStart?.let {
+ snstyle.add("grid-column-start" to "$it")
+ }
+ rowStart?.let {
+ snstyle.add("grid-row-start" to "$it")
+ }
+ columnEnd?.let {
+ snstyle.add("grid-column-end" to it)
+ }
+ rowEnd?.let {
+ snstyle.add("grid-row-end" to it)
+ }
+ area?.let {
+ snstyle.add("grid-area" to it)
+ }
+ justifySelf?.let {
+ snstyle.add("justify-self" to it.justify)
+ }
+ alignSelf?.let {
+ snstyle.add("align-self" to it.align)
+ }
+ return snstyle
}
+
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt
index 3d1db0e7..c9317374 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt
@@ -1,33 +1,5 @@
package pl.treksoft.kvision.panel
-import com.github.snabbdom.VNode
-import pl.treksoft.kvision.core.Container
-import pl.treksoft.kvision.core.Widget
-import pl.treksoft.kvision.core.WidgetWrapper
-import pl.treksoft.kvision.html.ALIGN
-import pl.treksoft.kvision.html.TAG
-import pl.treksoft.kvision.html.Tag
-
-open class HPanel(align: ALIGN = ALIGN.NONE, classes: Set<String> = setOf()) : GridPanel(GRIDTYPE.DSG, align = align,
- classes = classes) {
-
- override fun add(child: Widget, row: Int, col: Int, size: Int, offset: Int): Container {
- return super.add(child, 0, col, size, offset)
- }
-
- override fun childrenVNodesDsg(): Array<VNode> {
- val ret = mutableListOf<VNode>()
- val rowContainer = Container(setOf("dsgrow"))
- val row = map[0]
- if (row != null) {
- for (j in 0 until cols) {
- val wp = row[j]
- val widget = wp?.widget?.let { WidgetWrapper(it, setOf("dsgcolf")) } ?:
- Tag(TAG.DIV, classes = setOf("dsgcolf"))
- rowContainer.add(widget)
- }
- }
- ret.add(rowContainer.render())
- return ret.toTypedArray()
- }
-}
+open class HPanel(justify: FLEXJUSTIFY? = null, alignItems: FLEXALIGNITEMS? = null,
+ classes: Set<String> = setOf()) : FlexPanel(null,
+ null, justify, alignItems, null, classes)
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt
new file mode 100644
index 00000000..af4dd53f
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt
@@ -0,0 +1,117 @@
+package pl.treksoft.kvision.panel
+
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.core.WidgetWrapper
+import pl.treksoft.kvision.html.ALIGN
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+enum class GRIDSIZE(val size: String) {
+ XS("xs"),
+ SM("sm"),
+ MD("md"),
+ LG("lg")
+}
+
+const val MAX_COLUMNS = 12
+
+internal data class WidgetParam(val widget: Widget, val size: Int, val offset: Int)
+
+open class ResponsiveGridPanel(private val gridsize: GRIDSIZE = GRIDSIZE.MD,
+ private var rows: Int = 0, private var cols: Int = 0, align: ALIGN = ALIGN.NONE,
+ classes: Set<String> = setOf()) : Container(classes) {
+ protected var align = align
+ set(value) {
+ field = value
+ refresh()
+ }
+
+ internal val map = mutableMapOf<Int, MutableMap<Int, WidgetParam>>()
+ private var auto: Boolean = true
+
+ open fun add(child: Widget, row: Int, col: Int, size: Int = 0, offset: Int = 0): Container {
+ val cRow = if (row < 0) 0 else row
+ val cCol = if (col < 0) 0 else col
+ if (row > rows - 1) rows = cRow + 1
+ if (col > cols - 1) cols = cCol + 1
+ map.getOrPut(cRow, { mutableMapOf() }).put(cCol, WidgetParam(child, size, offset))
+ if (size > 0 || offset > 0) auto = false
+ refreshRowContainers()
+ return this
+ }
+
+ override fun add(child: Widget): Container {
+ return this.add(child, 0, this.cols)
+ }
+
+ override fun addAll(children: List<Widget>): Container {
+ children.forEach { this.add(it) }
+ return this
+ }
+
+ @Suppress("NestedBlockDepth")
+ override fun remove(child: Widget): Container {
+ for (i in 0 until rows) {
+ val row = map[i]
+ if (row != null) {
+ for (j in 0 until cols) {
+ val wp = row[j]
+ if (wp != null) {
+ if (wp.widget == child) row.remove(j)
+ }
+ }
+ }
+ }
+ refreshRowContainers()
+ return this
+ }
+
+ open fun removeAt(row: Int, col: Int): Container {
+ map[row]?.remove(col)
+ refreshRowContainers()
+ return this
+ }
+
+ @Suppress("ComplexMethod", "NestedBlockDepth")
+ protected open fun refreshRowContainers() {
+ clearRowContainers()
+ val num = MAX_COLUMNS / cols
+ for (i in 0 until rows) {
+ val rowContainer = Container(setOf("row"))
+ val row = map[i]
+ if (row != null) {
+ for (j in 0 until cols) {
+ val wp = row[j]
+ if (auto) {
+ val widget = wp?.widget?.let {
+ WidgetWrapper(it, setOf("col-" + gridsize.size + "-" + num))
+ } ?: Tag(TAG.DIV, classes = setOf("col-" + gridsize.size + "-" + num))
+ if (align != ALIGN.NONE) {
+ widget.addCssClass(align.className)
+ }
+ rowContainer.add(widget)
+ } else {
+ if (wp != null) {
+ val s = if (wp.size > 0) wp.size else num
+ val widget = WidgetWrapper(wp.widget, setOf("col-" + gridsize.size + "-" + s))
+ if (wp.offset > 0) {
+ widget.addCssClass("col-" + gridsize.size + "-offset-" + wp.offset)
+ }
+ if (align != ALIGN.NONE) {
+ widget.addCssClass(align.className)
+ }
+ rowContainer.add(widget)
+ }
+ }
+ }
+ }
+ addInternal(rowContainer)
+ }
+ }
+
+ private fun clearRowContainers() {
+ children.forEach { it.dispose() }
+ removeAll()
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
index 57519833..569a5b85 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
@@ -48,7 +48,7 @@ open class SplitPanel(private val direction: DIRECTION = DIRECTION.VERTICAL,
override fun childrenVNodes(): Array<VNode> {
return if (children.size == 2) {
- arrayOf(children[0].render(), splitter.render(), children[1].render())
+ arrayOf(children[0].renderVNode(), splitter.renderVNode(), children[1].renderVNode())
} else {
arrayOf()
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/StackPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/StackPanel.kt
index 372098b8..c5162c0a 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/StackPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/StackPanel.kt
@@ -14,7 +14,7 @@ open class StackPanel(private val activateLast: Boolean = true,
override fun childrenVNodes(): Array<VNode> {
return if (activeIndex >= 0 && activeIndex < children.size) {
- arrayOf(children[activeIndex].render())
+ arrayOf(children[activeIndex].renderVNode())
} else {
arrayOf()
}
@@ -40,12 +40,6 @@ open class StackPanel(private val activateLast: Boolean = true,
return this
}
- override fun removeAt(index: Int): Container {
- super.removeAt(index)
- if (activeIndex > children.size - 1) activeIndex = children.size - 1
- return this
- }
-
override fun removeAll(): Container {
super.removeAll()
if (activeIndex > children.size - 1) activeIndex = children.size - 1
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
index 0022023b..817ecaa0 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
@@ -47,8 +47,8 @@ open class TabPanel : Container(setOf()) {
}
open fun removeTab(index: Int): TabPanel {
- nav.removeAt(index)
- content.removeAt(index)
+ nav.remove(nav.children[index])
+ content.remove(content.children[index])
activeIndex = content.activeIndex
return this
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt
index f81c4a7e..42e33637 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt
@@ -1,27 +1,5 @@
package pl.treksoft.kvision.panel
-import pl.treksoft.kvision.core.Container
-import pl.treksoft.kvision.core.Widget
-import pl.treksoft.kvision.html.ALIGN
-
-open class VPanel(align: ALIGN = ALIGN.NONE, classes: Set<String> = setOf()) : GridPanel(GRIDTYPE.BOOTSTRAP,
- align = align, classes = classes) {
-
- override fun add(child: Widget, row: Int, col: Int, size: Int, offset: Int): Container {
- return super.add(child, row, 0, size, offset)
- }
-
- override fun add(child: Widget): Container {
- return this.add(child, this.rows, 0)
- }
-
- override fun addAll(children: List<Widget>): Container {
- children.forEach { this.add(it) }
- return this
- }
-
- override fun removeAt(index: Int): Container {
- return this.removeAt(index, 0)
- }
-
-}
+open class VPanel(justify: FLEXJUSTIFY? = null, alignItems: FLEXALIGNITEMS? = null,
+ classes: Set<String> = setOf()) : FlexPanel(FLEXDIR.COLUMN,
+ null, justify, alignItems, null, classes)