All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gtlp.ui.PWindow.kt Maven / Gradle / Ivy

The newest version!
package org.gtlp.ui

import org.gtlp.ui.events.*
import org.gtlp.ui.handlers.IMouseEventHandler
import org.gtlp.ui.handlers.ViewHandler
import org.gtlp.ui.listeners.IEventListener
import org.gtlp.ui.listeners.KeyEventListener
import org.gtlp.ui.listeners.MouseEventAdapter
import org.gtlp.ui.listeners.MouseEventListener
import org.gtlp.ui.views.IView
import org.gtlp.ui.views.buttons.AbstractButton
import org.gtlp.util.math.Vector
import processing.core.PApplet

/**
 * Class to hold a more advanced window with support for [IView]s and [IMouseEventHandler]
 * Uses [ViewHandler] for exactly those features
 */
abstract class PWindow : PApplet(), IView {

    @Suppress("LeakingThis")
    private val viewHandler = ViewHandler(this)

    override var visible = true

    override var tag: Any? = null
    override val listeners = mutableListOf()

    @Suppress("LeakingThis")
    override val parent = this

    override var pos = Vector.NAN

    override var size = Vector.NAN

    override fun drawHover() {
        draw()
    }

    override fun handleEvent(event: IWindowEvent) {
        when (event) {
            is MouseEvent -> when (event.mouseEventType) {
                MouseEventType.MOUSE_DOWN -> listeners.forEach { listeners.forEach { if (!event.cancelled && it.active && it is MouseEventListener) it.mouseDown(event) } }
                MouseEventType.MOUSE_UP -> listeners.forEach { if (!event.cancelled && it.active && it is MouseEventListener) it.mouseUp(event) }
                MouseEventType.MOUSE_CLICKED -> listeners.forEach { if (!event.cancelled && it.active && it is MouseEventListener) it.mouseClicked(event) }
                MouseEventType.NONE -> listeners.forEach { if (!event.cancelled && it.active && it is MouseEventListener) it.mouseMoved(event) }
            }
            is KeyEvent -> when (event.keyEventType) {
                KeyEventType.KEY_TYPED -> listeners.forEach { if (!event.cancelled && it.active && it is KeyEventListener) it.keyTyped(event) }
                KeyEventType.KEY_DOWN -> listeners.forEach { if (!event.cancelled && it.active && it is KeyEventListener) it.keyDown(event) }
                KeyEventType.KEY_UP -> listeners.forEach { if (!event.cancelled && it.active && it is KeyEventListener) it.keyUp(event) }
            }
        }
    }

    override fun onUpdate() {}

    final override fun mousePressed(nativeEvent: processing.event.MouseEvent) {
        viewHandler.handleEvent(MouseEvent(Vector(mouseX, mouseY), MouseEventType.MOUSE_DOWN, MouseButton.forInt(mouseButton)))
    }

    final override fun mouseReleased(nativeEvent: processing.event.MouseEvent) {
        viewHandler.handleEvent(MouseEvent(Vector(mouseX, mouseY), MouseEventType.MOUSE_UP, MouseButton.forInt(mouseButton)))
    }

    final override fun mouseClicked(nativeEvent: processing.event.MouseEvent) {
        viewHandler.handleEvent(MouseEvent(Vector(mouseX, mouseY), MouseEventType.MOUSE_CLICKED, MouseButton.forInt(mouseButton)))
    }

    final override fun mouseMoved(nativeEvent: processing.event.MouseEvent) {
        viewHandler.handleEvent(MouseEvent(Vector(mouseX, mouseY), MouseEventType.NONE, MouseButton.forInt(mouseButton)))
    }

    final override fun keyPressed(event: processing.event.KeyEvent) {
        viewHandler.handleEvent(KeyEvent(event.key, KeyEventType.KEY_DOWN))
    }

    final override fun keyReleased(event: processing.event.KeyEvent) {
        viewHandler.handleEvent(KeyEvent(event.key, KeyEventType.KEY_UP))
    }

    final override fun keyTyped(event: processing.event.KeyEvent) {
        viewHandler.handleEvent(KeyEvent(event.key, KeyEventType.KEY_TYPED))
    }

    /**
     * Method that is called prior to creating Processing's window.
     * Set the size of your sketch here.
     * Abstract to force an override on the developers side.
     */
    abstract override fun settings()

    override fun setup() {
        viewHandler.add(this)
        listeners.add(object : MouseEventAdapter() {
            override fun mouseUp(event: MouseEvent) {
                viewHandler.views.filter { it is AbstractButton<*> }.forEach {
                    it as AbstractButton<*>
                    it.pressed = false
                }
            }
        })
    }

    /**
     * Handles the drawing of [IView]s
     *
     * Remember to call `super.draw()` at the end of your [draw] method.
     * If you don't want to do that, use [onDraw].
     *
     * @see PApplet.draw
     * @see onDraw
     */
    override fun draw() {
        viewHandler.handleEvent(MouseEvent(Vector.NAN, MouseEventType.NONE, MouseButton.NONE))
        viewHandler.drawViews { it.pos.z < 0 }
        onDraw()
        viewHandler.drawViews { it.pos.z >= 0 }
    }

    /**
     * Is called whenever the [draw] method is called.
     * You can use this method to draw before the [IView]s are drawn.
     *
     * For more control over drawing on your [PApplet] override [draw].
     *
     * @see draw
     */
    open fun onDraw() {
    }

    /**
     * Used to add [IView]s to this window's [viewHandler]
     *
     * @param view the [IView] to add
     */
    fun add(view: IView) {
        viewHandler.add(view)
    }

    /**
     * Removes an [IView] form this window's [viewHandler]
     *
     * @param view the [IView] that should be removed
     *
     * @return whether or not the [view] was actually removed (ie. found in the list)
     *
     * @see MutableList.remove
     */
    fun remove(view: IView): Boolean {
        return viewHandler.remove(view)
    }

    /**
     * Method to easily determine whether the mouse hit the [IView]
     *
     * @param view the view in question
     * @param pos the position to check for, if not given, the current [mouseX] and [mouseY]
     *
     * @return whether or not the mouse is hovering over the view
     */
    fun hitView(view: IView, pos: Vector = Vector(mouseX, mouseY)): Boolean {
        return pos.x > view.pos.x && pos.x < view.pos.x + view.size.x &&
                pos.y > view.pos.y && pos.y < view.pos.y + view.size.y
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy