aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/assets/css/style.css33
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/Showcase.kt35
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Widget.kt7
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt149
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt31
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt (renamed from src/main/kotlin/pl/treksoft/kvision/tabs/Tabs.kt)9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt27
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt (renamed from src/test/kotlin/test/pl/treksoft/kvision/tabs/TabsSpec.kt)12
8 files changed, 289 insertions, 14 deletions
diff --git a/src/main/assets/css/style.css b/src/main/assets/css/style.css
index 61696cb2..568f0edd 100644
--- a/src/main/assets/css/style.css
+++ b/src/main/assets/css/style.css
@@ -52,3 +52,36 @@
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAICAQAAADdTl4aAAAAIElEQVQoz2MwrTD9TxFsZ7jPcV+IIsjFQAUw6hFqegQA+xzRHT2p7pEAAAAASUVORK5CYII=') center center no-repeat #cecece;
cursor: row-resize;
}
+
+/* Dead Simple Grid (c) 2015 Vladimir Agafonkin */
+
+.dsgrow .dsgrow { margin: 0 -1.5em; }
+.dsgcol { padding: 0 1.5em; }
+.dsgcolf { padding: 0 1.5em; }
+
+.dsgrow:after {
+ content: "";
+ clear: both;
+ display: table;
+}
+
+@media only screen {
+
+.dsgcol {
+ float: left;
+ width: 100%;
+ box-sizing: border-box;
+}
+.dsgcol::before {
+ content: "\200B";
+}
+
+.dsgcolf {
+ float: left;
+ box-sizing: border-box;
+}
+.dsgcolf::before {
+ content: "\200B";
+}
+
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
index 283a9236..221ac609 100644
--- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
@@ -7,14 +7,18 @@ import pl.treksoft.kvision.core.Root
import pl.treksoft.kvision.dropdown.DD.*
import pl.treksoft.kvision.dropdown.DropDown
import pl.treksoft.kvision.html.*
+import pl.treksoft.kvision.html.TAG.DIV
import pl.treksoft.kvision.html.TAG.H1
import pl.treksoft.kvision.modal.Alert
import pl.treksoft.kvision.modal.Confirm
import pl.treksoft.kvision.modal.Modal
import pl.treksoft.kvision.panel.DIRECTION
+import pl.treksoft.kvision.panel.GridPanel
+import pl.treksoft.kvision.panel.HPanel
import pl.treksoft.kvision.panel.SplitPanel
+import pl.treksoft.kvision.panel.TabPanel
+import pl.treksoft.kvision.panel.VPanel
import pl.treksoft.kvision.routing.routing
-import pl.treksoft.kvision.tabs.Tabs
class Showcase : ApplicationBase() {
@@ -62,11 +66,11 @@ class Showcase : ApplicationBase() {
dd3.add(Image(Img("kotlin.png")))
root.add(dd3)
- val tabs2 = Tabs()
+ val tabs2 = TabPanel()
tabs2.addTab("XXX", Label("XXX"), "fa-flag")
tabs2.addTab("YYY", Label("YYY"), "fa-flag")
- val tabs = Tabs()
+ val tabs = TabPanel()
tabs.addTab("Test zakładki", Label("test zakładki"), "fa-flag")
tabs.addTab("Test zakładki2", Label("test zakładki2"))
tabs.addTab("Test zakładki3", tabs2, "fa-bars")
@@ -110,6 +114,31 @@ class Showcase : ApplicationBase() {
val img = Image(Img("kotlin.png"), "Image", true, IMAGESHAPE.ROUNDED)
root.add(img)
+ val grid = GridPanel(align = ALIGN.RIGHT)
+ grid.add(Tag(DIV, "0,0"), 0, 0)
+ grid.add(Tag(DIV, "1,1"), 1, 1)
+ grid.add(Tag(DIV, "2,2"), 2, 2)
+ grid.add(Tag(DIV, "3,3"), 3, 3)
+ root.add(grid)
+
+ val grid2 = GridPanel(align = ALIGN.CENTER)
+ grid2.add(Tag(DIV, "0,0"), 0, 0, 8)
+ grid2.add(Tag(DIV, "0,1"), 0, 1, 4)
+ grid2.add(Tag(DIV, "1,1"), 1, 1, 8, 4)
+ root.add(grid2)
+
+ val hPanel = HPanel(align = ALIGN.RIGHT)
+ hPanel.add(Label("1"))
+ hPanel.add(Label("2"))
+ hPanel.add(Label("3"))
+ root.add(hPanel)
+
+ val vPanel = VPanel(align = ALIGN.CENTER)
+ vPanel.add(Label("1"))
+ vPanel.add(Label("2"))
+ vPanel.add(Label("3"))
+ root.add(vPanel)
+
val modal = Modal("Test okienka")
modal.add(Tag(TAG.H4, "ABC"))
modal.add(Image(Img("kotlin.png")))
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
index 846dde1b..c934aff2 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
@@ -52,6 +52,11 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
field = value
refresh()
}
+ var widthPercent: Int? = null
+ set(value) {
+ field = value
+ refresh()
+ }
var height: Int? = null
set(value) {
field = value
@@ -86,6 +91,8 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
val snstyle = mutableListOf<StringPair>()
if (width != null) {
snstyle.add("width" to width.toString() + "px")
+ } else if (widthPercent != null) {
+ snstyle.add("width" to widthPercent.toString() + "%")
}
if (height != null) {
snstyle.add("height" to height.toString() + "px")
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt
new file mode 100644
index 00000000..243d1442
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt
@@ -0,0 +1,149 @@
+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.html.ALIGN
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+enum class GRIDTYPE {
+ BOOTSTRAP,
+ DSG
+}
+
+enum class GRIDSIZE(val size: String) {
+ XS("xs"),
+ SM("sm"),
+ MD("md"),
+ LG("lg")
+}
+
+const val FULLPERCENT = 100
+const val MAX_COLUMNS = 12
+
+internal data class WidgetParam(val widget: Widget, val size: Int, val offset: Int)
+
+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) {
+ 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
+ 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
+ }
+
+ 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)
+ }
+ }
+ }
+ }
+ return this
+ }
+
+ open fun removeAt(row: Int, col: Int): Container {
+ map[row]?.remove(col)
+ 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("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?.addCssClass("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()
+ }
+
+ @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?.addCssClass("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
+ wp.widget.addCssClass("col-" + gridsize.size + "-" + s)
+ if (wp.offset > 0) {
+ wp.widget.addCssClass("col-" + gridsize.size + "-offset-" + wp.offset)
+ }
+ if (align != ALIGN.NONE) {
+ wp.widget.addCssClass(align.className)
+ }
+ rowContainer.add(wp.widget)
+ }
+ }
+ }
+ }
+ ret.add(rowContainer.render())
+ }
+ return ret.toTypedArray()
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt
new file mode 100644
index 00000000..685cfc87
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt
@@ -0,0 +1,31 @@
+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.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?.addCssClass("dsgcolf") ?: Tag(TAG.DIV, classes = setOf("dsgcolf"))
+ rowContainer.add(widget)
+ }
+ }
+ ret.add(rowContainer.render())
+ return ret.toTypedArray()
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/tabs/Tabs.kt b/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
index 773f341a..0022023b 100644
--- a/src/main/kotlin/pl/treksoft/kvision/tabs/Tabs.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
@@ -1,4 +1,4 @@
-package pl.treksoft.kvision.tabs
+package pl.treksoft.kvision.panel
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.ResString
@@ -6,9 +6,8 @@ import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.html.Link
import pl.treksoft.kvision.html.TAG
import pl.treksoft.kvision.html.Tag
-import pl.treksoft.kvision.panel.StackPanel
-open class Tabs : Container(setOf()) {
+open class TabPanel : Container(setOf()) {
private var nav = Tag(TAG.UL, classes = setOf("nav", "nav-tabs"))
private var content = StackPanel(false)
var activeIndex
@@ -27,7 +26,7 @@ open class Tabs : Container(setOf()) {
}
open fun addTab(title: String, panel: Widget, icon: String? = null,
- image: ResString? = null): Tabs {
+ image: ResString? = null): TabPanel {
val tag = Tag(TAG.LI)
tag.role = "presentation"
tag.add(Link(title, "#", icon, image))
@@ -47,7 +46,7 @@ open class Tabs : Container(setOf()) {
return this
}
- open fun removeTab(index: Int): Tabs {
+ open fun removeTab(index: Int): TabPanel {
nav.removeAt(index)
content.removeAt(index)
activeIndex = content.activeIndex
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt
new file mode 100644
index 00000000..f81c4a7e
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/VPanel.kt
@@ -0,0 +1,27 @@
+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)
+ }
+
+}
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/tabs/TabsSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt
index 60e2ef60..4a1f9652 100644
--- a/src/test/kotlin/test/pl/treksoft/kvision/tabs/TabsSpec.kt
+++ b/src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt
@@ -1,20 +1,20 @@
-package test.pl.treksoft.kvision.tabs
+package test.pl.treksoft.kvision.panel
import pl.treksoft.kvision.basic.Label
import pl.treksoft.kvision.core.Root
-import pl.treksoft.kvision.tabs.Tabs
+import pl.treksoft.kvision.panel.TabPanel
import test.pl.treksoft.kvision.DomSpec
import kotlin.browser.document
import kotlin.test.Test
import kotlin.test.assertEquals
-class TabsSpec : DomSpec {
+class TabPanelSpec : DomSpec {
@Test
fun render() {
run {
val root = Root("test")
- val tabs = Tabs()
+ val tabs = TabPanel()
root.add(tabs)
val label1 = Label("abc")
val label2 = Label("def")
@@ -29,7 +29,7 @@ class TabsSpec : DomSpec {
fun setActiveIndex() {
run {
val root = Root("test")
- val tabs = Tabs()
+ val tabs = TabPanel()
root.add(tabs)
val label1 = Label("abc")
val label2 = Label("def")
@@ -45,7 +45,7 @@ class TabsSpec : DomSpec {
fun removeTab() {
run {
val root = Root("test")
- val tabs = Tabs()
+ val tabs = TabPanel()
root.add(tabs)
val label1 = Label("abc")
val label2 = Label("def")