package ocelot.desktop.ui.widget import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.EventHandlers import ocelot.desktop.ui.event.Event import ocelot.desktop.ui.layout.{Layout, LinearLayout} class Widget { val eventHandlers = new EventHandlers protected var _children: Array[Widget] = Array[Widget]() protected var parent: Option[Widget] = None protected val layout: Layout = new LinearLayout(this) private var shouldRelayoutParent = false def relayoutParent(): Unit = { shouldRelayoutParent = true } def minimumSize: Size2D = layout.minimumSize def maximumSize: Size2D = layout.maximumSize protected var _position: Vector2D = Vector2D(0, 0) def position: Vector2D = _position def position_=(value: Vector2D): Unit = { if (value == _position) return _position = value relayout() } protected var _size: Size2D = Size2D(0, 0) def size: Size2D = _size def size_=(value: Size2D): Unit = { val clamped = value.clamped(minimumSize, maximumSize) if (clamped != _size) { recalculateBounds() _size = clamped.copy() relayout() shouldRelayoutParent = true } } def width: Float = size.width def height: Float = size.height def width_=(value: Float): Unit = { size = size.copy(width = value) } def height_=(value: Float): Unit = { size = size.copy(height = value) } def bounds: Rect2D = Rect2D(position, size) def children: Array[Widget] = _children def children_=(value: Array[Widget]): Unit = { _children = value for (child <- _children) child.parent = Some(this) recalculateBounds() size = _size relayout() } def recalculateBounds(): Unit = layout.recalculateBounds() def relayout(): Unit = layout.relayout() def draw(g: Graphics): Unit = { drawChildren(g) } protected def drawChildren(g: Graphics): Unit = { for (child <- children) { g.save() child.draw(g) g.restore() } } def update(): Unit = { if (shouldRelayoutParent) { parent.foreach(_.recalculateBounds()) parent.foreach(_.relayout()) shouldRelayoutParent = false } updateChildren() } protected def updateChildren(): Unit = { for (child <- children) child.update() } def handleEvent(event: Event): Unit = { eventHandlers(event) for (child <- children) child.handleEvent(event) } }