Skip to content

Commit 09fcdc6

Browse files
committed
Window minimization, api changes
1 parent 82c931e commit 09fcdc6

File tree

7 files changed

+113
-68
lines changed

7 files changed

+113
-68
lines changed

common/src/main/kotlin/com/lambda/newgui/LambdaScreen.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,8 @@ class LambdaScreen(
119119
@UIBuilder
120120
fun gui(block: Layout.() -> Unit) =
121121
Layout(owner = null, useBatching = false, batchChildren = true).apply {
122-
var screenSize = Vec2d.ONE * 10000.0
123-
124-
rectUpdate {
125-
Rect(Vec2d.ZERO, screenSize)
126-
}
127-
128122
onRender {
129-
screenSize = RenderMain.screenSize
123+
size = RenderMain.screenSize
130124
}
131125
}.apply(block)
132126

common/src/main/kotlin/com/lambda/newgui/component/core/TextField.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ class TextField(
2727
init {
2828
properties.interactionPassthrough = true
2929
verticalAlignment = VAlign.CENTER
30-
rectUpdate(owner::rect)
3130

3231
onRender {
32+
position = owner.position
33+
size = owner.size
34+
3335
val x = lerp(
3436
horizontalAlignment.multiplier,
3537
rect.left,

common/src/main/kotlin/com/lambda/newgui/component/layout/Layout.kt

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,36 @@ open class Layout(
4242
/**
4343
* The rectangle of this component
4444
*/
45-
val rect get() = Rect.basedOn(position, size)
45+
var rect
46+
get() = Rect.basedOn(actualPosition, actualSize)
47+
set(value) { position = value.leftTop; size = value.size }
48+
49+
private val actualPosition get() = positionOverride()
50+
private val actualSize get() = sizeOverride()
51+
52+
/**
53+
* Relative position of the component
54+
*/
55+
var relativePos = Vec2d.ZERO
56+
57+
/**
58+
* The position of the component
59+
*
60+
* Note: actual position could be overridden using [overridePosition], to get actual position [rect].leftTop instead
61+
*/
62+
var position: Vec2d
63+
get() = ownerRect.leftTop + relativeToAbs(relativePos).let {
64+
if (!properties.clampPosition) it
65+
else it.coerceIn(
66+
0.0, ownerRect.size.x - actualSize.x,
67+
0.0, ownerRect.size.y - actualSize.y
68+
)
69+
}; set(value) { relativePos = absToRelative(value - ownerRect.leftTop) }
4670

4771
/**
4872
* The size of this component
73+
*
74+
* Note: actual size could be overridden using [overridePosition], to get actual size [rect].size instead
4975
*/
5076
var size = Vec2d.ZERO
5177

@@ -57,7 +83,7 @@ open class Layout(
5783
field = to
5884

5985
val delta = to.multiplier - from.multiplier
60-
relativePos += Vec2d.RIGHT * delta * (size.x - ownerRect.size.x)
86+
relativePos += Vec2d.RIGHT * delta * (actualSize.x - ownerRect.size.x)
6187
}
6288

6389
/**
@@ -68,30 +94,13 @@ open class Layout(
6894
field = to
6995

7096
val delta = to.multiplier - from.multiplier
71-
relativePos += Vec2d.BOTTOM * delta * (size.y - ownerRect.size.y)
97+
relativePos += Vec2d.BOTTOM * delta * (actualSize.y - ownerRect.size.y)
7298
}
7399

74-
/**
75-
* Relative position of the component
76-
*/
77-
var relativePos = Vec2d.ZERO
78-
79-
/**
80-
* Absolute(drawn) position of the component
81-
*/
82-
var position: Vec2d
83-
get() = ownerRect.leftTop + relativeToAbs(relativePos).let {
84-
if (!properties.clampPosition) it
85-
else it.coerceIn(
86-
0.0, ownerRect.size.x - size.x,
87-
0.0, ownerRect.size.y - size.y
88-
)
89-
}; set(value) { relativePos = absToRelative(value - ownerRect.leftTop) }
90-
91100
// Rect-related properties
92101
private var screenSize = Vec2d.ZERO
93102
private val ownerRect get() = owner?.rect ?: Rect(Vec2d.ZERO, screenSize)
94-
private val dockingOffset get() = (ownerRect.size - size) * Vec2d(horizontalAlignment.multiplier, verticalAlignment.multiplier)
103+
private val dockingOffset get() = (ownerRect.size - actualSize) * Vec2d(horizontalAlignment.multiplier, verticalAlignment.multiplier)
95104
private fun relativeToAbs(posIn: Vec2d) = posIn + dockingOffset
96105
private fun absToRelative(posIn: Vec2d) = posIn - dockingOffset
97106

@@ -134,7 +143,8 @@ open class Layout(
134143
private var mouseClickActions = mutableListOf<(button: Mouse.Button, action: Mouse.Action) -> Unit>()
135144
private var mouseMoveActions = mutableListOf<(mouse: Vec2d) -> Unit>()
136145
private var mouseScrollActions = mutableListOf<(delta: Double) -> Unit>()
137-
private var rectUpdate: (() -> Rect)? = null
146+
private var positionOverride: (() -> Vec2d) = { position }
147+
private var sizeOverride: (() -> Vec2d) = { size }
138148

139149
/**
140150
* Sets the action to be performed when the element gets shown.
@@ -218,20 +228,22 @@ open class Layout(
218228
}
219229

220230
/**
221-
* Sets the rect of the element
231+
* Overrides the drawn position of the component
222232
*/
223-
fun rectUpdate(block: () -> Rect) {
224-
rectUpdate = block
233+
fun overridePosition(transform: () -> Vec2d) {
234+
positionOverride = transform
235+
}
236+
237+
/**
238+
* Overrides the drawn size of the component
239+
*/
240+
fun overrideSize(transform: () -> Vec2d) {
241+
sizeOverride = transform
225242
}
226243

227244
fun onEvent(e: GuiEvent) {
228245
if (e is GuiEvent.Render) {
229246
screenSize = RenderMain.screenSize
230-
231-
rectUpdate?.invoke()?.let {
232-
position = it.leftTop
233-
size = it.size
234-
}
235247
}
236248

237249
// Select an element that's on foreground
@@ -275,22 +287,28 @@ open class Layout(
275287
mouseClickActions.forEach { it(e.button, action) }
276288
}
277289
is GuiEvent.Render -> {
278-
val (pre, post) = children.partition { !it.owningRenderer }
290+
val drawChildren = rect.size.let { it.x > 0.1 && it.y > 0.1 }
291+
val partition by lazy { children.partition { !it.owningRenderer } }
279292

280-
pre.forEach { it.onEvent(e) }
281293
renderActions.forEach { it(renderer) }
282294

295+
if (drawChildren) {
296+
partition.first.forEach { it.onEvent(e) }
297+
}
298+
283299
if (owningRenderer) {
284300
renderer.render()
285301
}
286302

287-
val postAction = {
288-
post.forEach { it.onEvent(e) }
289-
}
303+
if (drawChildren) {
304+
val postAction = {
305+
partition.second.forEach { it.onEvent(e) }
306+
}
290307

291-
if (properties.scissorChildren) {
292-
scissor(rect, postAction)
293-
} else postAction()
308+
if (properties.scissorChildren) {
309+
scissor(rect, postAction)
310+
} else postAction()
311+
}
294312
}
295313
}
296314
}

common/src/main/kotlin/com/lambda/newgui/component/window/TitleBar.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import com.lambda.newgui.component.core.TextField.Companion.textField
55
import com.lambda.newgui.component.core.UIBuilder
66
import com.lambda.newgui.component.layout.Layout
77
import com.lambda.util.Mouse
8-
import com.lambda.util.math.Rect
98
import com.lambda.util.math.Vec2d
109

1110
/**
@@ -23,10 +22,6 @@ class TitleBar(
2322
private var dragOffset: Vec2d? = null
2423

2524
init {
26-
rectUpdate {
27-
Rect(owner.rect.leftTop, owner.rect.rightTop + Vec2d(0.0, renderer.font.getHeight() * 1.5))
28-
}
29-
3025
if (drag) {
3126
onShow {
3227
dragOffset = null

common/src/main/kotlin/com/lambda/newgui/component/window/Window.kt

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.lambda.newgui.component.window
22

3+
import com.lambda.graphics.animation.Animation.Companion.exp
34
import com.lambda.module.modules.client.NewCGui
45
import com.lambda.newgui.component.VAlign
56
import com.lambda.newgui.component.layout.Layout
@@ -33,8 +34,23 @@ open class Window(
3334
private val animation = animationTicker()
3435
private val cursorController = cursorController()
3536

37+
init {
38+
position = initialPosition
39+
size = initialSize
40+
}
41+
42+
// Position
43+
/*private val renderX by animation.exp(position::x, 0.8)
44+
private val renderY by animation.exp(position::y, 0.8)
45+
private val renderPosition get() = Vec2d(renderX, renderY)*/
46+
47+
// Size
48+
private val renderWidth by animation.exp({ size.x }, 0.8)
49+
private val renderHeight by animation.exp(::targetHeight, 0.8)
50+
private val targetHeight get() = (if (minimized) 0.0 else size.y).coerceAtLeast(titleBar.size.y)
51+
3652
// Minimizing
37-
var minimized = true
53+
var minimized = false
3854

3955
// Resizing
4056
private var resizeX: Double? = null
@@ -43,24 +59,39 @@ open class Window(
4359
private var resizeYHovered = false
4460

4561
init {
46-
position = initialPosition
47-
size = initialSize
48-
4962
// Clamp the window only within the screen bounds
5063
properties.clampPosition = owner.owner == null
5164

52-
onShow {
53-
with(content) {
54-
properties.scissorChildren = true
55-
56-
rectUpdate {
57-
Rect(
58-
titleBar.rect.leftBottom + NewCGui.padding,
59-
this@Window.rect.rightBottom - NewCGui.padding
60-
)
61-
}
65+
overrideSize {
66+
Vec2d(renderWidth, renderHeight)
67+
}
68+
69+
with(titleBar) {
70+
onRender {
71+
val heightVec = Vec2d(0.0, textField.textHeight * 1.5)
72+
rect = Rect(this@Window.rect.leftTop, this@Window.rect.rightTop + heightVec)
73+
}
74+
75+
onMouseClick { button, action ->
76+
if (!minimizable) return@onMouseClick
77+
if (button != Mouse.Button.Right || action != Mouse.Action.Click) return@onMouseClick
78+
79+
minimized = !minimized
80+
}
81+
}
82+
83+
with(content) {
84+
properties.scissorChildren = true
85+
86+
onRender {
87+
rect = Rect(
88+
titleBar.rect.leftBottom + NewCGui.padding,
89+
this@Window.rect.rightBottom - NewCGui.padding
90+
)
6291
}
92+
}
6393

94+
onShow {
6495
resizeX = null
6596
resizeY = null
6697
resizeXHovered = false
@@ -116,7 +147,7 @@ open class Window(
116147
resizeXHovered = false
117148
resizeYHovered = false
118149

119-
if (!resizable) return@onMouseMove
150+
if (!resizable || minimized) return@onMouseMove
120151

121152
// Hover state update
122153
if (selectedChild == null && isHovered) {
@@ -141,7 +172,10 @@ open class Window(
141172
mousePosition.y - ry
142173
} ?: size.y
143174

144-
size = Vec2d(x, y).coerceIn(80.0, 1000.0, titleBar.size.y + RESIZE_RANGE, 1000.0)
175+
size = Vec2d(x, y).coerceIn(
176+
80.0, 1000.0,
177+
titleBar.size.y + RESIZE_RANGE, 1000.0
178+
)
145179
}
146180
}
147181
}

common/src/main/kotlin/com/lambda/newgui/component/window/WindowContent.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class WindowContent(
6363
}
6464

6565
private fun reorderChildren() {
66+
// Skip for closed windows
67+
if (size.y < 0.1) return
68+
6669
var offset = renderScrollOffset
6770

6871
scrollableChildren.forEach { child ->

common/src/main/kotlin/com/lambda/util/math/Rect.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.lambda.util.math
22

3-
import com.lambda.util.math.lerp
43
import kotlin.math.max
54
import kotlin.math.min
65

0 commit comments

Comments
 (0)