Skip to content

Commit 6149b56

Browse files
committed
- [Fix] Edge case in ScrollPanel where layout might be skipped
- [Versions] Doodle -> 0.11.4 - [Docs] Update docs site
1 parent 282941c commit 6149b56

36 files changed

+139
-72
lines changed

Core/src/commonMain/kotlin/io/nacular/doodle/controls/panels/ScrollPanel.kt

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.nacular.doodle.controls.panels.ScrollPanelBehavior.ScrollBarType.Horiz
44
import io.nacular.doodle.core.Behavior
55
import io.nacular.doodle.core.Internal
66
import io.nacular.doodle.core.Layout
7+
import io.nacular.doodle.core.Positionable
78
import io.nacular.doodle.core.View
89
import io.nacular.doodle.core.behavior
910
import io.nacular.doodle.core.scrollTo
@@ -12,13 +13,14 @@ import io.nacular.doodle.drawing.Canvas
1213
import io.nacular.doodle.geometry.Point
1314
import io.nacular.doodle.geometry.Point.Companion.Origin
1415
import io.nacular.doodle.geometry.Rectangle
16+
import io.nacular.doodle.geometry.Size
1517
import io.nacular.doodle.layout.Insets
1618
import io.nacular.doodle.layout.constraints.Bounds
1719
import io.nacular.doodle.layout.constraints.Constraint
1820
import io.nacular.doodle.layout.constraints.ConstraintDslContext
1921
import io.nacular.doodle.layout.constraints.ConstraintLayout
2022
import io.nacular.doodle.layout.constraints.IdealSizedProperty
21-
import io.nacular.doodle.layout.constraints.constrain
23+
import io.nacular.doodle.layout.constraints.impl.ConstraintLayoutImpl
2224
import io.nacular.doodle.utils.ChangeObservers
2325
import io.nacular.doodle.utils.ChangeObserversImpl
2426
import io.nacular.doodle.utils.ObservableList
@@ -189,37 +191,38 @@ public open class ScrollPanel(content: View? = null): View() {
189191
it.top eq -scroll.y
190192
it.left eq -scroll.x
191193

192-
if (!ignoreLayout) {
193-
contentWidthConstraints?.invoke(this, object : IdealSizedProperty() {
194-
override val idealValue get() = it.idealWidth
195-
override val readOnly get() = it.width.readOnly
196-
override fun toTerm() = it.width.toTerm()
197-
})
198-
contentHeightConstraints?.invoke(this, object : IdealSizedProperty() {
199-
override val idealValue get() = it.idealHeight
200-
override val readOnly get() = it.height.readOnly
201-
override fun toTerm() = it.height.toTerm()
202-
})
203-
}
204-
205-
ignoreLayout = false
194+
contentWidthConstraints?.invoke(this, object : IdealSizedProperty() {
195+
override val idealValue get() = it.idealWidth
196+
override val readOnly get() = it.width.readOnly
197+
override fun toTerm() = it.width.toTerm()
198+
})
199+
contentHeightConstraints?.invoke(this, object : IdealSizedProperty() {
200+
override val idealValue get() = it.idealHeight
201+
override val readOnly get() = it.height.readOnly
202+
override fun toTerm() = it.height.toTerm()
203+
})
206204
}
207205

208-
private var ignoreLayout = false
209-
210206
init {
211207
mirrorWhenRightLeft = false
212208

213209
this.content = content
214210

215-
layout = when (content) {
216-
null -> constrain(view {}) {}
217-
else -> constrain(content, contentConstraints)
218-
}
211+
layout = CustomLayout()
219212

220213
preferredSize = { min, max -> this@ScrollPanel.content?.preferredSize(min, max) ?: min }
221214
}
222215

216+
/**
217+
* Used to avoid layouts on scroll
218+
*/
219+
private inner class CustomLayout: ConstraintLayoutImpl(content ?: view {}, originalLambda = contentConstraints, block = { (a) -> contentConstraints(a) }) {
220+
override fun requiresLayout(child: Positionable, within: Size, old: Rectangle, new: Rectangle) = when {
221+
old.size.fastEquals(new.size) -> false
222+
else -> super.requiresLayout(child, within, old, new)
223+
}
224+
}
225+
223226
public override var focusable: Boolean = false
224227

