Add documentation
This commit is contained in:
parent
7bfb18830c
commit
83bd29ecb8
|
@ -16,7 +16,7 @@ object ASMR: ModInitializer {
|
|||
CommandRegistry.INSTANCE.register(false) { dispatcher ->
|
||||
val command = CommandManager.literal("uitest").executes {
|
||||
try {
|
||||
MinecraftClient.getInstance().openScreen(TestScreen())
|
||||
MinecraftClient.getInstance().openScreen(TestCacaoScreen())
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.shadowfacts.asmr
|
||||
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.cacao.Screen
|
||||
import net.shadowfacts.cacao.CacaoScreen
|
||||
import net.shadowfacts.cacao.view.View
|
||||
import net.shadowfacts.cacao.Window
|
||||
import net.shadowfacts.cacao.geometry.Axis
|
||||
|
@ -12,10 +12,10 @@ import net.shadowfacts.cacao.view.StackView
|
|||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class TestScreen: Screen() {
|
||||
class TestCacaoScreen: CacaoScreen() {
|
||||
|
||||
init {
|
||||
windows.add(Window().apply {
|
||||
addWindow(Window().apply {
|
||||
val stack = addView(StackView(Axis.VERTICAL, StackView.Distribution.CENTER).apply {
|
||||
backgroundColor = Color.WHITE
|
||||
})
|
|
@ -0,0 +1,43 @@
|
|||
package net.shadowfacts.cacao
|
||||
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.network.chat.TextComponent
|
||||
import net.shadowfacts.cacao.geometry.Point
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* This class serves as the bridge between Cacao and a Minecraft [Screen]. It renders Cacao [Window]s in Minecraft and
|
||||
* sends input events from Minecraft back to Cacao objects.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
open class CacaoScreen: Screen(TextComponent("CacaoScreen")) {
|
||||
|
||||
// _windows is the internal, mutable object, since we only want it to by mutated by the add/removeWindow methods.
|
||||
private val _windows = LinkedList<Window>()
|
||||
/**
|
||||
* The list of windows that belong to this screen.
|
||||
* This list should never be modified directly, only by using the [addWindow]/[removeWindow] methods.
|
||||
*/
|
||||
val windows: List<Window> = _windows
|
||||
|
||||
/**
|
||||
* Adds the given window to this screen's window list.
|
||||
* By default, the new window is added at the tail of the window list, making it the active window.
|
||||
* Only the active window will receive input events.
|
||||
*
|
||||
* @param window The Window to add to this screen.
|
||||
* @param index The index to insert the window into the window list at.
|
||||
*/
|
||||
fun addWindow(window: Window, index: Int = _windows.size) {
|
||||
_windows.add(index, window)
|
||||
}
|
||||
|
||||
override fun render(mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val mouse = Point(mouseX, mouseY)
|
||||
windows.forEach {
|
||||
it.draw(mouse, delta)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,9 @@ import net.shadowfacts.cacao.view.View
|
|||
import no.birkett.kiwi.Variable
|
||||
|
||||
/**
|
||||
* A Kiwi variable that belongs to a Cacao view.
|
||||
* This class generally isn't used directly, but via the anchor *Anchor properties on [View].
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class LayoutVariable(val owner: View, val property: String): Variable("LayoutVariable") {
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package net.shadowfacts.cacao
|
||||
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.network.chat.TextComponent
|
||||
import net.shadowfacts.cacao.geometry.Point
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
open class Screen: Screen(TextComponent("Screen")) {
|
||||
|
||||
val windows = mutableListOf<Window>()
|
||||
|
||||
fun addWindow(window: Window, index: Int? = null) {
|
||||
if (index != null) {
|
||||
windows.add(index, window)
|
||||
} else {
|
||||
windows.add(window)
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val mouse = Point(mouseX, mouseY)
|
||||
windows.forEach {
|
||||
it.draw(mouse, delta)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,18 +3,36 @@ package net.shadowfacts.cacao
|
|||
import net.shadowfacts.cacao.geometry.Point
|
||||
import net.shadowfacts.cacao.view.View
|
||||
import no.birkett.kiwi.Solver
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class Window {
|
||||
|
||||
var solver = Solver()
|
||||
|
||||
val views = mutableListOf<View>()
|
||||
// _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.
|
||||
*/
|
||||
fun <T: View> addView(view: T): T {
|
||||
views.add(view)
|
||||
_views.add(view)
|
||||
view.solver = solver
|
||||
|
||||
view.wasAdded()
|
||||
|
@ -22,11 +40,22 @@ class Window {
|
|||
return view
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the solver to solve all of the provided constraints.
|
||||
* Should be called after the view hierarchy is setup.
|
||||
*/
|
||||
fun layout() {
|
||||
solver.updateVariables()
|
||||
views.forEach(View::didLayout)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
fun draw(mouse: Point, delta: Float) {
|
||||
views.forEach(View::draw)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package net.shadowfacts.cacao.geometry
|
||||
|
||||
/**
|
||||
* An axis in a 2D coordinate plane.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
enum class Axis {
|
||||
HORIZONTAL, VERTICAL;
|
||||
|
||||
val other: Axis
|
||||
/**
|
||||
* Gets the axis that is perpendicular to this one.
|
||||
*/
|
||||
val perpendicular: Axis
|
||||
get() = when (this) {
|
||||
HORIZONTAL -> VERTICAL
|
||||
VERTICAL -> HORIZONTAL
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
package net.shadowfacts.cacao.geometry
|
||||
|
||||
/**
|
||||
* A relative position on a line along an axis.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
enum class AxisPosition {
|
||||
LEADING, CENTER, TRAILING;
|
||||
/**
|
||||
* Top for vertical, left for horizontal.
|
||||
*/
|
||||
LEADING,
|
||||
/**
|
||||
* Center X/Y.
|
||||
*/
|
||||
CENTER,
|
||||
/**
|
||||
* Bottom for vertical, right for horizontal.
|
||||
*/
|
||||
TRAILING;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package net.shadowfacts.cacao.geometry
|
||||
|
||||
/**
|
||||
* Helper class for defining 2D points.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
data class Point(val x: Double, val y: Double) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package net.shadowfacts.cacao.geometry
|
||||
|
||||
/**
|
||||
* Helper class for defining rectangles. Provides helper values for calculating perpendicular components of a rectangle based on X/Y/W/H.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
data class Rect(val left: Double, val top: Double, val width: Double, val height: Double) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package net.shadowfacts.cacao.geometry
|
||||
|
||||
/**
|
||||
* Helper class for specifying the size of objects.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
data class Size(val width: Double, val height: Double)
|
|
@ -1,12 +1,24 @@
|
|||
package net.shadowfacts.cacao.util
|
||||
|
||||
/**
|
||||
* Helper class for Cacao colors.
|
||||
*
|
||||
* @author shadowfacts
|
||||
* @param red The red component, from 0-255.
|
||||
* @param green The green component, from 0-255.
|
||||
* @param blue The blue component, from 0-255.
|
||||
* @param alpha The alpha (i.e. transparency) component, from 0-255. (0 is transparent, 255 is opaque)
|
||||
*/
|
||||
data class Color(val red: Int, val green: Int, val blue: Int, val alpha: Int = 255) {
|
||||
|
||||
/**
|
||||
* Constructs a color from the packed RGB color.
|
||||
*/
|
||||
constructor(rgb: Int, alpha: Int = 255): this(rgb shr 16, (rgb shr 8) and 255, rgb and 255, alpha)
|
||||
|
||||
/**
|
||||
* The ARGB packed representation of this color.
|
||||
*/
|
||||
val argb: Int
|
||||
get() = ((alpha and 255) shl 24) or ((red and 255) shl 16) or ((green and 255) shl 8) or (blue and 255)
|
||||
|
||||
|
|
|
@ -4,10 +4,15 @@ import net.minecraft.client.gui.DrawableHelper
|
|||
import net.shadowfacts.cacao.geometry.Rect
|
||||
|
||||
/**
|
||||
* Helper methods for rendering using Minecraft's utilities from Cacao views.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
object RenderHelper {
|
||||
|
||||
/**
|
||||
* Draws a solid [rect] filled with the given [color].
|
||||
*/
|
||||
fun fill(rect: Rect, color: Color) {
|
||||
DrawableHelper.fill(rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt(), color.argb)
|
||||
}
|
||||
|
|
|
@ -6,15 +6,22 @@ import net.shadowfacts.cacao.geometry.Size
|
|||
import net.shadowfacts.cacao.util.Color
|
||||
|
||||
/**
|
||||
* A simple View that displays text. Allows for controlling the color and shadow of the text. Label cannot be used
|
||||
* for multi-line text, instead use [TextView].
|
||||
*
|
||||
* @author shadowfacts
|
||||
* @param text The text of this label.
|
||||
*/
|
||||
class Label(text: String): View() {
|
||||
|
||||
companion object {
|
||||
val textRenderer: TextRenderer
|
||||
private val textRenderer: TextRenderer
|
||||
get() = MinecraftClient.getInstance().textRenderer
|
||||
}
|
||||
|
||||
/**
|
||||
* The text of this label. Mutating this field will update the intrinsic content size and trigger a layout.
|
||||
*/
|
||||
var text: String = text
|
||||
set(value) {
|
||||
field = value
|
||||
|
|
|
@ -6,29 +6,54 @@ import net.shadowfacts.cacao.geometry.Axis
|
|||
import net.shadowfacts.cacao.geometry.AxisPosition
|
||||
import net.shadowfacts.cacao.geometry.AxisPosition.*
|
||||
import no.birkett.kiwi.Constraint
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* A view that lays out its children in a stack along either the horizontal for vertical axes.
|
||||
* This view does not have any content of its own.
|
||||
*
|
||||
* Only arranged subviews will be laid out in the stack mode, normal subviews must perform their own layout.
|
||||
*
|
||||
* @author shadowfacts
|
||||
* @param axis The primary axis that this stack lays out its children along.
|
||||
* @param distribution The mode by which this stack lays out its children along the axis perpendicular to the
|
||||
* primary [axis].
|
||||
*/
|
||||
class StackView(val axis: Axis, val distribution: Distribution = Distribution.FILL): View() {
|
||||
|
||||
val arrangedSubviews = mutableListOf<View>()
|
||||
// the internal mutable, list of arranged subviews
|
||||
private val _arrangedSubviews = LinkedList<View>()
|
||||
/**
|
||||
* The list of arranged subviews belonging to this stack view.
|
||||
* This list should never be mutated directly, only be calling the [addArrangedSubview]/[removeArrangedSubview]
|
||||
* methods.
|
||||
*/
|
||||
val arrangedSubviews: List<View> = _arrangedSubviews
|
||||
|
||||
private var leadingConnection: Constraint? = null
|
||||
private var trailingConnection: Constraint? = null
|
||||
private var arrangedSubviewConnections = mutableListOf<Constraint>()
|
||||
|
||||
/**
|
||||
* Adds an arranged subview to this view.
|
||||
* Arranged subviews are laid out according to the stack. If you wish to add a subview that is laid out separately,
|
||||
* use the normal [addSubview] method.
|
||||
*
|
||||
* @param view The view to add.
|
||||
* @param index The index in this stack to add the view at.
|
||||
* By default, adds the view to the end of the stack.
|
||||
* @return The view that was added, as a convenience.
|
||||
*/
|
||||
fun <T: View> addArrangedSubview(view: T, index: Int = arrangedSubviews.size): T {
|
||||
addSubview(view)
|
||||
|
||||
arrangedSubviews.add(index, view)
|
||||
_arrangedSubviews.add(index, view)
|
||||
|
||||
addConstraintsForArrangedView(view, index)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
fun addConstraintsForArrangedView(view: View, index: Int) {
|
||||
private fun addConstraintsForArrangedView(view: View, index: Int) {
|
||||
if (index == 0) {
|
||||
if (leadingConnection != null) {
|
||||
solver.removeConstraint(leadingConnection)
|
||||
|
@ -77,10 +102,107 @@ class StackView(val axis: Axis, val distribution: Distribution = Distribution.FI
|
|||
return view.getAnchor(axis, position)
|
||||
}
|
||||
private fun perpAnchor(position: AxisPosition, view: View = this): LayoutVariable {
|
||||
return view.getAnchor(axis.other, position)
|
||||
return view.getAnchor(axis.perpendicular, position)
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the modes of how content is distributed in a stack view along the perpendicular axis (i.e. the
|
||||
* non-primary axis).
|
||||
*
|
||||
* ASCII-art examples are shown below in a stack view with the primary axis [Axis.VERTICAL].
|
||||
*/
|
||||
enum class Distribution {
|
||||
FILL, LEADING, CENTER, TRAILING
|
||||
/**
|
||||
* The leading edges of arranged subviews are pinned to the leading edge of the stack view.
|
||||
* ```
|
||||
* ┌─────────────────────────────┐
|
||||
* │┌─────────────┐ │
|
||||
* ││ │ │
|
||||
* ││ │ │
|
||||
* ││ │ │
|
||||
* │└─────────────┘ │
|
||||
* │┌─────────┐ │
|
||||
* ││ │ │
|
||||
* ││ │ │
|
||||
* ││ │ │
|
||||
* │└─────────┘ │
|
||||
* │┌───────────────────────────┐│
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* │└───────────────────────────┘│
|
||||
* └─────────────────────────────┘
|
||||
* ```
|
||||
*/
|
||||
LEADING,
|
||||
/**
|
||||
* The centers of the arranged subviews are pinned to the center of the stack view.
|
||||
* ```
|
||||
* ┌─────────────────────────────┐
|
||||
* │ ┌─────────────┐ │
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* │ └─────────────┘ │
|
||||
* │ ┌─────────┐ │
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* │ └─────────┘ │
|
||||
* │┌───────────────────────────┐│
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* │└───────────────────────────┘│
|
||||
* └─────────────────────────────┘
|
||||
* ```
|
||||
*/
|
||||
CENTER,
|
||||
/**
|
||||
* The trailing edges of arranged subviews are pinned to the leading edge of the stack view.
|
||||
* ```
|
||||
* ┌─────────────────────────────┐
|
||||
* │ ┌─────────────┐│
|
||||
* │ │ ││
|
||||
* │ │ ││
|
||||
* │ │ ││
|
||||
* │ └─────────────┘│
|
||||
* │ ┌─────────┐│
|
||||
* │ │ ││
|
||||
* │ │ ││
|
||||
* │ │ ││
|
||||
* │ └─────────┘│
|
||||
* │┌───────────────────────────┐│
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* │└───────────────────────────┘│
|
||||
* └─────────────────────────────┘
|
||||
* ```
|
||||
*/
|
||||
TRAILING,
|
||||
/**
|
||||
* The arranged subviews fill the perpendicular axis of the stack view.
|
||||
* ```
|
||||
* ┌─────────────────────────────┐
|
||||
* │┌───────────────────────────┐│
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* │└───────────────────────────┘│
|
||||
* │┌───────────────────────────┐│
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* │└───────────────────────────┘│
|
||||
* │┌───────────────────────────┐│
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* ││ ││
|
||||
* │└───────────────────────────┘│
|
||||
* └─────────────────────────────┘
|
||||
* ```
|
||||
*/
|
||||
FILL
|
||||
}
|
||||
}
|
|
@ -11,29 +11,73 @@ import net.shadowfacts.cacao.util.Color
|
|||
import net.shadowfacts.cacao.util.RenderHelper
|
||||
import no.birkett.kiwi.Constraint
|
||||
import no.birkett.kiwi.Solver
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* The base Cacao View class. Provides layout anchors, properties, and helper methods.
|
||||
* Doesn't draw anything itself (unless [backgroundColor] is specified), but may be used for encapsulation/grouping.
|
||||
*
|
||||
* @author shadowfacts
|
||||
*/
|
||||
open class View {
|
||||
|
||||
/**
|
||||
* The constraint solver used by the [net.shadowfacts.cacao.Window] this view belongs to.
|
||||
* Not initialized until [wasAdded] called, using it before that will throw a runtime exception.
|
||||
*/
|
||||
lateinit var solver: Solver
|
||||
|
||||
// in the coordinate system of the screen
|
||||
/**
|
||||
* Layout anchor for the left edge of this view in the window's coordinate system.
|
||||
*/
|
||||
val leftAnchor = LayoutVariable(this, "left")
|
||||
/**
|
||||
* Layout anchor for the right edge of this view in the window's coordinate system.
|
||||
*/
|
||||
val rightAnchor = LayoutVariable(this, "right")
|
||||
/**
|
||||
* Layout anchor for the top edge of this view in the window's coordinate system.
|
||||
*/
|
||||
val topAnchor = LayoutVariable(this, "top")
|
||||
/**
|
||||
* Layout anchor for the bottom edge of this view in the window's coordinate system.
|
||||
*/
|
||||
val bottomAnchor = LayoutVariable(this, "bottom")
|
||||
/**
|
||||
* Layout anchor for the width of this view in the window's coordinate system.
|
||||
*/
|
||||
val widthAnchor = LayoutVariable(this, "width")
|
||||
/**
|
||||
* Layout anchor for the height of this view in the window's coordinate system.
|
||||
*/
|
||||
val heightAnchor = LayoutVariable(this, "height")
|
||||
/**
|
||||
* Layout anchor for the center X position of this view in the window's coordinate system.
|
||||
*/
|
||||
val centerXAnchor = LayoutVariable(this, "centerX")
|
||||
/**
|
||||
* Layout anchor for the center Y position of this view in the window's coordinate system.
|
||||
*/
|
||||
val centerYAnchor = LayoutVariable(this, "centerY")
|
||||
|
||||
// The rectangle for this view in the coordinate system of the parent view.
|
||||
/**
|
||||
* The rectangle for this view in the coordinate system of its superview view (or the window, if there is no superview).
|
||||
* Not initialized until [didLayout] called.
|
||||
*/
|
||||
lateinit var frame: Rect
|
||||
// The rectangle for this view in its own coordinate system.
|
||||
/**
|
||||
* The rectangle for this view in its own coordinate system.
|
||||
* Not initialized until [didLayout] called.
|
||||
*/
|
||||
lateinit var bounds: Rect
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Setting this creates/updates [no.birkett.kiwi.Strength.WEAK] constraints on this view's width/height using
|
||||
* the size.
|
||||
*/
|
||||
var intrinsicContentSize: Size? = null
|
||||
set(value) {
|
||||
updateIntrinsicContentSizeConstraints(intrinsicContentSize, value)
|
||||
|
@ -42,11 +86,26 @@ open class View {
|
|||
private var intrinsicContentSizeWidthConstraint: Constraint? = null
|
||||
private var intrinsicContentSizeHeightConstraint: Constraint? = null
|
||||
|
||||
/**
|
||||
* The background color of this view.
|
||||
*/
|
||||
var backgroundColor = Color.CLEAR
|
||||
|
||||
var parent: View? = null
|
||||
val subviews = mutableListOf<View>()
|
||||
/**
|
||||
* This view's parent view. If `null`, this view is a top-level view in the [Window].
|
||||
*/
|
||||
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<View>()
|
||||
/**
|
||||
* The list of all the subviews of this view.
|
||||
* This list should never by mutated directly, only by the [addSubview]/[removeSubview] methods.
|
||||
*/
|
||||
val subviews: List<View> = _subviews
|
||||
|
||||
/**
|
||||
* Helper method for retrieve the anchor for a specific position on the given axis.
|
||||
*/
|
||||
fun getAnchor(axis: Axis, position: AxisPosition): LayoutVariable {
|
||||
return when (axis) {
|
||||
Axis.HORIZONTAL ->
|
||||
|
@ -64,9 +123,15 @@ open class View {
|
|||
}
|
||||
}
|
||||
|
||||
fun addSubview(view: View): View {
|
||||
subviews.add(view)
|
||||
view.parent = this
|
||||
/**
|
||||
* Adds the given subview as a child of this view.
|
||||
*
|
||||
* @param view The view to add.
|
||||
* @return The view that was added, as a convenience.
|
||||
*/
|
||||
fun <T: View> addSubview(view: T): T {
|
||||
_subviews.add(view)
|
||||
view.superview = this
|
||||
view.solver = solver
|
||||
|
||||
view.wasAdded()
|
||||
|
@ -74,11 +139,19 @@ open class View {
|
|||
return view
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this view was added to a view hierarchy.
|
||||
* If overridden, the super-class method must be called.
|
||||
*/
|
||||
open fun wasAdded() {
|
||||
createInternalConstraints()
|
||||
updateIntrinsicContentSizeConstraints(null, intrinsicContentSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during [wasAdded] to add any constraints to the [solver] that are internal to this view.
|
||||
* If overridden, the super-class method must be called.
|
||||
*/
|
||||
open fun createInternalConstraints() {
|
||||
solver.dsl {
|
||||
rightAnchor equalTo (leftAnchor + widthAnchor)
|
||||
|
@ -103,15 +176,24 @@ open class View {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after this view has been laid-out.
|
||||
* If overridden, the super-class method must be called.
|
||||
*/
|
||||
open fun didLayout() {
|
||||
subviews.forEach(View::didLayout)
|
||||
|
||||
val parentLeft = parent?.leftAnchor?.value ?: 0.0
|
||||
val parentTop = parent?.topAnchor?.value ?: 0.0
|
||||
frame = Rect(leftAnchor.value - parentLeft, topAnchor.value - parentTop, widthAnchor.value, heightAnchor.value)
|
||||
val superviewLeft = superview?.leftAnchor?.value ?: 0.0
|
||||
val superviewTop = superview?.topAnchor?.value ?: 0.0
|
||||
frame = Rect(leftAnchor.value - superviewLeft, topAnchor.value - superviewTop, widthAnchor.value, heightAnchor.value)
|
||||
bounds = Rect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to draw this view.
|
||||
* This method should not be called directly, it is called by the parent view/window.
|
||||
* This method may not be overridden, use [drawContent] to draw any custom content.
|
||||
*/
|
||||
fun draw() {
|
||||
GlStateManager.pushMatrix()
|
||||
GlStateManager.translated(frame.left, frame.top, 0.0)
|
||||
|
@ -125,6 +207,11 @@ open class View {
|
|||
GlStateManager.popMatrix()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during [draw] to draw content that's part of this view.
|
||||
* During this method, the OpenGL coordinate system has been translated so the origin is at the top left corner
|
||||
* of this view. Be careful not to translate additionally, and not to draw outside the [bounds] of the view.
|
||||
*/
|
||||
open fun drawContent() {}
|
||||
|
||||
}
|
Loading…
Reference in New Issue