From e7a42e05b51f5df9662e30e41e9c3dc4c6e5c1f3 Mon Sep 17 00:00:00 2001 From: Omar Date: Sun, 20 Oct 2019 13:02:14 +0200 Subject: [PATCH] chore: adjust ToDo to use ScrollableWidget --- checklist/checklist.go | 93 +++------------------------------------- modules/todo/display.go | 11 +++-- modules/todo/keyboard.go | 63 ++++++++++++++++++--------- modules/todo/widget.go | 47 ++++++++++++++++---- 4 files changed, 94 insertions(+), 120 deletions(-) diff --git a/checklist/checklist.go b/checklist/checklist.go index 4ff75a78..e3d336f5 100644 --- a/checklist/checklist.go +++ b/checklist/checklist.go @@ -48,9 +48,8 @@ func (list *Checklist) CheckedItems() []*ChecklistItem { } // 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() +func (list *Checklist) Delete(selectedIndex int) { + list.Items = append(list.Items[:selectedIndex], list.Items[selectedIndex+1:]...) } // IsSelectable returns true if the checklist has selectable items, false if it does not @@ -76,35 +75,14 @@ func (list *Checklist) LongestLine() int { 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) { +// IndexByItem returns the index of a giving item if found ,otherwise returns 0 with ok set to false +func (list *Checklist) IndexByItem(selectableItem *ChecklistItem) (index int, ok bool) { for idx, item := range list.Items { if item == selectableItem { - list.selected = idx - break + return idx, true } } -} - -// Toggle switches the checked state of the currently-selected item -func (list *Checklist) Toggle() { - if list.IsUnselectable() { - return - } - - list.SelectedItem().Toggle() + return 0, false } // UncheckedItems returns a slice of all the unchecked items @@ -125,65 +103,6 @@ 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-- - 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++ - 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 { diff --git a/modules/todo/display.go b/modules/todo/display.go index 8132ad91..ca577aee 100644 --- a/modules/todo/display.go +++ b/modules/todo/display.go @@ -20,19 +20,22 @@ func (widget *Widget) content() (string, string, bool) { ) offset := 0 - + selectedItem := widget.SelectedItem() for idx, item := range widget.list.UncheckedItems() { - str += widget.formattedItemLine(idx, item, widget.list.SelectedItem(), widget.list.LongestLine()) + str += widget.formattedItemLine(idx, item, selectedItem, widget.list.LongestLine()) newList.Items = append(newList.Items, item) offset++ } for idx, item := range widget.list.CheckedItems() { - str += widget.formattedItemLine(idx+offset, item, widget.list.SelectedItem(), widget.list.LongestLine()) + str += widget.formattedItemLine(idx+offset, item, selectedItem, widget.list.LongestLine()) newList.Items = append(newList.Items, item) } - newList.SetSelectedByItem(widget.list.SelectedItem()) + if idx, ok := newList.IndexByItem(selectedItem); ok { + widget.Selected = idx + } + widget.SetList(newList) return widget.CommonSettings().Title, str, false diff --git a/modules/todo/keyboard.go b/modules/todo/keyboard.go index a04962f7..8d2422ea 100644 --- a/modules/todo/keyboard.go +++ b/modules/todo/keyboard.go @@ -11,62 +11,85 @@ import ( func (widget *Widget) initializeKeyboardControls() { widget.InitializeCommonControls(widget.Refresh) - widget.SetKeyboardChar("j", widget.displayNext, "Select next item") - widget.SetKeyboardChar("k", widget.displayPrev, "Select previous item") + widget.SetKeyboardChar("j", widget.Next, "Select next item") + widget.SetKeyboardChar("k", widget.Prev, "Select previous item") widget.SetKeyboardChar(" ", widget.toggleChecked, "Toggle checkmark") widget.SetKeyboardChar("n", widget.newItem, "Create new item") widget.SetKeyboardChar("o", widget.openFile, "Open file") - widget.SetKeyboardKey(tcell.KeyDown, widget.displayNext, "Select next item") - widget.SetKeyboardKey(tcell.KeyUp, widget.displayPrev, "Select previous item") + widget.SetKeyboardKey(tcell.KeyDown, widget.Next, "Select next item") + widget.SetKeyboardKey(tcell.KeyUp, widget.Prev, "Select previous item") widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect, "Clear selection") widget.SetKeyboardKey(tcell.KeyCtrlD, widget.deleteSelected, "Delete item") widget.SetKeyboardKey(tcell.KeyCtrlJ, widget.demoteSelected, "Demote item") widget.SetKeyboardKey(tcell.KeyCtrlK, widget.promoteSelected, "Promote item") - widget.SetKeyboardKey(tcell.KeyEnter, widget.editSelected, "Edit item") + widget.SetKeyboardKey(tcell.KeyEnter, widget.updateSelected, "Edit item") } func (widget *Widget) deleteSelected() { - widget.list.Delete() + + if !widget.isItemSelected() { + return + } + + widget.list.Delete(widget.Selected) + widget.ScrollableWidget.SetItemCount(len(widget.list.Items)) + widget.Prev() widget.persist() widget.display() } func (widget *Widget) demoteSelected() { - widget.list.Demote() + if !widget.isItemSelected() { + return + } + + j := widget.Selected + 1 + if j >= len(widget.list.Items) { + j = 0 + } + + widget.list.Swap(widget.Selected, j) + widget.Selected = j + widget.persist() widget.display() } -func (widget *Widget) displayNext() { - widget.list.Next() - widget.display() -} - -func (widget *Widget) displayPrev() { - widget.list.Prev() - widget.display() -} - func (widget *Widget) openFile() { confDir, _ := cfg.WtfConfigDir() utils.OpenFile(fmt.Sprintf("%s/%s", confDir, widget.filePath)) } func (widget *Widget) promoteSelected() { - widget.list.Promote() + if !widget.isItemSelected() { + return + } + + k := widget.Selected - 1 + if k < 0 { + k = len(widget.list.Items) - 1 + } + + widget.list.Swap(widget.Selected, k) + widget.Selected = k widget.persist() widget.display() } func (widget *Widget) toggleChecked() { - widget.list.Toggle() + selectedItem := widget.SelectedItem() + if selectedItem == nil { + return + } + + selectedItem.Toggle() widget.persist() widget.display() } func (widget *Widget) unselect() { - widget.list.Unselect() + widget.Selected = -1 widget.display() } diff --git a/modules/todo/widget.go b/modules/todo/widget.go index dfbc357d..bc9c6cd3 100644 --- a/modules/todo/widget.go +++ b/modules/todo/widget.go @@ -23,7 +23,7 @@ const ( // A Widget represents a Todo widget type Widget struct { view.KeyboardWidget - view.TextWidget + view.ScrollableWidget app *tview.Application settings *Settings @@ -35,8 +35,8 @@ type Widget struct { // NewWidget creates a new instance of a widget func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ - KeyboardWidget: view.NewKeyboardWidget(app, pages, settings.common), - TextWidget: view.NewTextWidget(app, settings.common), + KeyboardWidget: view.NewKeyboardWidget(app, pages, settings.common), + ScrollableWidget: view.NewScrollableWidget(app, settings.common), app: app, settings: settings, @@ -54,6 +54,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) * widget.View.SetScrollable(true) widget.KeyboardWidget.SetView(widget.View) + widget.SetRenderFunction(widget.display) return &widget } @@ -75,18 +76,44 @@ func (widget *Widget) HelpText() string { /* -------------------- Unexported Functions -------------------- */ -// edit opens a modal dialog that permits editing the text of the currently-selected item -func (widget *Widget) editSelected() { - if widget.list.SelectedItem() == nil { +// isItemSelected returns weather any item of the todo is selected or not +func (widget *Widget) isItemSelected() bool { + + return widget.Selected >= 0 && widget.Selected < len(widget.list.Items) +} + +// SelectedItem returns the currently-selected checklist item or nil if no item is selected +func (widget *Widget) SelectedItem() *checklist.ChecklistItem { + var selectedItem *checklist.ChecklistItem + if widget.isItemSelected() { + selectedItem = widget.list.Items[widget.Selected] + } + + return selectedItem +} + +// updateSelectedItem update the text of the selected item. +func (widget *Widget) updateSelectedItem(text string) { + selectedItem := widget.SelectedItem() + if selectedItem == nil { return } - form := widget.modalForm("Edit:", widget.list.SelectedItem().Text) + selectedItem.Text = text +} + +// updateSelected sets the text of the currently-selected item to the provided text +func (widget *Widget) updateSelected() { + if !widget.isItemSelected() { + return + } + + form := widget.modalForm("Edit:", widget.SelectedItem().Text) saveFctn := func() { text := form.GetFormItem(0).(*tview.InputField).GetText() - widget.list.Update(text) + widget.updateSelectedItem(text) widget.persist() widget.pages.RemovePage("modal") widget.app.SetFocus(widget.View) @@ -104,7 +131,7 @@ func (widget *Widget) init() { } } -// Loads the todo list from Yaml file +// Loads the todo list from3 Yaml file func (widget *Widget) load() { confDir, _ := cfg.WtfConfigDir() filePath := fmt.Sprintf("%s/%s", confDir, widget.filePath) @@ -113,6 +140,7 @@ func (widget *Widget) load() { yaml.Unmarshal(fileData, &widget.list) + widget.ScrollableWidget.SetItemCount(len(widget.list.Items)) widget.setItemChecks() } @@ -123,6 +151,7 @@ func (widget *Widget) newItem() { text := form.GetFormItem(0).(*tview.InputField).GetText() widget.list.Add(false, text) + widget.SetItemCount(len(widget.list.Items)) widget.persist() widget.pages.RemovePage("modal") widget.app.SetFocus(widget.View)