From 664ce5f5560f3eb4efd2a59856d7d7338eb957b4 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 13 May 2024 17:43:26 -0400 Subject: [PATCH] Add scroll code for ContainerBox --- containerbox.go | 75 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/containerbox.go b/containerbox.go index 377361d..5a9899d 100644 --- a/containerbox.go +++ b/containerbox.go @@ -59,7 +59,7 @@ func (this *containerBox) ContentBounds () image.Rectangle { } func (this *containerBox) ScrollTo (point image.Point) { - // TODO: constrain scroll + if this.scroll == point { return } this.scroll = point this.invalidateLayout() } @@ -68,19 +68,19 @@ func (this *containerBox) OnContentBoundsChange (callback func()) event.Cookie { return this.on.contentBoundsChange.Connect(callback) } -func (this *containerBox) CaptureDND (capture bool) { +func (this *containerBox) CaptureDND (capture bool) { this.capture[eventCategoryDND] = capture } -func (this *containerBox) CaptureMouse (capture bool) { +func (this *containerBox) CaptureMouse (capture bool) { this.capture[eventCategoryMouse] = capture } -func (this *containerBox) CaptureScroll (capture bool) { +func (this *containerBox) CaptureScroll (capture bool) { this.capture[eventCategoryScroll] = capture } -func (this *containerBox) CaptureKeyboard (capture bool) { +func (this *containerBox) CaptureKeyboard (capture bool) { this.capture[eventCategoryKeyboard] = capture } @@ -225,10 +225,14 @@ func (this *containerBox) notifyMinimumSizeChange (child anyBox) { } } +func (this *containerBox) boundedLayoutHints () tomo.LayoutHints { + hints := this.layoutHints() + hints.Bounds = this.ContentBounds().Add(this.InnerBounds().Min) + return hints +} + func (this *containerBox) layoutHints () tomo.LayoutHints { - innerBounds := this.InnerBounds().Sub(this.scroll) return tomo.LayoutHints { - Bounds: innerBounds, OverflowX: this.hOverflow, OverflowY: this.vOverflow, AlignX: this.hAlign, @@ -240,10 +244,12 @@ func (this *containerBox) layoutHints () tomo.LayoutHints { func (this *containerBox) contentMinimum () image.Point { minimum := this.box.contentMinimum() if this.layout != nil { - minimum = minimum.Add ( - this.layout.MinimumSize ( - this.layoutHints(), - this.children)) + layoutMinimum := this.layout.MinimumSize ( + this.boundedLayoutHints(), + this.children) + if this.hOverflow { layoutMinimum.X = 0 } + if this.vOverflow { layoutMinimum.Y = 0 } + minimum = minimum.Add(layoutMinimum) } return minimum } @@ -251,14 +257,59 @@ func (this *containerBox) contentMinimum () image.Point { func (this *containerBox) doLayout () { this.box.doLayout() previousContentBounds := this.contentBounds + + // by default, use innerBounds for contentBounds. if a direction + // overflows, use the layout's minimum size for it. + var minimum image.Point if this.layout != nil { - this.layout.Arrange(this.layoutHints(), this.children) + minimum = this.layout.MinimumSize ( + this.layoutHints(), + this.children) } + innerBounds := this.InnerBounds() + this.contentBounds = innerBounds + if this.hOverflow { this.contentBounds.Max.X = this.contentBounds.Min.X + minimum.X } + if this.vOverflow { this.contentBounds.Max.Y = this.contentBounds.Min.Y + minimum.Y } + + // offset the content bounds by the scroll so children can be positioned + // accordingly. + this.constrainScroll() + this.contentBounds = this.contentBounds.Sub(this.scroll).Sub(innerBounds.Min) + + // arrange children + if this.layout != nil { + this.layout.Arrange(this.boundedLayoutHints(), this.children) + } + if previousContentBounds != this.contentBounds { this.on.contentBoundsChange.Broadcast() } } +func (this *containerBox) constrainScroll () { + innerBounds := this.InnerBounds() + width := this.contentBounds.Dx() + height := this.contentBounds.Dy() + + // X + if width <= innerBounds.Dx() { + this.scroll.X = 0 + } else if this.scroll.X < 0 { + this.scroll.X = 0 + } else if this.scroll.X > width - innerBounds.Dx() { + this.scroll.X = width - innerBounds.Dx() + } + + // Y + if height <= innerBounds.Dy() { + this.scroll.Y = 0 + } else if this.scroll.Y < 0 { + this.scroll.Y = 0 + } else if this.scroll.Y > height - innerBounds.Dy() { + this.scroll.Y = height - innerBounds.Dy() + } +} + func (this *containerBox) recursiveRedo () { this.doLayout() this.doDraw()