From b2499ad2476ce8a40745fed3a4d5bad3bde6584e Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Tue, 25 Jun 2019 18:39:58 -0400 Subject: [PATCH] Add Z index and view sorting --- .../kotlin/net/shadowfacts/cacao/Window.kt | 26 +++++++++++++++---- .../kotlin/net/shadowfacts/cacao/view/View.kt | 26 +++++++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/net/shadowfacts/cacao/Window.kt b/src/main/kotlin/net/shadowfacts/cacao/Window.kt index dcc884d..649846a 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/Window.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/Window.kt @@ -26,6 +26,8 @@ class Window { */ val views: List = _views + private var viewsSortedByZIndex: List = listOf() + /** * Adds the given view as a top-level view in this window. * @@ -34,6 +36,9 @@ class Window { */ fun addView(view: T): T { _views.add(view) + viewsSortedByZIndex = views.sortedBy(View::zIndex) + + view.window = this view.solver = solver view.wasAdded() @@ -42,11 +47,22 @@ class Window { } /** - * Attempts to find a top level view of this window that contains the given point. - * If there are multiple overlapping views, which one this method returns is undefined. + * Finds all views in this window at the given point. * * @param point The point to find views at, in the coordinate system of the window. - * @return The view, if any, that contains the given point. + * @return All views that contain the point. + */ + fun viewsAtPoint(point: Point): List { + return views.filter { point in it.frame } + } + + /** + * Attempts to find a top level view of this window that contains the given point. + * If there are multiple overlapping views, which one this method returns is undefined. + * [viewsAtPoint] may be used, and the resulting List sorted by [View.zIndex]. + * + * @param point The point to find views at, in the coordinate system of the window. + * @return the Veiw, if any, that contain the given point. */ fun viewAtPoint(point: Point): View? { return views.firstOrNull { point in it.frame } @@ -69,7 +85,7 @@ class Window { * @param delta The time elapsed since the last frame. */ fun draw(mouse: Point, delta: Float) { - views.forEach { + viewsSortedByZIndex.forEach { val mouseInView = Point(mouse.x - it.frame.left, mouse.y - it.frame.top) it.draw(mouseInView, delta) } @@ -84,7 +100,7 @@ class Window { * @return Whether the mouse click was handled by a view. */ fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean { - val view = viewAtPoint(point) + val view = viewsAtPoint(point).minBy(View::zIndex) if (view != null) { val pointInView = Point(point.x - view.frame.left, point.y - view.frame.top) return view.mouseClicked(pointInView, mouseButton) diff --git a/src/main/kotlin/net/shadowfacts/cacao/view/View.kt b/src/main/kotlin/net/shadowfacts/cacao/view/View.kt index bd8f2c8..1cadf1f 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/view/View.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/view/View.kt @@ -78,6 +78,12 @@ open class View() { */ lateinit var bounds: Rect + /** + * The position on the Z-axis of this view. + * Views are rendered from lowest Z index to highest. Clicks are handled from highest to lowest. + */ + var zIndex: Double = 0.0 + /** * The intrinsic size of this view's content. May be null if the view doesn't have any content or there is no * intrinsic size. @@ -104,6 +110,9 @@ open class View() { var superview: View? = null // _subviews is the internal, mutable object since we only want it to by mutated by the add/removeSubview methods private val _subviews = LinkedList() + + private var subviewsSortedByZIndex: List = listOf() + /** * The list of all the subviews of this view. * This list should never by mutated directly, only by the [addSubview]/[removeSubview] methods. @@ -143,6 +152,8 @@ open class View() { */ fun addSubview(view: T): T { _subviews.add(view) + subviewsSortedByZIndex = subviews.sortedBy(View::zIndex) + view.superview = this view.solver = solver @@ -151,9 +162,20 @@ open class View() { return view } + /** + * Finds all subviews that contain the given point. + * + * @param point The point to find subviews for, in the coordinate system of this view. + * @return All views that contain the given point. + */ + fun subviewsAtPoint(point: Point): List { + return subviews.filter { point in it.frame } + } + /** * Attempts to find a subview which contains the given point. * If multiple subviews contain the given point, which one this method returns is undefined. + * [subviewsAtPoint] may be used, and the resulting List sorted by [View.zIndex]. * * @param point The point to find a subview for, in the coordinate system of this view. * @return The view, if any, that contains the given point. @@ -233,7 +255,7 @@ open class View() { drawContent(mouse, delta) - subviews.forEach { + subviewsSortedByZIndex.forEach { val mouseInView = convert(mouse, to = it) it.draw(mouseInView, delta) } @@ -261,7 +283,7 @@ open class View() { * @return Whether the mouse click was handled by this view or any subviews. */ open fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean { - val view = subviewAtPoint(point) + val view = subviewsAtPoint(point).maxBy(View::zIndex) if (view != null) { val pointInView = convert(point, to = view) return view.mouseClicked(pointInView, mouseButton)