Reputation: 1
I'm new in Kotlin and TornadoFX, so I need to resize VBox as Rectangle on the code below. Inside my VBox I also have other components like scroll pane or HBox so maybe it isn't very clear resizing my VBox. But as I tested, this code below does exactly what I need but only for Rectangle, not VBox. So How can I use this code for resizing VBox or what do I need to add for resizing it? Or maybe any tips for using frameworks JavaFX or TornadoFX to resize my VBox?
import javafx.event.EventHandler
import javafx.scene.Cursor
import javafx.scene.Node
import javafx.scene.canvas.Canvas
import javafx.scene.input.MouseEvent
import javafx.scene.layout.Pane
import javafx.scene.layout.VBox
import javafx.scene.shape.Rectangle
class DragResizeMod {
interface OnDragResizeEventListener {
fun onDrag(node: Node?, x: Double, y: Double, h: Double, w: Double)
fun onResize(node: Node?, x: Double, y: Double, h: Double, w: Double)
}
private val defaultListener: OnDragResizeEventListener = object: OnDragResizeEventListener {
override fun onDrag(node: Node?, x: Double, y: Double, h: Double, w: Double) {
setNodeSize(node, x, y, h, w)
}
override fun onResize(node: Node?, x: Double, y: Double, h: Double, w: Double) {
setNodeSize(node, x, y, h, w)
}
fun setNodeSize(node: Node?, x: Double, y: Double, h: Double, w: Double) {
node!!.layoutX = x
node.layoutY = y
if (node is Canvas) {
node.width = w
node.height = h
} else if (node is Rectangle) {
node.width = w
node.height = h
}
}
}
enum class S {
DEFAULT, DRAG, NW_RESIZE, SW_RESIZE, NE_RESIZE, SE_RESIZE, E_RESIZE, W_RESIZE, N_RESIZE, S_RESIZE
}
private var clickX = 0.0
private var clickY = 0.0
private var nodeX = 0.0
private var nodeY = 0.0
private var nodeH = 0.0
private var nodeW = 0.0
private var state = S.DEFAULT
private var node: Node? = null
private var listener: OnDragResizeEventListener? = defaultListener
private val MARGIN = 8
private val MIN_W = 30.0
private val MIN_H = 20.0
constructor(node: Node, listener: OnDragResizeEventListener?) {
this.node = node
if (listener != null) this.listener = listener
makeResizable(node)
}
fun makeResizable(node: Node) {
makeResizable(node, null)
}
fun makeResizable(node: Node, listener: OnDragResizeEventListener?) {
node.onMousePressed = EventHandler { event -> mousePressed(event!!) }
node.onMouseDragged = EventHandler { event -> mouseDragged(event!!) }
node.onMouseMoved = EventHandler { event -> mouseOver(event!!) }
node.onMouseReleased = EventHandler { event -> mouseReleased(event) }
}
protected fun mouseReleased(event: MouseEvent?) {
node!!.cursor = Cursor.DEFAULT
state = S.DEFAULT
}
protected fun mouseOver(event: MouseEvent) {
val state = currentMouseState(event)
val cursor = getCursorForState(state)
node!!.cursor = cursor
}
private fun currentMouseState(event: MouseEvent): S {
var state = S.DEFAULT
val left = isLeftResizeZone(event)
val right = isRightResizeZone(event)
val top = isTopResizeZone(event)
val bottom = isBottomResizeZone(event)
if (left && top) state = S.NW_RESIZE else if (left && bottom) state = S.SW_RESIZE else if (right && top) state =
S.NE_RESIZE else if (right && bottom) state = S.SE_RESIZE else if (right) state =
S.E_RESIZE else if (left) state = S.W_RESIZE else if (top) state = S.N_RESIZE else if (bottom) state =
S.S_RESIZE else if (isInDragZone(event)) state = S.DRAG
return state
}
private fun getCursorForState(state: S): Cursor {
return when (state) {
S.NW_RESIZE -> Cursor.NW_RESIZE
S.SW_RESIZE -> Cursor.SW_RESIZE
S.NE_RESIZE -> Cursor.NE_RESIZE
S.SE_RESIZE -> Cursor.SE_RESIZE
S.E_RESIZE -> Cursor.E_RESIZE
S.W_RESIZE -> Cursor.W_RESIZE
S.N_RESIZE -> Cursor.N_RESIZE
S.S_RESIZE -> Cursor.S_RESIZE
else -> Cursor.DEFAULT
}
}
protected fun mouseDragged(event: MouseEvent) {
if (listener != null) {
val mouseX = parentX(event.x)
val mouseY = parentY(event.y)
if (state == S.DRAG) {
listener!!.onDrag(node, mouseX - clickX, mouseY - clickY, nodeH, nodeW)
} else if (state != S.DEFAULT) {
var newX = nodeX
var newY = nodeY
var newH = nodeH
var newW = nodeW
if (state == S.E_RESIZE || state == S.NE_RESIZE || state == S.SE_RESIZE) {
newW = mouseX - nodeX
}
if (state == S.W_RESIZE || state == S.NW_RESIZE || state == S.SW_RESIZE) {
newX = mouseX
newW = nodeW + nodeX - newX
}
if (state == S.S_RESIZE || state == S.SE_RESIZE || state == S.SW_RESIZE) {
newH = mouseY - nodeY
}
if (state == S.N_RESIZE || state == S.NW_RESIZE || state == S.NE_RESIZE) {
newY = mouseY
newH = nodeH + nodeY - newY
}
if (newW < MIN_W) {
if (state == S.W_RESIZE || state == S.NW_RESIZE || state == S.SW_RESIZE) newX = newX - MIN_W + newW
newW = MIN_W
}
if (newH < MIN_H) {
if (state == S.N_RESIZE || state == S.NW_RESIZE || state == S.NE_RESIZE) newY = newY + newH - MIN_H
newH = MIN_H
}
listener!!.onResize(node, newX, newY, newH, newW)
}
}
}
protected fun mousePressed(event: MouseEvent) {
state = if (isInResizeZone(event)) {
setNewInitialEventCoordinates(event)
currentMouseState(event)
} else if (isInDragZone(event)) {
setNewInitialEventCoordinates(event)
S.DRAG
} else {
S.DEFAULT
}
}
private fun setNewInitialEventCoordinates(event: MouseEvent) {
nodeX = nodeX()
nodeY = nodeY()
nodeH = nodeH()
nodeW = nodeW()
clickX = event.x
clickY = event.y
}
private fun isInResizeZone(event: MouseEvent): Boolean {
return (isLeftResizeZone(event) || isRightResizeZone(event)
|| isBottomResizeZone(event) || isTopResizeZone(event))
}
private fun isInDragZone(event: MouseEvent): Boolean {
val xPos = parentX(event.x)
val yPos = parentY(event.y)
val nodeX = nodeX() + MARGIN
val nodeY = nodeY() + MARGIN
val nodeX0 = nodeX() + nodeW() - MARGIN
val nodeY0 = nodeY() + nodeH() - MARGIN
return xPos > nodeX && xPos < nodeX0 && yPos > nodeY && yPos < nodeY0
}
private fun isLeftResizeZone(event: MouseEvent): Boolean {
return intersect(0.0, event.x)
}
private fun isRightResizeZone(event: MouseEvent): Boolean {
return intersect(nodeW(), event.x)
}
private fun isTopResizeZone(event: MouseEvent): Boolean {
return intersect(0.0, event.y)
}
private fun isBottomResizeZone(event: MouseEvent): Boolean {
return intersect(nodeH(), event.y)
}
private fun intersect(side: Double, point: Double): Boolean {
return side + MARGIN > point && side - MARGIN < point
}
private fun parentX(localX: Double): Double {
return nodeX() + localX
}
private fun parentY(localY: Double): Double {
return nodeY() + localY
}
private fun nodeX(): Double {
return node!!.boundsInParent.minX
}
private fun nodeY(): Double {
return node!!.boundsInParent.minY
}
private fun nodeW(): Double {
return node!!.boundsInParent.width
}
private fun nodeH(): Double {
return node!!.boundsInParent.height
}
}
Upvotes: 0
Views: 308