Ivan Tsitserskyi
Ivan Tsitserskyi

Reputation: 1

Resize of VBox as part of Scene JavaFX

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

Answers (0)

Related Questions