225228
override fun render(canvas: Canvas) {
@@ -317,7 +320,7 @@ public open class ScrollPanel(content: View? = null): View() {
317320
false -> Point(max(0.0, min(point.x, it.width - width)), max(0.0, min(point.y, it.height - height)))
318321
}
319322

320-
ignoreLayout = true
323+
// ignoreLayout = true
321324
scroll = newScroll
322325

323326
it.suggestPosition(-newScroll)

Core/src/commonMain/kotlin/io/nacular/doodle/drawing/impl/RenderManagerImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ public open class RenderManagerImpl(
700700

701701
when (parent) {
702702
null -> if (display.layout?.requiresLayout(view.positionable, display.size, old, new) == true) displayPendingLayout = true
703-
else -> if (parent != layingOut && parent.layout_?.requiresLayout(view.positionable, parent.size, old, new) == true) {
703+
else -> if (parent != layingOut && parent.layout_?.requiresLayout(view.positionable, parent.size, old, new) == true) {
704704
pendingLayout += parent
705705
}
706706
}

Core/src/commonMain/kotlin/io/nacular/doodle/layout/constraints/impl/ConstraintLayoutImpl.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,11 @@ internal open class ParentBoundsImpl(private val context: ConstraintDslContext):
194194
override var insets: Insets = Insets.None
195195
}
196196

197-
internal class ConstraintLayoutImpl(
198-
view: View,
199-
vararg others: View,
200-
originalLambda: Any,
201-
block: ConstraintDslContext.(List<Bounds>) -> Unit
197+
internal open class ConstraintLayoutImpl(
198+
view : View,
199+
vararg others : View,
200+
originalLambda: Any,
201+
block : ConstraintDslContext.(List<Bounds>) -> Unit
202202
): ConstraintLayout(), BoundsAttemptObserver {
203203
private var layingOut = false
204204
private val activeBounds = mutableMapOf<ReflectionVariable, Double>()
@@ -217,7 +217,7 @@ internal class ConstraintLayoutImpl(
217217

218218
override fun boundsChangeAttempted(view: View, old: Rectangle, new: Rectangle, relayout: Boolean) {
219219
updateBounds(view, new)?.let {
220-
if (!layingOut && relayout && view.displayed) {
220+
if (!layingOut && relayout && view.displayed && requiresLayout(view.positionable, withinSize(view), old, new)) {
221221
when (val p = view.parent) {
222222
null -> view.display?.relayout()
223223
else -> p.relayout_()
@@ -320,6 +320,11 @@ internal class ConstraintLayoutImpl(
320320
(exceptionThrown as SetPool).forEach { it(this, exception) }
321321
}
322322

323+
private fun withinSize(view: View) = when (val p = view.parent) {
324+
null -> view.display?.size ?: Size.Empty
325+
else -> p.size
326+
}
327+
323328
internal companion object {
324329
fun setupSolver(
325330
solver : Solver,

docs/404.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313

1414
<script src="https://unpkg.com/kotlin-playground@1"></script><link rel="stylesheet" href="/doodle/assets/css/styles.ae3d4d5a.css">
15-
<script src="/doodle/assets/js/runtime~main.b445f854.js" defer="defer"></script>
15+
<script src="/doodle/assets/js/runtime~main.72adf7e7.js" defer="defer"></script>
1616
<script src="/doodle/assets/js/main.b2c734db.js" defer="defer"></script>
1717
</head>
1818
<body class="navigation-with-keyboard">
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/assets/js/common.631781ec.js

Lines changed: 2 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*!****************************!*\
2+
!*** ./kotlin/measured.js ***!
3+
\****************************/
4+
5+
/*!*******************************!*\
6+
!*** ./kotlin/doodle-core.js ***!
7+
\*******************************/
8+
9+
/*!********************************!*\
10+
!*** ./kotlin/DocApps-Main.js ***!
11+
\********************************/
12+
13+
/*!*********************************!*\
14+
!*** ./kotlin/doodle-themes.js ***!
15+
\*********************************/
16+
17+
/*!**********************************!*\
18+
!*** ./kotlin/doodle-browser.js ***!
19+
\**********************************/
20+
21+
/*!***********************************!*\
22+
!*** ./kotlin/doodle-controls.js ***!
23+
\***********************************/
24+
25+
/*!************************************!*\
26+
!*** ./kotlin/doodle-animation.js ***!
27+
\************************************/
28+
29+
/*!************************************!*\
30+
!*** ./kotlin/kotlinx-atomicfu.js ***!
31+
\************************************/
32+
33+
/*!****************************************!*\
34+
!*** ./kotlin/Kosi-Kaverit-kaverit.js ***!
35+
\****************************************/
36+
37+
/*!****************************************!*\
38+
!*** ./kotlin/kotlin-kotlin-stdlib.js ***!
39+
\****************************************/
40+
41+
/*!*****************************************!*\
42+
!*** ./kotlin/Kosi-Kodein-kodein-di.js ***!
43+
\*****************************************/
44+
45+
/*!*******************************************!*\
46+
!*** ./kotlin/kotlinx-coroutines-core.js ***!
47+
\*******************************************/
48+
49+
/*!************************************************************!*\
50+
!*** ../../node_modules/@js-joda/core/dist/js-joda.esm.js ***!
51+
\************************************************************/
52+
53+
/*!************************************************************!*\
54+
!*** ./kotlin/Kotlin-DateTime-library-kotlinx-datetime.js ***!
55+
\************************************************************/
56+
57+
/*!********************************************************************!*\
58+
!*** ./kotlin/kotlinx-serialization-kotlinx-serialization-core.js ***!
59+
\********************************************************************/

docs/assets/js/common.82c8c059.js

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)