mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
200 lines
4.2 KiB
Go
200 lines
4.2 KiB
Go
package checklist
|
|
|
|
// Checklist is a module for creating generic checklist implementations
|
|
// See 'Todo' for an implementation example
|
|
type Checklist struct {
|
|
Items []*ChecklistItem
|
|
|
|
checkedIcon string
|
|
selected int
|
|
uncheckedIcon string
|
|
}
|
|
|
|
func NewChecklist(checkedIcon, uncheckedIcon string) Checklist {
|
|
list := Checklist{
|
|
checkedIcon: checkedIcon,
|
|
selected: -1,
|
|
uncheckedIcon: uncheckedIcon,
|
|
}
|
|
|
|
return list
|
|
}
|
|
|
|
/* -------------------- Exported Functions -------------------- */
|
|
|
|
// Add creates a new item in the checklist
|
|
func (list *Checklist) Add(checked bool, text string) {
|
|
item := NewChecklistItem(
|
|
checked,
|
|
text,
|
|
list.checkedIcon,
|
|
list.uncheckedIcon,
|
|
)
|
|
|
|
list.Items = append([]*ChecklistItem{item}, list.Items...)
|
|
}
|
|
|
|
// CheckedItems returns a slice of all the checked items
|
|
func (list *Checklist) CheckedItems() []*ChecklistItem {
|
|
items := []*ChecklistItem{}
|
|
|
|
for _, item := range list.Items {
|
|
if item.Checked {
|
|
items = append(items, item)
|
|
}
|
|
}
|
|
|
|
return items
|
|
}
|
|
|
|
// Delete removes the selected item from the checklist
|
|
func (list *Checklist) Delete() {
|
|
list.Items = append(list.Items[:list.selected], list.Items[list.selected+1:]...)
|
|
list.Prev()
|
|
}
|
|
|
|
// IsSelectable returns true if the checklist has selectable items, false if it does not
|
|
func (list *Checklist) IsSelectable() bool {
|
|
return list.selected >= 0 && list.selected < len(list.Items)
|
|
}
|
|
|
|
// IsUnselectable returns true if the checklist has no selectable items, false if it does
|
|
func (list *Checklist) IsUnselectable() bool {
|
|
return !list.IsSelectable()
|
|
}
|
|
|
|
// LongestLine returns the length of the longest checklist item's text
|
|
func (list *Checklist) LongestLine() int {
|
|
maxLen := 0
|
|
|
|
for _, item := range list.Items {
|
|
if len(item.Text) > maxLen {
|
|
maxLen = len(item.Text)
|
|
}
|
|
}
|
|
|
|
return maxLen
|
|
}
|
|
|
|
func (list *Checklist) Selected() int {
|
|
return list.selected
|
|
}
|
|
|
|
// SelectedItem returns the currently-selected checklist item or nil if no item is selected
|
|
func (list *Checklist) SelectedItem() *ChecklistItem {
|
|
if list.IsUnselectable() {
|
|
return nil
|
|
}
|
|
|
|
return list.Items[list.selected]
|
|
}
|
|
|
|
func (list *Checklist) SetSelectedByItem(selectableItem *ChecklistItem) {
|
|
for idx, item := range list.Items {
|
|
if item == selectableItem {
|
|
list.selected = idx
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// Toggle switches the checked state of the currently-selected item
|
|
func (list *Checklist) Toggle() {
|
|
if list.IsUnselectable() {
|
|
return
|
|
}
|
|
|
|
list.SelectedItem().Toggle()
|
|
}
|
|
|
|
// UncheckedItems returns a slice of all the unchecked items
|
|
func (list *Checklist) UncheckedItems() []*ChecklistItem {
|
|
items := []*ChecklistItem{}
|
|
|
|
for _, item := range list.Items {
|
|
if !item.Checked {
|
|
items = append(items, item)
|
|
}
|
|
}
|
|
|
|
return items
|
|
}
|
|
|
|
// Unselect removes the current select such that no item is selected
|
|
func (list *Checklist) Unselect() {
|
|
list.selected = -1
|
|
}
|
|
|
|
// Update sets the text of the currently-selected item to the provided text
|
|
func (list *Checklist) Update(text string) {
|
|
item := list.SelectedItem()
|
|
|
|
if item == nil {
|
|
return
|
|
}
|
|
|
|
item.Text = text
|
|
}
|
|
|
|
/* -------------------- Item Movement -------------------- */
|
|
|
|
// Prev selects the previous item UP in the checklist
|
|
func (list *Checklist) Prev() {
|
|
list.selected = list.selected - 1
|
|
if list.selected < 0 {
|
|
list.selected = len(list.Items) - 1
|
|
}
|
|
}
|
|
|
|
// Next selects the next item DOWN in the checklist
|
|
func (list *Checklist) Next() {
|
|
list.selected = list.selected + 1
|
|
if list.selected >= len(list.Items) {
|
|
list.selected = 0
|
|
}
|
|
}
|
|
|
|
// Promote moves the selected item UP in the checklist
|
|
func (list *Checklist) Promote() {
|
|
if list.IsUnselectable() {
|
|
return
|
|
}
|
|
|
|
k := list.selected - 1
|
|
if k < 0 {
|
|
k = len(list.Items) - 1
|
|
}
|
|
|
|
list.Swap(list.selected, k)
|
|
list.selected = k
|
|
}
|
|
|
|
// Demote moves the selected item DOWN in the checklist
|
|
func (list *Checklist) Demote() {
|
|
if list.IsUnselectable() {
|
|
return
|
|
}
|
|
|
|
j := list.selected + 1
|
|
if j >= len(list.Items) {
|
|
j = 0
|
|
}
|
|
|
|
list.Swap(list.selected, j)
|
|
list.selected = j
|
|
}
|
|
|
|
/* -------------------- Sort Interface -------------------- */
|
|
|
|
func (list *Checklist) Len() int {
|
|
return len(list.Items)
|
|
}
|
|
|
|
func (list *Checklist) Less(i, j int) bool {
|
|
return list.Items[i].Text < list.Items[j].Text
|
|
}
|
|
|
|
func (list *Checklist) Swap(i, j int) {
|
|
list.Items[i], list.Items[j] = list.Items[j], list.Items[i]
|
|
}
|