From 7fc2b1cd877a82b053acb1fb3702a9eb04f0bb64 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 9 Sep 2023 20:22:10 -0400 Subject: [PATCH] Text boxes now have properly constrained scrolling/autoscrolling --- textbox.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/textbox.go b/textbox.go index d277467..e54c0e2 100644 --- a/textbox.go +++ b/textbox.go @@ -59,7 +59,7 @@ func (this *textBox) ContentBounds () image.Rectangle { } func (this *textBox) ScrollTo (point image.Point) { - // TODO: constrain scroll + if this.scroll == point { return } this.scroll = point this.invalidateLayout() } @@ -115,6 +115,7 @@ func (this *textBox) Select (dot text.Dot) { if this.dot == dot { return } this.SetFocused(true) this.dot = dot + this.scrollToDot() this.on.dotChange.Broadcast() this.invalidateDraw() } @@ -275,16 +276,13 @@ func (this *textBox) normalizedLayoutBoundsSpace () image.Rectangle { } func (this *textBox) contentMinimum () image.Point { - minimum := image.Pt ( - this.drawer.Em().Round(), - this.drawer.LineHeight().Round()) + minimum := this.drawer.MinimumSize() - textSize := this.drawer.MinimumSize() - if !this.hOverflow && !this.wrap { - minimum.X = textSize.X + if this.hOverflow || this.wrap { + minimum.X = this.drawer.Em().Round() } - if !this.vOverflow { - minimum.Y = textSize.Y + if this.vOverflow { + minimum.Y = this.drawer.LineHeight().Round() } return minimum.Add(this.box.contentMinimum()) @@ -298,9 +296,59 @@ func (this *textBox) doLayout () { this.drawer.SetMaxWidth(innerBounds.Dx()) this.drawer.SetMaxHeight(innerBounds.Dy()) - this.contentBounds = this.normalizedLayoutBoundsSpace().Add(this.scroll) + this.contentBounds = this.normalizedLayoutBoundsSpace() + this.constrainScroll() + this.contentBounds = this.contentBounds.Add(this.scroll) if previousContentBounds != this.contentBounds { this.on.contentBoundsChange.Broadcast() } } + +func (this *textBox) 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 *textBox) scrollToDot () { + dot := roundPt(this.drawer.PositionAt(this.dot.End)).Add(this.textOffset()) + innerBounds := this.InnerBounds() + scroll := this.scroll + em := this.drawer.Em().Round() + lineHeight := this.drawer.LineHeight().Round() + + // X + if dot.X < innerBounds.Min.X + em { + scroll.X -= innerBounds.Min.X - dot.X + em + } else if dot.X > innerBounds.Max.X - em { + scroll.X += dot.X - innerBounds.Max.X + em + } + + // Y + if dot.Y < innerBounds.Min.Y + lineHeight { + scroll.Y -= innerBounds.Min.Y - dot.Y + lineHeight + } else if dot.Y > innerBounds.Max.Y - lineHeight { + scroll.Y += dot.Y - innerBounds.Max.Y + lineHeight + } + + this.ScrollTo(scroll) +}