diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/assets/css/style.css | 33 | ||||
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/Showcase.kt | 35 | ||||
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/core/Widget.kt | 7 | ||||
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/panel/GridPanel.kt | 149 | ||||
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/panel/HPanel.kt | 31 | ||||
-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.kt | 27 | ||||
-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") |