mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
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
210 lines
5.0 KiB
Go
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
|
|
}
|