1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00
wtf/modules/todo/widget.go
Sean Smith 7f3daaac59 Have keyboard widget manage its own help
Define help with keys
This means that keys and help are automatically in sync
This means that you can't define keys, but forget help
This unfortunately also means that formatting may not be quite as good
2019-05-11 12:15:52 -04:00

210 lines
5.0 KiB
Go

package todo
import (
"fmt"
"io/ioutil"
"github.com/gdamore/tcell"
"github.com/rivo/tview"
"github.com/wtfutil/wtf/cfg"
"github.com/wtfutil/wtf/checklist"
"github.com/wtfutil/wtf/wtf"
"gopkg.in/yaml.v2"
)
const offscreen = -1000
const modalWidth = 80
const modalHeight = 7
// A Widget represents a Todo widget
type Widget struct {
wtf.KeyboardWidget
wtf.TextWidget
app *tview.Application
settings *Settings
filePath string
list checklist.Checklist
pages *tview.Pages
}
// NewWidget creates a new instance of a widget
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
widget := Widget{
KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common),
TextWidget: wtf.NewTextWidget(app, settings.common, true),
app: app,
settings: settings,
filePath: settings.filePath,
list: checklist.NewChecklist(settings.common.Sigils.Checkbox.Checked, settings.common.Sigils.Checkbox.Unchecked),
pages: pages,
}
widget.init()
widget.initializeKeyboardControls()
widget.View.SetInputCapture(widget.InputCapture)
widget.View.SetRegions(true)
widget.View.SetScrollable(true)
widget.KeyboardWidget.SetView(widget.View)
return &widget
}
/* -------------------- Exported Functions -------------------- */
func (widget *Widget) Refresh() {
widget.load()
widget.display()
}
func (widget *Widget) SetList(list checklist.Checklist) {
widget.list = list
}
/* -------------------- 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 {
return
}
form := widget.modalForm("Edit:", widget.list.SelectedItem().Text)
saveFctn := func() {
text := form.GetFormItem(0).(*tview.InputField).GetText()
widget.list.Update(text)
widget.persist()
widget.pages.RemovePage("modal")
widget.app.SetFocus(widget.View)
widget.display()
}
widget.addButtons(form, saveFctn)
widget.modalFocus(form)
}
func (widget *Widget) init() {
_, err := cfg.CreateFile(widget.filePath)
if err != nil {
panic(err)
}
}
// Loads the todo list from Yaml file
func (widget *Widget) load() {
confDir, _ := cfg.ConfigDir()
filePath := fmt.Sprintf("%s/%s", confDir, widget.filePath)
fileData, _ := wtf.ReadFileBytes(filePath)
yaml.Unmarshal(fileData, &widget.list)
widget.setItemChecks()
}
func (widget *Widget) newItem() {
form := widget.modalForm("New Todo:", "")
saveFctn := func() {
text := form.GetFormItem(0).(*tview.InputField).GetText()
widget.list.Add(false, text)
widget.persist()
widget.pages.RemovePage("modal")
widget.app.SetFocus(widget.View)
widget.display()
}
widget.addButtons(form, saveFctn)
widget.modalFocus(form)
widget.app.QueueUpdate(func() {
widget.app.Draw()
})
}
// persist writes the todo list to Yaml file
func (widget *Widget) persist() {
confDir, _ := cfg.ConfigDir()
filePath := fmt.Sprintf("%s/%s", confDir, widget.filePath)
fileData, _ := yaml.Marshal(&widget.list)
err := ioutil.WriteFile(filePath, fileData, 0644)
if err != nil {
panic(err)
}
}
// setItemChecks rolls through the checklist and ensures that all checklist
// items have the correct checked/unchecked icon per the user's preferences
func (widget *Widget) setItemChecks() {
for _, item := range widget.list.Items {
item.CheckedIcon = widget.settings.common.Checkbox.Checked
item.UncheckedIcon = widget.settings.common.Checkbox.Unchecked
}
}
/* -------------------- Modal Form -------------------- */
func (widget *Widget) addButtons(form *tview.Form, saveFctn func()) {
widget.addSaveButton(form, saveFctn)
widget.addCancelButton(form)
}
func (widget *Widget) addCancelButton(form *tview.Form) {
cancelFn := func() {
widget.pages.RemovePage("modal")
widget.app.SetFocus(widget.View)
widget.display()
}
form.AddButton("Cancel", cancelFn)
form.SetCancelFunc(cancelFn)
}
func (widget *Widget) addSaveButton(form *tview.Form, fctn func()) {
form.AddButton("Save", fctn)
}
func (widget *Widget) modalFocus(form *tview.Form) {
widget.app.QueueUpdateDraw(func() {
frame := widget.modalFrame(form)
widget.pages.AddPage("modal", frame, false, true)
widget.app.SetFocus(frame)
})
}
func (widget *Widget) modalForm(lbl, text string) *tview.Form {
form := tview.NewForm().SetFieldBackgroundColor(wtf.ColorFor(widget.settings.common.Colors.Background))
form.SetButtonsAlign(tview.AlignCenter).SetButtonTextColor(wtf.ColorFor(widget.settings.common.Colors.Text))
form.AddInputField(lbl, text, 60, nil, nil)
return form
}
func (widget *Widget) modalFrame(form *tview.Form) *tview.Frame {
frame := tview.NewFrame(form).SetBorders(0, 0, 0, 0, 0, 0)
frame.SetRect(offscreen, offscreen, modalWidth, modalHeight)
frame.SetBorder(true)
frame.SetBorders(1, 1, 0, 0, 1, 1)
drawFunc := func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
w, h := screen.Size()
frame.SetRect((w/2)-(width/2), (h/2)-(height/2), width, height)
return x, y, width, height
}
frame.SetDrawFunc(drawFunc)
return frame
}