2019-06-22 19:02:17 +00:00
|
|
|
package net.shadowfacts.cacao
|
2019-06-21 23:02:08 +00:00
|
|
|
|
2019-06-22 19:02:17 +00:00
|
|
|
import net.shadowfacts.cacao.geometry.Point
|
2019-06-23 15:41:32 +00:00
|
|
|
import net.shadowfacts.cacao.util.MouseButton
|
2019-06-22 19:02:17 +00:00
|
|
|
import net.shadowfacts.cacao.view.View
|
2019-06-21 23:02:08 +00:00
|
|
|
import no.birkett.kiwi.Solver
|
2019-06-22 20:08:00 +00:00
|
|
|
import java.util.*
|
2019-06-21 23:02:08 +00:00
|
|
|
|
2019-06-22 14:59:18 +00:00
|
|
|
/**
|
2019-06-22 20:08:00 +00:00
|
|
|
* A Window is the object at the top of a Cacao view hierarchy. It occupies the entirety of the Minecraft screen size
|
|
|
|
* and provides the base coordinate system for its view hierarchy.
|
|
|
|
*
|
|
|
|
* The Window owns the Kiwi [Solver] object used for layout by all of its views.
|
|
|
|
*
|
2019-06-22 14:59:18 +00:00
|
|
|
* @author shadowfacts
|
|
|
|
*/
|
2019-06-21 23:02:08 +00:00
|
|
|
class Window {
|
|
|
|
|
|
|
|
var solver = Solver()
|
|
|
|
|
2019-06-22 20:08:00 +00:00
|
|
|
// _views is the internal, mutable object, since we only want it to be mutated by the add/removeView methods
|
|
|
|
private val _views = LinkedList<View>()
|
|
|
|
/**
|
|
|
|
* The list of top-level views in this window.
|
|
|
|
* This list should never be modified directly, only by calling the [addView]/[removeView] methods.
|
|
|
|
*/
|
|
|
|
val views: List<View> = _views
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the given view as a top-level view in this window.
|
|
|
|
*
|
|
|
|
* @param view The view to add.
|
|
|
|
* @return The same view, as a convenience.
|
|
|
|
*/
|
2019-06-21 23:02:08 +00:00
|
|
|
fun <T: View> addView(view: T): T {
|
2019-06-22 20:08:00 +00:00
|
|
|
_views.add(view)
|
2019-06-21 23:02:08 +00:00
|
|
|
view.solver = solver
|
|
|
|
|
|
|
|
view.wasAdded()
|
|
|
|
|
|
|
|
return view
|
|
|
|
}
|
|
|
|
|
2019-06-23 15:41:32 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* @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.
|
|
|
|
*/
|
|
|
|
fun viewAtPoint(point: Point): View? {
|
|
|
|
return views.firstOrNull { point in it.frame }
|
|
|
|
}
|
|
|
|
|
2019-06-22 20:08:00 +00:00
|
|
|
/**
|
|
|
|
* Instructs the solver to solve all of the provided constraints.
|
|
|
|
* Should be called after the view hierarchy is setup.
|
|
|
|
*/
|
2019-06-21 23:02:08 +00:00
|
|
|
fun layout() {
|
|
|
|
solver.updateVariables()
|
|
|
|
views.forEach(View::didLayout)
|
|
|
|
}
|
|
|
|
|
2019-06-22 20:08:00 +00:00
|
|
|
/**
|
|
|
|
* Draws this window and all of its views.
|
|
|
|
* This method is called by [CacaoScreen] and generally shouldn't be called directly.
|
|
|
|
*
|
|
|
|
* @param mouse The point in the coordinate system of the window.
|
|
|
|
* @param delta The time elapsed since the last frame.
|
|
|
|
*/
|
2019-06-21 23:02:08 +00:00
|
|
|
fun draw(mouse: Point, delta: Float) {
|
2019-06-23 15:41:32 +00:00
|
|
|
views.forEach {
|
|
|
|
val mouseInView = Point(mouse.x - it.frame.left, mouse.y - it.frame.top)
|
|
|
|
it.draw(mouseInView, delta)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when a mouse button is clicked and this is the active window.
|
|
|
|
* This method is called by [CacaoScreen] and generally shouldn't be called directly.
|
|
|
|
*
|
|
|
|
* @param point The point in the window of the click.
|
|
|
|
* @param mouseButton The mouse button that was used to click.
|
|
|
|
*/
|
|
|
|
fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
|
|
|
val view = viewAtPoint(point)
|
|
|
|
if (view != null) {
|
|
|
|
val pointInView = Point(point.x - view.frame.left, point.y - view.frame.top)
|
|
|
|
view.mouseClicked(pointInView, mouseButton)
|
|
|
|
}
|
2019-06-21 23:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|