diff options
Diffstat (limited to 'src/main/kotlin/pl/treksoft/kvision/panel')
4 files changed, 262 insertions, 0 deletions
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/panel/TabPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt new file mode 100644 index 00000000..0022023b --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt @@ -0,0 +1,55 @@ +package pl.treksoft.kvision.panel + +import pl.treksoft.kvision.core.Container +import pl.treksoft.kvision.core.ResString +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.html.Link +import pl.treksoft.kvision.html.TAG +import pl.treksoft.kvision.html.Tag + +open class TabPanel : Container(setOf()) { + private var nav = Tag(TAG.UL, classes = setOf("nav", "nav-tabs")) + private var content = StackPanel(false) + var activeIndex + get() = content.activeIndex + set(value) { + content.activeIndex = value + nav.children.forEach { it.removeCssClass("active") } + if (content.activeIndex >= 0 && content.activeIndex <= nav.children.size) { + nav.children[content.activeIndex].addCssClass("active") + } + } + + init { + this.add(nav) + this.add(content) + } + + open fun addTab(title: String, panel: Widget, icon: String? = null, + image: ResString? = null): TabPanel { + val tag = Tag(TAG.LI) + tag.role = "presentation" + tag.add(Link(title, "#", icon, image)) + val index = nav.children.size + tag.setEventListener { + click = { e -> + activeIndex = index + e.preventDefault() + } + } + nav.add(tag) + if (nav.children.size == 1) { + tag.addCssClass("active") + activeIndex = 0 + } + content.add(panel) + return this + } + + open fun removeTab(index: Int): TabPanel { + nav.removeAt(index) + content.removeAt(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 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) + } + +} |