diff options
author | Drew DeVault <sir@cmpwn.com> | 2019-01-13 15:10:47 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-01-13 15:10:47 -0500 |
commit | 3157897c1a20e5638feaf56e753b7886bc4ba267 (patch) | |
tree | d47b8ea1654a5627811df1e5ad5c5cfd172358fc /lib/ui/list.go | |
parent | 755aa9af731c6faac64cbe3ad77324fb2850a7ae (diff) |
Add abstract list, update dirlist accordingly
Diffstat (limited to 'lib/ui/list.go')
-rw-r--r-- | lib/ui/list.go | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/ui/list.go b/lib/ui/list.go new file mode 100644 index 0000000..58f304f --- /dev/null +++ b/lib/ui/list.go @@ -0,0 +1,110 @@ +package ui + +import ( + "fmt" +) + +// A container which arranges its children in a list. +type List struct { + Items []*ListItem + itemHeight int + onInvalidate func(d Drawable) + selected int +} + +type ListItem struct { + Content Drawable + invalid bool +} + +type SelectableDrawable interface { + Drawable + DrawWithSelected(ctx *Context, selected bool) +} + +func NewList() *List { + return &List{itemHeight: 1, selected: -1} +} + +func (list *List) OnInvalidate(onInvalidate func(d Drawable)) { + list.onInvalidate = onInvalidate +} + +func (list *List) Invalidate() { + for _, item := range list.Items { + item.Content.Invalidate() + } + if list.onInvalidate != nil { + list.onInvalidate(list) + } +} + +func (list *List) Draw(ctx *Context) { + for i, item := range list.Items { + if !item.invalid { + continue + } + subctx := ctx.Subcontext(0, i, ctx.Width(), list.itemHeight) + if content, ok := item.Content.(SelectableDrawable); ok { + content.DrawWithSelected(subctx, i == list.selected) + } else { + item.Content.Draw(subctx) + } + } +} + +func (list *List) Add(child Drawable) { + list.Items = append(list.Items, &ListItem{Content: child, invalid: true}) + child.OnInvalidate(list.childInvalidated) + list.Invalidate() +} + +func (list *List) Remove(child Drawable) { + for i, item := range list.Items { + if item.Content == child { + list.Items = append(list.Items[:i], list.Items[i+1:]...) + child.OnInvalidate(nil) + list.Invalidate() + return + } + } + panic(fmt.Errorf("Attempted to remove unknown child")) +} + +func (list *List) Set(items []Drawable) { + for _, item := range list.Items { + item.Content.OnInvalidate(nil) + } + list.Items = make([]*ListItem, len(items)) + for i, item := range items { + list.Items[i] = &ListItem{Content: item, invalid: true} + item.OnInvalidate(list.childInvalidated) + } + list.Invalidate() +} + +func (list *List) Select(index int) { + if index >= len(list.Items) || index < 0 { + panic(fmt.Errorf("Attempted to select unknown child")) + } + list.selected = index + list.Invalidate() +} + +func (list *List) ItemHeight(height int) { + list.itemHeight = height + list.Invalidate() +} + +func (list *List) childInvalidated(child Drawable) { + for _, item := range list.Items { + if item.Content == child { + item.invalid = true + if list.onInvalidate != nil { + list.onInvalidate(list) + } + return + } + } + panic(fmt.Errorf("Attempted to invalidate unknown child")) +} |