diff options
Diffstat (limited to 'src/main/kotlin/pl/treksoft')
4 files changed, 157 insertions, 31 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Css.kt b/src/main/kotlin/pl/treksoft/kvision/core/Css.kt index 8aeee71a..096cb26a 100644 --- a/src/main/kotlin/pl/treksoft/kvision/core/Css.kt +++ b/src/main/kotlin/pl/treksoft/kvision/core/Css.kt @@ -257,6 +257,17 @@ enum class BGCLIP(internal val clip: String) { } /** + * Definitions of CSS position options. + */ +enum class POSITION(internal val position: String) { + STATIC("static"), + RELATIVE("relative"), + FIXED("fixed"), + ABSOLUTE("absolute"), + STICKY("sticky") +} + +/** * Type-safe definition of CSS border. */ class Border private constructor( diff --git a/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt b/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt index d130ec0b..0215d967 100644 --- a/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt +++ b/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt @@ -55,6 +55,30 @@ abstract class StyledComponent : Component { */ var maxHeight: CssSize? by refreshOnUpdate() /** + * CSS position of the current component. + */ + var position: POSITION? by refreshOnUpdate() + /** + * Top edge of the current component. + */ + var top: CssSize? by refreshOnUpdate() + /** + * Left edge of the current component. + */ + var left: CssSize? by refreshOnUpdate() + /** + * Right edge of the current component. + */ + var right: CssSize? by refreshOnUpdate() + /** + * Bottom edge of the current component. + */ + var bottom: CssSize? by refreshOnUpdate() + /** + * Z-index of the current component. + */ + var zIndex: Int? by refreshOnUpdate() + /** * Border of the current component. */ var border: Border? by refreshOnUpdate() @@ -155,7 +179,6 @@ abstract class StyledComponent : Component { */ var background: Background? by refreshOnUpdate() - private var snStyleCache: List<StringPair>? = null /** @@ -202,6 +225,24 @@ abstract class StyledComponent : Component { maxHeight?.let { snstyle.add("max-height" to it.asString()) } + position?.let { + snstyle.add("position" to it.position) + } + top?.let { + snstyle.add("top" to it.asString()) + } + left?.let { + snstyle.add("left" to it.asString()) + } + right?.let { + snstyle.add("right" to it.asString()) + } + bottom?.let { + snstyle.add("bottom" to it.asString()) + } + zIndex?.let { + snstyle.add("z-index" to it.toString()) + } border?.let { snstyle.add("border" to it.asString()) } diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt index 8e66d130..bfa1fc40 100644 --- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt +++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt @@ -25,6 +25,7 @@ import com.github.snabbdom.VNode import com.github.snabbdom.VNodeData import com.github.snabbdom.h import org.w3c.dom.CustomEventInit +import org.w3c.dom.DragEvent import org.w3c.dom.Node import pl.treksoft.jquery.JQuery import pl.treksoft.jquery.jQuery @@ -74,6 +75,10 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() { * A role attribute of generated HTML element. */ var role: String? by refreshOnUpdate() + /** + * Determines if the current widget is draggable. + */ + var draggable: Boolean? by refreshOnUpdate() internal var surroundingSpan by refreshOnUpdate(false) @@ -210,6 +215,9 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() { role?.let { snattrs.add("role" to it) } + if (draggable == true) { + snattrs.add("draggable" to "true") + } return snattrs } @@ -476,6 +484,72 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() { } /** + * Sets D&D data for the current widget. It also makes it draggable. + * @param format D&D data format + * @param data D&D data transferred to a drop target + */ + open fun setDragDropData(format: String, data: String) { + draggable = true + setEventListener<Widget> { + dragstart = { e -> + e.dataTransfer?.setData(format, data) + } + } + } + + /** + * Clears D&D data for the current widget. It also makes it not draggable. + */ + open fun clearDragDropData() { + draggable = false + setEventListener<Widget> { + dragstart = { + } + } + } + + /** + * Sets the current widget as a D&D drop target with helper callback accepting String data. + * @param format accepted D&D data format + * @param callback a callback function accepting String data called after any drop event + */ + open fun setDropTargetData(format: String, callback: (String?) -> Unit) { + setDropTarget(format) { e -> + callback(e.dataTransfer?.getData(format)) + } + } + + /** + * Sets the current widget as a D&D drop target. + * @param format accepted D&D data format + * @param callback a callback function accepting event object called after any drop event + */ + open fun setDropTarget(format: String, callback: (DragEvent) -> Unit) { + setDropTarget(setOf(format), callback) + } + + /** + * Sets the current widget as a D&D drop target. + * @param formats a set of accepted D&D data formats + * @param callback a callback function accepting event object called after any drop event + */ + open fun setDropTarget(formats: Set<String>? = null, callback: (DragEvent) -> Unit) { + setEventListener<Widget> { + dragover = { e -> + val types = e.dataTransfer?.types?.toSet() ?: setOf() + if (formats == null || formats.intersect(types).isNotEmpty()) { + e.preventDefault() + } + } + drop = { e -> + e.preventDefault() + e.stopPropagation() + callback(e) + } + } + } + + /** * @suppress * Internal function */ diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt index 4573b6a4..b605cf56 100644 --- a/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt +++ b/src/main/kotlin/pl/treksoft/kvision/panel/DockPanel.kt @@ -48,27 +48,27 @@ open class DockPanel(classes: Set<String> = setOf(), init: (DockPanel.() -> Unit * @suppress * Internal property. */ - protected var left: Component? = null + protected var leftComponent: Component? = null /** * @suppress * Internal property. */ - protected var center: Component? = null + protected var centerComponent: Component? = null /** * @suppress * Internal property. */ - protected var right: Component? = null + protected var rightComponent: Component? = null /** * @suppress * Internal property. */ - protected var up: Component? = null + protected var upComponent: Component? = null /** * @suppress * Internal property. */ - protected var down: Component? = null + protected var downComponent: Component? = null /** * @suppress @@ -101,28 +101,28 @@ open class DockPanel(classes: Set<String> = setOf(), init: (DockPanel.() -> Unit open fun add(child: Component, position: SIDE): DockPanel { when (position) { SIDE.UP -> { - up?.let { mainContainer.remove(it) } - up = child + upComponent?.let { mainContainer.remove(it) } + upComponent = child mainContainer.add(child, 1, alignSelf = FLEXALIGNITEMS.CENTER) } SIDE.CENTER -> { - center?.let { subContainer.remove(it) } - center = child + centerComponent?.let { subContainer.remove(it) } + centerComponent = child subContainer.add(child, 2) } SIDE.LEFT -> { - left?.let { subContainer.remove(it) } - left = child + leftComponent?.let { subContainer.remove(it) } + leftComponent = child subContainer.add(child, 1) } SIDE.RIGHT -> { - right?.let { subContainer.remove(it) } - right = child + rightComponent?.let { subContainer.remove(it) } + rightComponent = child subContainer.add(child, 3) } SIDE.DOWN -> { - down?.let { mainContainer.remove(it) } - down = child + downComponent?.let { mainContainer.remove(it) } + downComponent = child mainContainer.add(child, 3, alignSelf = FLEXALIGNITEMS.CENTER) } } @@ -139,11 +139,11 @@ open class DockPanel(classes: Set<String> = setOf(), init: (DockPanel.() -> Unit } override fun remove(child: Component): DockPanel { - 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) + if (child == leftComponent) removeAt(SIDE.LEFT) + if (child == centerComponent) removeAt(SIDE.CENTER) + if (child == rightComponent) removeAt(SIDE.RIGHT) + if (child == upComponent) removeAt(SIDE.UP) + if (child == downComponent) removeAt(SIDE.DOWN) return this } @@ -155,24 +155,24 @@ open class DockPanel(classes: Set<String> = setOf(), init: (DockPanel.() -> Unit open fun removeAt(position: SIDE): DockPanel { when (position) { SIDE.UP -> { - up?.let { mainContainer.remove(it) } - up = null + upComponent?.let { mainContainer.remove(it) } + upComponent = null } SIDE.CENTER -> { - center?.let { subContainer.remove(it) } - center = null + centerComponent?.let { subContainer.remove(it) } + centerComponent = null } SIDE.LEFT -> { - left?.let { subContainer.remove(it) } - left = null + leftComponent?.let { subContainer.remove(it) } + leftComponent = null } SIDE.RIGHT -> { - right?.let { subContainer.remove(it) } - right = null + rightComponent?.let { subContainer.remove(it) } + rightComponent = null } SIDE.DOWN -> { - down?.let { mainContainer.remove(it) } - down = null + downComponent?.let { mainContainer.remove(it) } + downComponent = null } } return this |