Got scroll container working

This commit is contained in:
Sasha Koshka 2023-01-31 18:39:17 -05:00
parent 541d0f4204
commit 9b22e80f05
10 changed files with 52 additions and 42 deletions

View File

@ -134,7 +134,7 @@ func (element *Checkbox) SetText (text string) {
func (element *Checkbox) draw () { func (element *Checkbox) draw () {
bounds := element.Bounds() bounds := element.Bounds()
boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()) boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
backgroundPattern, _ := theme.BackgroundPattern(theme.PatternState { backgroundPattern, _ := theme.BackgroundPattern(theme.PatternState {
Case: checkboxCase, Case: checkboxCase,
@ -150,9 +150,9 @@ func (element *Checkbox) draw () {
artist.FillRectangle(element, pattern, boxBounds) artist.FillRectangle(element, pattern, boxBounds)
textBounds := element.drawer.LayoutBounds() textBounds := element.drawer.LayoutBounds()
offset := image.Point { offset := bounds.Min.Add(image.Point {
X: bounds.Dy() + theme.Padding(), X: bounds.Dy() + theme.Padding(),
} })
offset.Y -= textBounds.Min.Y offset.Y -= textBounds.Min.Y
offset.X -= textBounds.Min.X offset.X -= textBounds.Min.X

View File

@ -57,7 +57,7 @@ func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) {
func (element *ScrollContainer) handleResize () { func (element *ScrollContainer) handleResize () {
element.recalculate() element.recalculate()
element.child.DrawTo(tomo.Cut(element, element.child.Bounds())) element.resizeChildToFit()
element.draw() element.draw()
} }
@ -91,7 +91,7 @@ func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
element.vertical.enabled = element.child.ScrollAxes() element.vertical.enabled = element.child.ScrollAxes()
if element.core.HasImage() { if element.core.HasImage() {
element.child.DrawTo(tomo.Cut(element, element.child.Bounds())) element.resizeChildToFit()
} }
} }
} }
@ -113,7 +113,8 @@ func (element *ScrollContainer) HandleMouseDown (x, y int, button tomo.Button) {
if point.In(element.horizontal.bar) { if point.In(element.horizontal.bar) {
element.horizontal.dragging = true element.horizontal.dragging = true
element.horizontal.dragOffset = element.horizontal.dragOffset =
point.Sub(element.horizontal.bar.Min).X x - element.horizontal.bar.Min.X +
element.Bounds().Min.X
element.dragHorizontalBar(point) element.dragHorizontalBar(point)
} else if point.In(element.horizontal.gutter) { } else if point.In(element.horizontal.gutter) {
@ -128,7 +129,8 @@ func (element *ScrollContainer) HandleMouseDown (x, y int, button tomo.Button) {
} else if point.In(element.vertical.bar) { } else if point.In(element.vertical.bar) {
element.vertical.dragging = true element.vertical.dragging = true
element.vertical.dragOffset = element.vertical.dragOffset =
point.Sub(element.vertical.bar.Min).Y y - element.vertical.bar.Min.Y +
element.Bounds().Min.Y
element.dragVerticalBar(point) element.dragVerticalBar(point)
} else if point.In(element.vertical.gutter) { } else if point.In(element.vertical.gutter) {
@ -268,6 +270,14 @@ func (element *ScrollContainer) clearChildEventHandlers (child tomo.Scrollable)
} }
} }
func (element *ScrollContainer) resizeChildToFit () {
childBounds := image.Rect (
0, 0,
element.childWidth,
element.childHeight).Add(element.Bounds().Min)
element.child.DrawTo(tomo.Cut(element, childBounds))
}
func (element *ScrollContainer) recalculate () { func (element *ScrollContainer) recalculate () {
_, gutterInsetHorizontal := theme.GutterPattern(theme.PatternState { _, gutterInsetHorizontal := theme.GutterPattern(theme.PatternState {
Case: scrollBarHorizontalCase, Case: scrollBarHorizontalCase,
@ -300,6 +310,7 @@ func (element *ScrollContainer) recalculate () {
// if enabled, give substance to the gutters // if enabled, give substance to the gutters
if horizontal.exists { if horizontal.exists {
horizontal.gutter.Min.X = bounds.Min.X
horizontal.gutter.Min.Y = bounds.Max.Y - thicknessHorizontal horizontal.gutter.Min.Y = bounds.Max.Y - thicknessHorizontal
horizontal.gutter.Max.X = bounds.Max.X horizontal.gutter.Max.X = bounds.Max.X
horizontal.gutter.Max.Y = bounds.Max.Y horizontal.gutter.Max.Y = bounds.Max.Y
@ -312,6 +323,7 @@ func (element *ScrollContainer) recalculate () {
if vertical.exists { if vertical.exists {
vertical.gutter.Min.X = bounds.Max.X - thicknessVertical vertical.gutter.Min.X = bounds.Max.X - thicknessVertical
vertical.gutter.Max.X = bounds.Max.X vertical.gutter.Max.X = bounds.Max.X
vertical.gutter.Min.Y = bounds.Min.Y
vertical.gutter.Max.Y = bounds.Max.Y vertical.gutter.Max.Y = bounds.Max.Y
if horizontal.exists { if horizontal.exists {
vertical.gutter.Max.Y -= thicknessHorizontal vertical.gutter.Max.Y -= thicknessHorizontal

View File

@ -141,8 +141,8 @@ func (element *Switch) calculateMinimumSize () {
func (element *Switch) draw () { func (element *Switch) draw () {
bounds := element.Bounds() bounds := element.Bounds()
handleBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()) handleBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
gutterBounds := image.Rect(0, 0, bounds.Dy() * 2, bounds.Dy()) gutterBounds := image.Rect(0, 0, bounds.Dy() * 2, bounds.Dy()).Add(bounds.Min)
backgroundPattern, _ := theme.BackgroundPattern(theme.PatternState { backgroundPattern, _ := theme.BackgroundPattern(theme.PatternState {
Case: switchCase, Case: switchCase,
}) })
@ -179,9 +179,9 @@ func (element *Switch) draw () {
artist.FillRectangle(element, handlePattern, handleBounds) artist.FillRectangle(element, handlePattern, handleBounds)
textBounds := element.drawer.LayoutBounds() textBounds := element.drawer.LayoutBounds()
offset := image.Point { offset := bounds.Min.Add(image.Point {
X: bounds.Dy() * 2 + theme.Padding(), X: bounds.Dy() * 2 + theme.Padding(),
} })
offset.Y -= textBounds.Min.Y offset.Y -= textBounds.Min.Y
offset.X -= textBounds.Min.X offset.X -= textBounds.Min.X

View File

@ -258,6 +258,7 @@ func (element *TextBox) scrollToCursor () {
if !element.core.HasImage() { return } if !element.core.HasImage() { return }
bounds := element.Bounds().Inset(theme.Padding()) bounds := element.Bounds().Inset(theme.Padding())
bounds = bounds.Sub(bounds.Min)
bounds.Max.X -= element.valueDrawer.Em().Round() bounds.Max.X -= element.valueDrawer.Em().Round()
cursorPosition := element.valueDrawer.PositionOf(element.cursor) cursorPosition := element.valueDrawer.PositionOf(element.cursor)
cursorPosition.X -= element.scroll cursorPosition.X -= element.scroll
@ -285,10 +286,10 @@ func (element *TextBox) draw () {
if len(element.text) == 0 && !element.Focused() { if len(element.text) == 0 && !element.Focused() {
// draw placeholder // draw placeholder
textBounds := element.placeholderDrawer.LayoutBounds() textBounds := element.placeholderDrawer.LayoutBounds()
offset := image.Point { offset := bounds.Min.Add (image.Point {
X: theme.Padding() + inset[3], X: theme.Padding() + inset[3],
Y: theme.Padding() + inset[0], Y: theme.Padding() + inset[0],
} })
foreground, _ := theme.ForegroundPattern(theme.PatternState { foreground, _ := theme.ForegroundPattern(theme.PatternState {
Case: textBoxCase, Case: textBoxCase,
Disabled: true, Disabled: true,
@ -300,10 +301,10 @@ func (element *TextBox) draw () {
} else { } else {
// draw input value // draw input value
textBounds := element.valueDrawer.LayoutBounds() textBounds := element.valueDrawer.LayoutBounds()
offset := image.Point { offset := bounds.Min.Add (image.Point {
X: theme.Padding() + inset[3] - element.scroll, X: theme.Padding() + inset[3] - element.scroll,
Y: theme.Padding() + inset[0], Y: theme.Padding() + inset[0],
} })
foreground, _ := theme.ForegroundPattern(theme.PatternState { foreground, _ := theme.ForegroundPattern(theme.PatternState {
Case: textBoxCase, Case: textBoxCase,
Disabled: !element.Enabled(), Disabled: !element.Enabled(),

View File

@ -84,12 +84,12 @@ func (element *AnalogClock) radialLine (
bounds := element.Bounds() bounds := element.Bounds()
width := float64(bounds.Dx()) / 2 width := float64(bounds.Dx()) / 2
height := float64(bounds.Dy()) / 2 height := float64(bounds.Dy()) / 2
min := image.Pt ( min := element.Bounds().Min.Add(image.Pt (
int(math.Cos(radian) * inner * width + width), int(math.Cos(radian) * inner * width + width),
int(math.Sin(radian) * inner * height + height)) int(math.Sin(radian) * inner * height + height)))
max := image.Pt ( max := element.Bounds().Min.Add(image.Pt (
int(math.Cos(radian) * outer * width + width), int(math.Cos(radian) * outer * width + width),
int(math.Sin(radian) * outer * height + height)) int(math.Sin(radian) * outer * height + height)))
// println(min.String(), max.String()) // println(min.String(), max.String())
artist.Line(element, source, 1, min, max) artist.Line(element, source, 1, min, max)
} }

View File

@ -26,8 +26,8 @@ func NewArtist () (element *Artist) {
func (element *Artist) draw () { func (element *Artist) draw () {
bounds := element.Bounds() bounds := element.Bounds()
element.cellBounds.Max.X = bounds.Dx() / 5 element.cellBounds.Max.X = bounds.Min.X + bounds.Dx() / 5
element.cellBounds.Max.Y = (bounds.Dy() - 48) / 8 element.cellBounds.Max.Y = bounds.Min.Y + (bounds.Dy() - 48) / 8
drawStart := time.Now() drawStart := time.Now()

View File

@ -36,12 +36,12 @@ func (element *Mouse) draw () {
bounds) bounds)
artist.Line ( artist.Line (
element, artist.NewUniform(color.White), 1, element, artist.NewUniform(color.White), 1,
image.Pt(1, 1), bounds.Min.Add(image.Pt(1, 1)),
image.Pt(bounds.Dx() - 2, bounds.Dy() - 2)) bounds.Min.Add(image.Pt(bounds.Dx() - 2, bounds.Dy() - 2)))
artist.Line ( artist.Line (
element, artist.NewUniform(color.White), 1, element, artist.NewUniform(color.White), 1,
image.Pt(1, bounds.Dy() - 2), bounds.Min.Add(image.Pt(1, bounds.Dy() - 2)),
image.Pt(bounds.Dx() - 2, 1)) bounds.Min.Add(image.Pt(bounds.Dx() - 2, 1)))
} }
func (element *Mouse) HandleMouseDown (x, y int, button tomo.Button) { func (element *Mouse) HandleMouseDown (x, y int, button tomo.Button) {

View File

@ -18,13 +18,12 @@ type Dialog struct {
Pad bool Pad bool
} }
// Arrange arranges a list of entries into a dialog. // FIXME
func (layout Dialog) Arrange (entries []tomo.LayoutEntry, width, height int) {
if layout.Pad {
width -= theme.Margin() * 2
height -= theme.Margin() * 2
}
// Arrange arranges a list of entries into a dialog.
func (layout Dialog) Arrange (entries []tomo.LayoutEntry, bounds image.Rectangle) {
if layout.Pad { bounds = bounds.Inset(theme.Margin()) }
controlRowWidth, controlRowHeight := 0, 0 controlRowWidth, controlRowHeight := 0, 0
if len(entries) > 1 { if len(entries) > 1 {
controlRowWidth, controlRowWidth,
@ -37,19 +36,19 @@ func (layout Dialog) Arrange (entries []tomo.LayoutEntry, width, height int) {
entries[0].Bounds.Min.X += theme.Margin() entries[0].Bounds.Min.X += theme.Margin()
entries[0].Bounds.Min.Y += theme.Margin() entries[0].Bounds.Min.Y += theme.Margin()
} }
mainHeight := height - controlRowHeight mainHeight := bounds.Dy() - controlRowHeight
if layout.Gap { if layout.Gap {
mainHeight -= theme.Margin() mainHeight -= theme.Margin()
} }
mainBounds := entries[0].Bounds mainBounds := entries[0].Bounds
if mainBounds.Dy() != mainHeight || mainBounds.Dx() != width { if mainBounds.Dy() != mainHeight || mainBounds.Dx() != bounds.Dx() {
entries[0].Bounds.Max = entries[0].Bounds.Max =
mainBounds.Min.Add(image.Pt(width, mainHeight)) mainBounds.Min.Add(image.Pt(bounds.Dx(), mainHeight))
} }
} }
if len(entries) > 1 { if len(entries) > 1 {
freeSpace := width freeSpace := bounds.Dx()
expandingElements := 0 expandingElements := 0
// count the number of expanding elements and the amount of free // count the number of expanding elements and the amount of free
@ -71,15 +70,15 @@ func (layout Dialog) Arrange (entries []tomo.LayoutEntry, width, height int) {
} }
// determine starting position and dimensions for control row // determine starting position and dimensions for control row
x, y := 0, height - controlRowHeight x, y := 0, bounds.Dy() - controlRowHeight
if expandingElements == 0 { if expandingElements == 0 {
x = width - controlRowWidth x = bounds.Dx() - controlRowWidth
} }
if layout.Pad { if layout.Pad {
x += theme.Margin() x += theme.Margin()
y += theme.Margin() y += theme.Margin()
} }
height -= controlRowHeight bounds.Max.Y -= controlRowHeight
// set the size and position of each element in the control row // set the size and position of each element in the control row
for index, entry := range entries[1:] { for index, entry := range entries[1:] {

View File

@ -22,10 +22,9 @@ func (layout Horizontal) Arrange (entries []tomo.LayoutEntry, bounds image.Recta
// get width of expanding elements // get width of expanding elements
expandingElementWidth := layout.expandingElementWidth(entries, bounds.Dx()) expandingElementWidth := layout.expandingElementWidth(entries, bounds.Dx())
dot := bounds.Min
// set the size and position of each element // set the size and position of each element
dot := bounds.Min
for index, entry := range entries { for index, entry := range entries {
if index > 0 && layout.Gap { dot.X += theme.Margin() } if index > 0 && layout.Gap { dot.X += theme.Margin() }

View File

@ -50,9 +50,8 @@ func (layout Vertical) Arrange (entries []tomo.LayoutEntry, bounds image.Rectang
expandingElementHeight = freeSpace / expandingElements expandingElementHeight = freeSpace / expandingElements
} }
dot := bounds.Min
// set the size and position of each element // set the size and position of each element
dot := bounds.Min
for index, entry := range entries { for index, entry := range entries {
if index > 0 && layout.Gap { dot.Y += theme.Margin() } if index > 0 && layout.Gap { dot.Y += theme.Margin() }