Various improvements to list

This commit is contained in:
Sasha Koshka 2023-01-23 23:54:12 -05:00
parent 24bcd6977a
commit 468d4e9dab
4 changed files with 103 additions and 31 deletions

View File

@ -11,11 +11,15 @@ import "git.tebibyte.media/sashakoshka/tomo/elements/core"
type List struct { type List struct {
*core.Core *core.Core
core core.CoreControl core core.CoreControl
enabled bool enabled bool
selected bool selected bool
pressed bool
contentHeight int contentHeight int
forcedMinimumWidth int forcedMinimumWidth int
forcedMinimumHeight int forcedMinimumHeight int
selectedEntry int selectedEntry int
scroll int scroll int
entries []ListEntry entries []ListEntry
@ -28,7 +32,7 @@ type List struct {
// NewList creates a new list element with the specified entries. // NewList creates a new list element with the specified entries.
func NewList (entries ...ListEntry) (element *List) { func NewList (entries ...ListEntry) (element *List) {
element = &List { } element = &List { enabled: true, selectedEntry: -1 }
element.Core, element.core = core.NewCore(element) element.Core, element.core = core.NewCore(element)
element.entries = make([]ListEntry, len(entries)) element.entries = make([]ListEntry, len(entries))
@ -71,16 +75,16 @@ func (element *List) HandleMouseDown (x, y int, button tomo.Button) {
if !element.enabled { return } if !element.enabled { return }
if !element.selected { element.Select() } if !element.selected { element.Select() }
if button != tomo.ButtonLeft { return } if button != tomo.ButtonLeft { return }
element.pressed = true
// if element.core.HasImage() { if element.selectUnderMouse(x, y) && element.core.HasImage() {
// element.draw() element.draw()
// element.core.DamageAll() element.core.DamageAll()
// } }
} }
func (element *List) HandleMouseUp (x, y int, button tomo.Button) { func (element *List) HandleMouseUp (x, y int, button tomo.Button) {
if button != tomo.ButtonLeft { return } if button != tomo.ButtonLeft { return }
// element.pressed = false element.pressed = false
// if element.core.HasImage() { // if element.core.HasImage() {
// element.draw() // element.draw()
// element.core.DamageAll() // element.core.DamageAll()
@ -95,7 +99,15 @@ func (element *List) HandleMouseUp (x, y int, button tomo.Button) {
// } // }
} }
func (element *List) HandleMouseMove (x, y int) { } func (element *List) HandleMouseMove (x, y int) {
if element.pressed {
if element.selectUnderMouse(x, y) && element.core.HasImage() {
element.draw()
element.core.DamageAll()
}
}
}
func (element *List) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *List) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *List) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *List) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
@ -324,6 +336,32 @@ func (element *List) Replace (index int, entry ListEntry) {
} }
} }
func (element *List) selectUnderMouse (x, y int) (updated bool) {
bounds := element.Bounds()
mousePoint := image.Pt(x, y)
dot := image.Pt (
bounds.Min.X + theme.Padding() / 2,
bounds.Min.Y - element.scroll + theme.Padding() / 2)
newlySelectedEntryIndex := -1
for index, entry := range element.entries {
entryPosition := dot
dot.Y += entry.Bounds().Dy()
if entryPosition.Y > bounds.Max.Y { break }
if mousePoint.In(entry.Bounds().Add(entryPosition)) {
newlySelectedEntryIndex = index
break
}
}
if element.selectedEntry == newlySelectedEntryIndex { return false }
element.selectedEntry = newlySelectedEntryIndex
if element.onSelectedEntryChange != nil {
element.onSelectedEntryChange(element.selectedEntry)
}
return true
}
func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) { func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) {
entry.Collapse(element.forcedMinimumWidth) entry.Collapse(element.forcedMinimumWidth)
return entry return entry
@ -332,7 +370,6 @@ func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) {
func (element *List) updateMinimumSize () { func (element *List) updateMinimumSize () {
element.contentHeight = 0 element.contentHeight = 0
for _, entry := range element.entries { for _, entry := range element.entries {
element.contentHeight += theme.Padding()
element.contentHeight += entry.Bounds().Dy() element.contentHeight += entry.Bounds().Dy()
} }
@ -340,11 +377,18 @@ func (element *List) updateMinimumSize () {
minimumHeight := element.forcedMinimumHeight minimumHeight := element.forcedMinimumHeight
if minimumWidth == 0 { if minimumWidth == 0 {
minimumWidth = theme.Padding()
for _, entry := range element.entries {
entryWidth := entry.Bounds().Dx()
if entryWidth > minimumWidth {
minimumWidth = entryWidth
}
}
minimumWidth += theme.Padding()
} }
if minimumHeight == 0 { if minimumHeight == 0 {
minimumHeight = element.contentHeight minimumHeight = element.contentHeight + theme.Padding() * 2
} }
element.core.SetMinimumSize(minimumWidth, minimumHeight) element.core.SetMinimumSize(minimumWidth, minimumHeight)
@ -359,27 +403,21 @@ func (element *List) draw () {
bounds) bounds)
dot := image.Point { dot := image.Point {
bounds.Min.X + theme.Padding(), bounds.Min.X,
bounds.Min.Y - element.scroll, bounds.Min.Y - element.scroll + theme.Padding() / 2,
} }
for index, entry := range element.entries { for index, entry := range element.entries {
dot.Y += theme.Padding()
entryPosition := dot entryPosition := dot
dot.Y += entry.Bounds().Dy() dot.Y += entry.Bounds().Dy()
if dot.Y < bounds.Min.Y { continue } if dot.Y < bounds.Min.Y { continue }
if entryPosition.Y > bounds.Max.Y { break } if entryPosition.Y > bounds.Max.Y { break }
selectionMarkerBounds := image.Rect ( if element.selectedEntry == index {
theme.Padding() / 2, artist.FillRectangle (
entryPosition.Y - theme.Padding() / 2, element,
bounds.Dx() - theme.Padding() / 2, theme.ListEntryPattern(true),
entryPosition.Y + entry.Bounds().Dy() + entry.Bounds().Add(entryPosition))
theme.Padding() / 2) }
artist.FillRectangle (
element,
theme.ListEntryPattern(element.selectedEntry == index),
selectionMarkerBounds)
entry.Draw ( entry.Draw (
element, entryPosition, element, entryPosition,
element.selectedEntry == index && element.selected) element.selectedEntry == index && element.selected)

View File

@ -33,13 +33,20 @@ func (entry *ListEntry) Collapse (width int) {
} }
func (entry *ListEntry) updateBounds () { func (entry *ListEntry) updateBounds () {
padding := theme.Padding()
entry.bounds = image.Rectangle { } entry.bounds = image.Rectangle { }
entry.bounds.Max.Y = entry.drawer.LineHeight().Round() entry.bounds.Max.Y = entry.drawer.LineHeight().Round() + padding
if entry.forcedMinimumWidth > 0 { if entry.forcedMinimumWidth > 0 {
entry.bounds.Max.X = entry.drawer.LayoutBounds().Dx() entry.bounds.Max.X = entry.forcedMinimumWidth
} else {
entry.bounds.Max.X =
entry.drawer.LayoutBounds().Dx() + padding * 2
} }
entry.textPoint = image.Pt(0, 0).Sub(entry.drawer.LayoutBounds().Min) entry.textPoint =
image.Pt(padding, padding / 2).
Sub(entry.drawer.LayoutBounds().Min)
} }
func (entry *ListEntry) Draw ( func (entry *ListEntry) Draw (

View File

@ -28,7 +28,7 @@ func (element *Artist) Resize (width, height int) {
element.core.AllocateCanvas(width, height) element.core.AllocateCanvas(width, height)
bounds := element.Bounds() bounds := element.Bounds()
element.cellBounds.Max.X = bounds.Dx() / 4 element.cellBounds.Max.X = bounds.Dx() / 4
element.cellBounds.Max.Y = (bounds.Dy() - 48) / 5 element.cellBounds.Max.Y = (bounds.Dy() - 48) / 6
drawStart := time.Now() drawStart := time.Now()
@ -128,6 +128,17 @@ func (element *Artist) Resize (width, height int) {
drawTime.Milliseconds(), drawTime.Milliseconds(),
drawTime.Microseconds()))) drawTime.Microseconds())))
textDrawer.Draw(element, uhex(0xFFFFFFFF), image.Pt(8, bounds.Max.Y - 24)) textDrawer.Draw(element, uhex(0xFFFFFFFF), image.Pt(8, bounds.Max.Y - 24))
// 0, 5
artist.FillRectangle (
element,
artist.QuadBeveled {
artist.NewUniform(hex(0x880000FF)),
artist.NewUniform(hex(0x00FF00FF)),
artist.NewUniform(hex(0x0000FFFF)),
artist.NewUniform(hex(0xFF00FFFF)),
},
element.cellAt(0, 5))
} }
func (element *Artist) lines (weight int, bounds image.Rectangle) { func (element *Artist) lines (weight int, bounds image.Rectangle) {

View File

@ -14,9 +14,25 @@ var listPattern = artist.NewMultiBordered (
artist.Stroke { Pattern: artist.NewUniform(hex(0x999C99FF)) }) artist.Stroke { Pattern: artist.NewUniform(hex(0x999C99FF)) })
var listEntryPattern = artist.NewUniform(hex(0x999C99FF)) var listEntryPattern = artist.NewMultiBordered (
artist.Stroke { Weight: 1, Pattern: artist.QuadBeveled {
artist.NewUniform(hex(0x999C99FF)),
strokePattern,
artist.NewUniform(hex(0x999C99FF)),
strokePattern,
}},
artist.Stroke { Pattern: artist.NewUniform(hex(0x999C99FF)) })
var selectedListEntryPattern = accentPattern var selectedListEntryPattern = artist.NewMultiBordered (
artist.Stroke { Weight: 1, Pattern: strokePattern },
artist.Stroke {
Weight: 1,
Pattern: artist.Beveled {
Highlight: artist.NewUniform(hex(0x3b534eFF)),
Shadow: artist.NewUniform(hex(0x97a09cFF)),
},
},
artist.Stroke { Pattern: artist.NewUniform(hex(0x97a09cFF)) })
func ListPattern () (pattern artist.Pattern) { func ListPattern () (pattern artist.Pattern) {
return listPattern return listPattern