1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
/*
* Copyright (c) 2017-present Robert Jaros
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package pl.treksoft.kvision.panel
import com.github.snabbdom.VNode
import pl.treksoft.jquery.JQuery
import pl.treksoft.jquery.JQueryEventObject
import pl.treksoft.kvision.core.StyledComponent
import pl.treksoft.kvision.core.UNIT
import pl.treksoft.kvision.html.TAG
import pl.treksoft.kvision.html.Tag
import pl.treksoft.kvision.utils.obj
/**
* Split panel direction.
*/
enum class DIRECTION(internal val dir: String) {
HORIZONTAL("horizontal"),
VERTICAL("vertical")
}
/**
* The container with draggable splitter.
*
* It is required to have exactly two children, for both sides of the splitter. Otherwise it will be
* rendered as empty.
*
* @constructor
* @param direction direction of the splitter
* @param classes a set of CSS class names
*/
open class SplitPanel(
private val direction: DIRECTION = DIRECTION.VERTICAL,
classes: Set<String> = setOf()
) : SimplePanel(classes + ("splitpanel-" + direction.dir)) {
@Suppress("LeakingThis")
internal val splitter = Splitter(this, direction)
@Suppress("UnsafeCastFromDynamic")
internal fun afterInsertSplitter() {
if (children.size == 2) {
val horizontal = direction == DIRECTION.HORIZONTAL
val px = UNIT.px
val self = this
children[0].getElementJQueryD().resizable(obj {
handleSelector = "#" + splitter.id
resizeWidth = !horizontal
resizeHeight = horizontal
onDrag = lok@ { e: JQueryEventObject, _: JQuery, newWidth: Int, newHeight: Int, _: dynamic ->
e.asDynamic()["newWidth"] = newWidth
e.asDynamic()["newHeight"] = newHeight
self.dispatchEvent("dragSplitPanel", obj { detail = e })
return@lok !e.isDefaultPrevented()
}
onDragEnd = { e: JQueryEventObject, el: JQuery, _: dynamic ->
if (horizontal) {
(children[0] as? StyledComponent)?.height = el.height().toInt() to px
} else {
(children[0] as? StyledComponent)?.width = el.width().toInt() to px
}
self.dispatchEvent("dragEndSplitPanel", obj { detail = e })
}
})
}
}
override fun childrenVNodes(): Array<VNode> {
return if (children.size == 2) {
arrayOf(children[0].renderVNode(), splitter.renderVNode(), children[1].renderVNode())
} else {
arrayOf()
}
}
}
internal class Splitter(private val splitPanel: SplitPanel, direction: DIRECTION) : Tag(
TAG.DIV,
classes = setOf("splitter-" + direction.dir)
) {
private val idc = "kv_splitter_" + counter
init {
counter++
this.id = idc
}
override fun afterInsert(node: VNode) {
splitPanel.afterInsertSplitter()
}
companion object {
internal var counter = 0
}
}
|