Working on Tag Editor
This commit is contained in:
parent
36d24ee5d3
commit
56f12e4a58
@ -12,6 +12,13 @@ import (
|
|||||||
"github.com/nsf/termbox-go"
|
"github.com/nsf/termbox-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
activeToggleActive = iota
|
||||||
|
activeToggleInactive
|
||||||
|
activeToggleAll
|
||||||
|
activeToggleErr
|
||||||
|
)
|
||||||
|
|
||||||
type listTimersScreen struct {
|
type listTimersScreen struct {
|
||||||
ui *Ui
|
ui *Ui
|
||||||
|
|
||||||
@ -21,10 +28,12 @@ type listTimersScreen struct {
|
|||||||
|
|
||||||
cursor int
|
cursor int
|
||||||
|
|
||||||
fullList *timertxt.TimerList
|
activeToggle int
|
||||||
timerList *timertxt.TimerList
|
fullList *timertxt.TimerList
|
||||||
doneList *timertxt.TimerList
|
timerList *timertxt.TimerList
|
||||||
|
doneList *timertxt.TimerList
|
||||||
|
|
||||||
|
fullFilterList *timertxt.TimerList
|
||||||
timerFilterList *timertxt.TimerList
|
timerFilterList *timertxt.TimerList
|
||||||
doneFilterList *timertxt.TimerList
|
doneFilterList *timertxt.TimerList
|
||||||
|
|
||||||
@ -33,7 +42,9 @@ type listTimersScreen struct {
|
|||||||
inputDialog *widdles.InputDialog
|
inputDialog *widdles.InputDialog
|
||||||
filter string
|
filter string
|
||||||
|
|
||||||
partManager *PartManager
|
choiceMenu *widdles.MenuV
|
||||||
|
tagEditor *PromptForTagWiddle
|
||||||
|
//partManager *PartManager
|
||||||
|
|
||||||
msg string
|
msg string
|
||||||
err error
|
err error
|
||||||
@ -49,7 +60,9 @@ func NewListTimersScreen(u *Ui) *listTimersScreen {
|
|||||||
scrollbar: widdles.NewScrollbar(w-2, 2, 1, h-2),
|
scrollbar: widdles.NewScrollbar(w-2, 2, 1, h-2),
|
||||||
selected: make(map[int]bool),
|
selected: make(map[int]bool),
|
||||||
inputDialog: widdles.NewInputDialog("", ""),
|
inputDialog: widdles.NewInputDialog("", ""),
|
||||||
partManager: NewPartManager("", 0, 0, 0, 0),
|
|
||||||
|
choiceMenu: widdles.NewMenuV(0, 0, 0, 0),
|
||||||
|
tagEditor: NewPromptForTagWiddle(0, 0, widdles.AUTO_SIZE, widdles.AUTO_SIZE, "", ""),
|
||||||
}
|
}
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
@ -74,14 +87,23 @@ func (s *listTimersScreen) Init() wandle.Cmd {
|
|||||||
s.fullList = timertxt.NewTimerList()
|
s.fullList = timertxt.NewTimerList()
|
||||||
s.fullList.AddTimers(s.timerList.GetTimerSlice())
|
s.fullList.AddTimers(s.timerList.GetTimerSlice())
|
||||||
s.fullList.AddTimers(s.doneList.GetTimerSlice())
|
s.fullList.AddTimers(s.doneList.GetTimerSlice())
|
||||||
|
s.fullFilterList = s.fullList
|
||||||
s.timerFilterList, s.doneFilterList = s.timerList, s.doneList
|
s.timerFilterList, s.doneFilterList = s.timerList, s.doneList
|
||||||
|
s.fullFilterList.Sort(timertxt.SORT_START_DATE_DESC)
|
||||||
s.timerFilterList.Sort(timertxt.SORT_START_DATE_DESC)
|
s.timerFilterList.Sort(timertxt.SORT_START_DATE_DESC)
|
||||||
s.doneFilterList.Sort(timertxt.SORT_START_DATE_DESC)
|
s.doneFilterList.Sort(timertxt.SORT_START_DATE_DESC)
|
||||||
w, h := termbox.Size()
|
w, h := termbox.Size()
|
||||||
s.partManager.SetX(w / 4)
|
s.choiceMenu.SetBorder(wandle.BRD_CSIMPLE)
|
||||||
s.partManager.SetY(h / 4)
|
s.choiceMenu.SetX((w / 2) - 7)
|
||||||
s.partManager.SetWidth(w / 2)
|
s.choiceMenu.SetY((h / 2) - 7)
|
||||||
s.partManager.SetHeight(h / 2)
|
s.choiceMenu.SetWidth(widdles.AUTO_SIZE)
|
||||||
|
s.choiceMenu.SetHeight(widdles.AUTO_SIZE)
|
||||||
|
s.choiceMenu.SetPadding(0, 1, 0, 1)
|
||||||
|
s.tagEditor.SetX(w / 4)
|
||||||
|
s.tagEditor.SetY(h / 4)
|
||||||
|
s.tagEditor.SetWidth(w / 2)
|
||||||
|
s.tagEditor.SetHeight(h / 2)
|
||||||
|
s.updateFullFilterList()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -98,44 +120,50 @@ func (s *listTimersScreen) Update(msg wandle.Msg) wandle.Cmd {
|
|||||||
func (s *listTimersScreen) View(style wandle.Style) {
|
func (s *listTimersScreen) View(style wandle.Style) {
|
||||||
_, h := termbox.Size()
|
_, h := termbox.Size()
|
||||||
y := 2
|
y := 2
|
||||||
wandle.Print(1, y, style.Bold(true), "Active Timers")
|
printedTimers := 0
|
||||||
y++
|
if s.activeToggle == activeToggleAll || s.activeToggle == activeToggleActive {
|
||||||
for idx, tmr := range s.timerFilterList.GetTimerSlice() {
|
wandle.Print(1, y, style.Bold(true), "Active Timers")
|
||||||
if y > h-2 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
st := style
|
|
||||||
if s.cursor == idx {
|
|
||||||
st = st.Invert()
|
|
||||||
}
|
|
||||||
if s.selected[idx] {
|
|
||||||
wandle.Print(1, y, st, "[✔] ")
|
|
||||||
} else {
|
|
||||||
wandle.Print(1, y, st, "[ ] ")
|
|
||||||
}
|
|
||||||
s.ViewTimer(5, y, st, tmr)
|
|
||||||
y++
|
y++
|
||||||
}
|
for idx, tmr := range s.timerFilterList.GetTimerSlice() {
|
||||||
y++
|
if y > h-2 {
|
||||||
wandle.Print(1, y, style.Bold(true), "Done Timers")
|
break
|
||||||
y++
|
}
|
||||||
for idx, tmr := range s.doneFilterList.GetTimerSlice() {
|
st := style
|
||||||
if y > h-3 {
|
if s.cursor == idx {
|
||||||
break
|
st = st.Invert()
|
||||||
|
}
|
||||||
|
if s.selected[idx] {
|
||||||
|
wandle.Print(1, y, st, "[✔] ")
|
||||||
|
} else {
|
||||||
|
wandle.Print(1, y, st, "[ ] ")
|
||||||
|
}
|
||||||
|
s.ViewTimer(5, y, st, tmr)
|
||||||
|
y++
|
||||||
}
|
}
|
||||||
st := style
|
|
||||||
if s.cursor == s.timerFilterList.Size()+idx {
|
|
||||||
st = st.Invert()
|
|
||||||
}
|
|
||||||
if s.selected[s.timerFilterList.Size()+idx] {
|
|
||||||
wandle.Print(1, y, st, "[✔] ")
|
|
||||||
} else {
|
|
||||||
wandle.Print(1, y, st, "[ ] ")
|
|
||||||
}
|
|
||||||
s.ViewTimer(5, y, st, tmr)
|
|
||||||
y++
|
y++
|
||||||
|
printedTimers = s.timerFilterList.Size()
|
||||||
}
|
}
|
||||||
wandle.Print(1, h-1, style, "[p]roject(+), [c]ontext(@), [t]ags(:)")
|
if s.activeToggle == activeToggleAll || s.activeToggle == activeToggleInactive {
|
||||||
|
wandle.Print(1, y, style.Bold(true), "Done Timers")
|
||||||
|
y++
|
||||||
|
for idx, tmr := range s.doneFilterList.GetTimerSlice() {
|
||||||
|
if y > h-3 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
st := style
|
||||||
|
if s.cursor == printedTimers+idx {
|
||||||
|
st = st.Invert()
|
||||||
|
}
|
||||||
|
if s.selected[printedTimers+idx] {
|
||||||
|
wandle.Print(1, y, st, "[✔] ")
|
||||||
|
} else {
|
||||||
|
wandle.Print(1, y, st, "[ ] ")
|
||||||
|
}
|
||||||
|
s.ViewTimer(5, y, st, tmr)
|
||||||
|
y++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wandle.Print(1, h-1, style, "[A]ctive toggle, [p]roject(+), [c]ontext(@), [t]ags(:)")
|
||||||
if len(s.selected) > 0 {
|
if len(s.selected) > 0 {
|
||||||
wandle.Print(39, h-1, style, fmt.Sprintf("(%d selected)", len(s.selected)))
|
wandle.Print(39, h-1, style, fmt.Sprintf("(%d selected)", len(s.selected)))
|
||||||
}
|
}
|
||||||
@ -144,7 +172,13 @@ func (s *listTimersScreen) View(style wandle.Style) {
|
|||||||
if s.menu.IsActive() {
|
if s.menu.IsActive() {
|
||||||
s.menu.View(style)
|
s.menu.View(style)
|
||||||
}
|
}
|
||||||
s.partManager.View(style)
|
if s.choiceMenu.IsActive() {
|
||||||
|
s.choiceMenu.View(style)
|
||||||
|
}
|
||||||
|
if s.tagEditor.IsActive() {
|
||||||
|
s.tagEditor.View(style)
|
||||||
|
}
|
||||||
|
wandle.Print(1, h-2, style, s.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *listTimersScreen) ViewTimer(x, y int, style wandle.Style, tmr *timertxt.Timer) {
|
func (s *listTimersScreen) ViewTimer(x, y int, style wandle.Style, tmr *timertxt.Timer) {
|
||||||
@ -157,26 +191,19 @@ func (s *listTimersScreen) ViewTimer(x, y int, style wandle.Style, tmr *timertxt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||||
if pmRes := s.partManager.Update(msg); pmRes != nil {
|
if s.choiceMenu.IsActive() {
|
||||||
return pmRes
|
return s.choiceMenu.Update(msg)
|
||||||
|
}
|
||||||
|
if s.tagEditor.IsActive() {
|
||||||
|
return s.tagEditor.Update(msg)
|
||||||
}
|
}
|
||||||
if (msg.Type == termbox.EventKey && msg.Key == termbox.KeyEsc) || s.menu.IsActive() {
|
if (msg.Type == termbox.EventKey && msg.Key == termbox.KeyEsc) || s.menu.IsActive() {
|
||||||
return s.menu.Update(msg)
|
return s.menu.Update(msg)
|
||||||
}
|
}
|
||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
case termbox.EventKey:
|
case termbox.EventKey:
|
||||||
top := s.timerFilterList.Size() + s.doneFilterList.Size() - 2
|
|
||||||
selected := len(s.selected)
|
|
||||||
var selTimer *timertxt.Timer
|
|
||||||
if selected == 0 {
|
|
||||||
if s.cursor < s.timerFilterList.Size() {
|
|
||||||
selTimer, s.err = s.timerFilterList.GetTimer(s.cursor)
|
|
||||||
} else {
|
|
||||||
selTimer, s.err = s.doneFilterList.GetTimer(s.cursor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if msg.Key == termbox.KeyEnter {
|
if msg.Key == termbox.KeyEnter {
|
||||||
// Edit the entry
|
// TODO: Edit the entry
|
||||||
/*
|
/*
|
||||||
if s.cursor >= 0 && s.cursor < s.timerFilterList.Size()+s.doneFilterList.Size() {
|
if s.cursor >= 0 && s.cursor < s.timerFilterList.Size()+s.doneFilterList.Size() {
|
||||||
} else {
|
} else {
|
||||||
@ -189,6 +216,12 @@ func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
|||||||
} else {
|
} else {
|
||||||
s.selected[s.cursor] = true
|
s.selected[s.cursor] = true
|
||||||
}
|
}
|
||||||
|
if s.cursor < s.fullFilterList.Size()-1 {
|
||||||
|
s.cursor++
|
||||||
|
}
|
||||||
|
} else if msg.Ch == 'A' {
|
||||||
|
s.activeToggle = (s.activeToggle + 1) % activeToggleErr
|
||||||
|
s.updateFullFilterList()
|
||||||
} else if msg.Key == termbox.KeyArrowUp || msg.Ch == 'k' {
|
} else if msg.Key == termbox.KeyArrowUp || msg.Ch == 'k' {
|
||||||
if s.cursor > 0 {
|
if s.cursor > 0 {
|
||||||
s.cursor--
|
s.cursor--
|
||||||
@ -197,60 +230,172 @@ func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
} else if msg.Key == termbox.KeyArrowDown || msg.Ch == 'j' {
|
} else if msg.Key == termbox.KeyArrowDown || msg.Ch == 'j' {
|
||||||
if s.cursor < top {
|
if s.cursor < s.fullFilterList.Size()-1 {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
} else {
|
} else {
|
||||||
s.cursor = top
|
s.cursor = s.fullFilterList.Size() - 1
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
} else if msg.Ch == 'G' {
|
} else if msg.Ch == 'G' {
|
||||||
s.cursor = top
|
s.cursor = s.fullFilterList.Size() - 1
|
||||||
} else if msg.Ch == 't' {
|
} else if msg.Ch == 't' {
|
||||||
// Edit tag(s)
|
// Edit tag(s)
|
||||||
tags := s.fullList.GetTagKeys()
|
return s.showEditTagsChoice()
|
||||||
s.partManager.SetOptions(tags)
|
|
||||||
if selected > 0 {
|
|
||||||
// TODO
|
|
||||||
//s.partManager.SetLabel(fmt.Sprintf("Manage Tags on %d Timers", selected))
|
|
||||||
} else {
|
|
||||||
s.partManager.SetLabel("Manage Tags for Timer")
|
|
||||||
s.partManager.SetType("Tag")
|
|
||||||
}
|
|
||||||
s.partManager.Show()
|
|
||||||
} else if msg.Ch == 'p' {
|
} else if msg.Ch == 'p' {
|
||||||
// Edit project(s)
|
// Edit project(s)
|
||||||
|
// TODO: Prompt for Choice: Add/Edit/Remove
|
||||||
projs := s.fullList.GetProjects()
|
projs := s.fullList.GetProjects()
|
||||||
s.partManager.SetOptions(projs)
|
_ = projs
|
||||||
if selected > 0 {
|
|
||||||
// TODO
|
|
||||||
//s.partManager.SetLabel(fmt.Sprintf("Manage Projects on %d Timers", selected))
|
|
||||||
} else {
|
|
||||||
s.partManager.SetLabel("Manage Projects for Timer")
|
|
||||||
s.partManager.SetType("Project")
|
|
||||||
s.partManager.SetValue(strings.Join(selTimer.Projects, " "))
|
|
||||||
}
|
|
||||||
s.partManager.Show()
|
|
||||||
} else if msg.Ch == 'c' {
|
} else if msg.Ch == 'c' {
|
||||||
// Edit context(s)
|
// Edit context(s)
|
||||||
|
// TODO: Prompt for choice: Add/Edit/Remove
|
||||||
ctxts := s.fullList.GetContexts()
|
ctxts := s.fullList.GetContexts()
|
||||||
s.partManager.SetOptions(ctxts)
|
_ = ctxts
|
||||||
if selected > 0 {
|
|
||||||
// TODO
|
|
||||||
//s.partManager.SetLabel(fmt.Sprintf("Manage Contexts on %d Timers", selected))
|
|
||||||
} else {
|
|
||||||
s.partManager.SetLabel("Manage Contexts for Timer")
|
|
||||||
s.partManager.SetType("Context")
|
|
||||||
s.partManager.SetValue(strings.Join(selTimer.Contexts, " "))
|
|
||||||
}
|
|
||||||
s.partManager.Show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *listTimersScreen) showEditTagsChoice() wandle.Cmd {
|
||||||
|
tags := s.getSelectedTimerTags()
|
||||||
|
var showTagEditor = func(key, val string) wandle.Cmd {
|
||||||
|
return func() wandle.Msg {
|
||||||
|
s.tagEditor.SetTag(key, val)
|
||||||
|
// TODO: Set Done & Cancel Commands
|
||||||
|
s.choiceMenu.SetActive(false)
|
||||||
|
s.tagEditor.SetActive(true)
|
||||||
|
return wandle.EmptyCmd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.choiceMenu.SetTitle("")
|
||||||
|
s.choiceMenu.ClearOptions()
|
||||||
|
addTag := widdles.NewMenuItem("Add New Tag")
|
||||||
|
addTag.SetCommand(showTagEditor("", ""))
|
||||||
|
s.choiceMenu.AddOption(addTag)
|
||||||
|
editTag := widdles.NewMenuItem("Edit Tag")
|
||||||
|
editTag.SetEnabled(len(tags) > 0)
|
||||||
|
editTag.SetCommand(func() wandle.Msg {
|
||||||
|
s.choiceMenu.ClearOptions()
|
||||||
|
s.choiceMenu.SetTitle("Choose Tag to Edit")
|
||||||
|
for k, v := range tags {
|
||||||
|
var vals string
|
||||||
|
if len(v) == 1 {
|
||||||
|
vals = v[0]
|
||||||
|
} else {
|
||||||
|
vals = "..."
|
||||||
|
}
|
||||||
|
opt := widdles.NewMenuItem(fmt.Sprintf("%s (%s)", k, vals))
|
||||||
|
opt.SetCommand(showTagEditor(k, vals))
|
||||||
|
s.choiceMenu.AddOption(opt)
|
||||||
|
}
|
||||||
|
return wandle.EmptyCmd
|
||||||
|
})
|
||||||
|
s.choiceMenu.AddOption(editTag)
|
||||||
|
removeTag := widdles.NewMenuItem("Remove Tag")
|
||||||
|
removeTag.SetCommand(func() wandle.Msg {
|
||||||
|
s.choiceMenu.ClearOptions()
|
||||||
|
s.choiceMenu.SetTitle("Choose Tag to Remove")
|
||||||
|
return wandle.EmptyCmd
|
||||||
|
})
|
||||||
|
s.choiceMenu.AddOption(removeTag)
|
||||||
|
s.choiceMenu.SetActive(true)
|
||||||
|
//tags := s.fullList.GetTagKeys()
|
||||||
|
//_ = tags
|
||||||
|
return wandle.EmptyCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *listTimersScreen) updateFullFilterList() {
|
||||||
|
s.fullFilterList = timertxt.NewTimerList()
|
||||||
|
switch s.activeToggle {
|
||||||
|
case activeToggleAll:
|
||||||
|
s.fullFilterList.Combine(s.timerFilterList)
|
||||||
|
s.fullFilterList.Combine(s.doneFilterList)
|
||||||
|
case activeToggleActive:
|
||||||
|
s.fullFilterList.Combine(s.timerFilterList)
|
||||||
|
case activeToggleInactive:
|
||||||
|
s.fullFilterList.Combine(s.doneFilterList)
|
||||||
|
}
|
||||||
|
if s.cursor >= s.fullFilterList.Size() {
|
||||||
|
s.cursor = s.fullFilterList.Size() - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *listTimersScreen) gotoSettingsScreen() wandle.Msg {
|
func (s *listTimersScreen) gotoSettingsScreen() wandle.Msg {
|
||||||
return ScreenMsg{
|
return ScreenMsg{
|
||||||
source: ListTimersId,
|
source: ListTimersId,
|
||||||
command: CmdGotoSettings,
|
command: CmdGotoSettings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *listTimersScreen) getSelectedTimerTags() map[string][]string {
|
||||||
|
ret := make(map[string][]string)
|
||||||
|
selected := len(s.selected)
|
||||||
|
var selTimer *timertxt.Timer
|
||||||
|
if selected == 0 {
|
||||||
|
if s.cursor < s.fullFilterList.Size() {
|
||||||
|
selTimer, s.err = s.fullFilterList.GetTimer(s.cursor)
|
||||||
|
for k, v := range selTimer.AdditionalTags {
|
||||||
|
ret[k] = []string{v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range s.selected {
|
||||||
|
if tmr, err := s.fullFilterList.GetTimer(i); err == nil {
|
||||||
|
for k, v := range tmr.AdditionalTags {
|
||||||
|
if !util.StringSliceContains(ret[k], v) {
|
||||||
|
ret[k] = append(ret[k], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func (s *listTimersScreen) getSelectedTimerProjects() []string {
|
||||||
|
var ret []string
|
||||||
|
selected := len(s.selected)
|
||||||
|
var selTimer *timertxt.Timer
|
||||||
|
if selected == 0 {
|
||||||
|
if s.cursor < s.fullFilterList.Size() {
|
||||||
|
selTimer, s.err = s.fullFilterList.GetTimer(s.cursor)
|
||||||
|
for _, v := range selTimer.Projects {
|
||||||
|
ret = append(ret, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range s.selected {
|
||||||
|
if tmr, err := s.fullFilterList.GetTimer(i); err == nil {
|
||||||
|
for _, v := range tmr.Projects {
|
||||||
|
if !util.StringSliceContains(ret, v) {
|
||||||
|
ret = append(ret, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func (s *listTimersScreen) getSelectedTimerContexts() []string {
|
||||||
|
var ret []string
|
||||||
|
selected := len(s.selected)
|
||||||
|
var selTimer *timertxt.Timer
|
||||||
|
if selected == 0 {
|
||||||
|
if s.cursor < s.fullFilterList.Size() {
|
||||||
|
selTimer, s.err = s.fullFilterList.GetTimer(s.cursor)
|
||||||
|
for _, v := range selTimer.Contexts {
|
||||||
|
ret = append(ret, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range s.selected {
|
||||||
|
if tmr, err := s.fullFilterList.GetTimer(i); err == nil {
|
||||||
|
for _, v := range tmr.Contexts {
|
||||||
|
if !util.StringSliceContains(ret, v) {
|
||||||
|
ret = append(ret, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
195
ui/widdle_addtagtotimers.go
Normal file
195
ui/widdle_addtagtotimers.go
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.bullercodeworks.com/brian/wandle"
|
||||||
|
"git.bullercodeworks.com/brian/widdles"
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A widdle to prompt the user for a tag key and value
|
||||||
|
*/
|
||||||
|
type PromptForTagWiddle struct {
|
||||||
|
active bool
|
||||||
|
x, y, w, h int
|
||||||
|
|
||||||
|
origKey, origVal string
|
||||||
|
|
||||||
|
keyInput *widdles.ToggleField
|
||||||
|
valInput *widdles.ToggleField
|
||||||
|
|
||||||
|
cancelButton *widdles.Button
|
||||||
|
doneButton *widdles.Button
|
||||||
|
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ widdles.Widdle = (*PromptForTagWiddle)(nil)
|
||||||
|
|
||||||
|
func NewPromptForTagWiddle(x, y, w, h int, key, val string) *PromptForTagWiddle {
|
||||||
|
keyInp := widdles.NewToggleField("Key", key, 0, 0, 0, 0)
|
||||||
|
keyInp.SetActive(true)
|
||||||
|
return &PromptForTagWiddle{
|
||||||
|
x: x, y: y, w: w, h: h,
|
||||||
|
origKey: key, origVal: val,
|
||||||
|
keyInput: keyInp,
|
||||||
|
valInput: widdles.NewToggleField("Value", val, 0, 0, 0, 0),
|
||||||
|
cancelButton: widdles.NewButton("Cancel", 0, 0, 0, 0),
|
||||||
|
doneButton: widdles.NewButton("Done", 0, 0, 0, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PromptForTagWiddle) Init() wandle.Cmd {
|
||||||
|
return func() wandle.Msg {
|
||||||
|
w.Measure()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) Update(msg wandle.Msg) wandle.Cmd {
|
||||||
|
if w.active {
|
||||||
|
// Make sure a widdle is active
|
||||||
|
var found bool
|
||||||
|
for _, wdl := range []widdles.Widdle{w.keyInput, w.valInput, w.cancelButton, w.doneButton} {
|
||||||
|
if wdl.IsActive() {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
w.keyInput.SetActive(true)
|
||||||
|
}
|
||||||
|
if msg, ok := msg.(termbox.Event); ok {
|
||||||
|
return w.handleTermboxEvent(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) View(style wandle.Style) {
|
||||||
|
title := "Add Tag"
|
||||||
|
if w.origKey != "" {
|
||||||
|
title = "Edit Tag"
|
||||||
|
}
|
||||||
|
wandle.TitledBorderFilled(title, w.x, w.y, w.x+w.w, w.y+w.h, style, wandle.BRD_CSIMPLE)
|
||||||
|
w.keyInput.View(style)
|
||||||
|
w.valInput.View(style)
|
||||||
|
w.cancelButton.View(style)
|
||||||
|
w.doneButton.View(style)
|
||||||
|
wandle.Print(w.x+1, w.y+w.h-2, style, w.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PromptForTagWiddle) IsActive() bool { return w.active }
|
||||||
|
func (w *PromptForTagWiddle) SetActive(b bool) { w.active = b }
|
||||||
|
func (w *PromptForTagWiddle) Focusable() bool { return true }
|
||||||
|
func (w *PromptForTagWiddle) SetX(x int) {
|
||||||
|
w.x = x
|
||||||
|
w.Measure()
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) GetX() int { return w.x }
|
||||||
|
func (w *PromptForTagWiddle) SetY(y int) {
|
||||||
|
w.y = y
|
||||||
|
w.Measure()
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) GetY() int { return w.y }
|
||||||
|
func (w *PromptForTagWiddle) SetHeight(h int) {
|
||||||
|
w.h = h
|
||||||
|
w.Measure()
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) GetHeight() int {
|
||||||
|
//if w.h == widdles.AUTO_SIZE { }
|
||||||
|
return w.h
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) SetWidth(v int) {
|
||||||
|
w.w = v
|
||||||
|
w.Measure()
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) GetWidth() int {
|
||||||
|
//if w.w == widdles.AUTO_SIZE { }
|
||||||
|
return w.w
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) Measure() {
|
||||||
|
w.keyInput.SetX(w.x + 1)
|
||||||
|
w.keyInput.SetY(w.y + 1)
|
||||||
|
w.keyInput.SetWidth(w.w - 2)
|
||||||
|
w.keyInput.SetHeight(1)
|
||||||
|
|
||||||
|
w.valInput.SetX(w.x + 1)
|
||||||
|
w.valInput.SetY(w.y + 2)
|
||||||
|
w.valInput.SetWidth(w.w - 2)
|
||||||
|
w.valInput.SetHeight(1)
|
||||||
|
|
||||||
|
w.doneButton.SetX(w.x + w.w - 9)
|
||||||
|
w.doneButton.SetY(w.y + w.h - 1)
|
||||||
|
w.doneButton.SetWidth(8)
|
||||||
|
w.doneButton.SetHeight(1)
|
||||||
|
|
||||||
|
w.cancelButton.SetX(w.doneButton.GetX() - 12)
|
||||||
|
w.cancelButton.SetY(w.y + w.h - 1)
|
||||||
|
w.cancelButton.SetWidth(10)
|
||||||
|
w.cancelButton.SetHeight(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PromptForTagWiddle) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||||
|
if msg.Key == termbox.KeyEnter {
|
||||||
|
if w.keyInput.IsEditable() {
|
||||||
|
w.keyInput.SetActive(false)
|
||||||
|
w.keyInput.SetEditable(false)
|
||||||
|
w.valInput.SetActive(true)
|
||||||
|
w.valInput.SetEditable(true)
|
||||||
|
return wandle.EmptyCmd
|
||||||
|
} else if w.valInput.IsEditable() {
|
||||||
|
w.valInput.SetActive(false)
|
||||||
|
w.valInput.SetEditable(false)
|
||||||
|
if w.keyInput.GetValue() != "" && w.valInput.GetValue() != "" {
|
||||||
|
w.doneButton.SetActive(true)
|
||||||
|
} else {
|
||||||
|
w.cancelButton.SetActive(true)
|
||||||
|
}
|
||||||
|
return wandle.EmptyCmd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widdles := []widdles.Widdle{w.keyInput, w.valInput, w.cancelButton, w.doneButton}
|
||||||
|
for _, wdl := range widdles {
|
||||||
|
if wdl.IsActive() {
|
||||||
|
if ret := wdl.Update(msg); ret != nil {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if msg.Ch == 'j' || msg.Key == termbox.KeyArrowDown || msg.Key == termbox.KeyArrowRight {
|
||||||
|
for i := range widdles {
|
||||||
|
if widdles[i].IsActive() {
|
||||||
|
return func() wandle.Msg {
|
||||||
|
widdles[i].SetActive(false)
|
||||||
|
next := ((i + 1) + len(widdles)) % len(widdles)
|
||||||
|
widdles[next].SetActive(true)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if msg.Ch == 'k' || msg.Key == termbox.KeyArrowUp || msg.Key == termbox.KeyArrowLeft {
|
||||||
|
for i := range widdles {
|
||||||
|
if widdles[i].IsActive() {
|
||||||
|
return func() wandle.Msg {
|
||||||
|
widdles[i].SetActive(false)
|
||||||
|
next := ((i - 1) + len(widdles)) % len(widdles)
|
||||||
|
widdles[next].SetActive(true)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (w *PromptForTagWiddle) SetTag(key, val string) {
|
||||||
|
w.origKey, w.origVal = key, val
|
||||||
|
w.keyInput.SetValue(key)
|
||||||
|
if key == "" && val == "" {
|
||||||
|
w.keyInput.SetEditable(true)
|
||||||
|
}
|
||||||
|
w.valInput.SetValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PromptForTagWiddle) ClearCancelCommand() { w.SetCancelCommand(wandle.EmptyCmd) }
|
||||||
|
func (w *PromptForTagWiddle) SetCancelCommand(cmd func() wandle.Msg) { w.cancelButton.SetCommand(cmd) }
|
||||||
|
func (w *PromptForTagWiddle) ClearDoneCommand() { w.SetDoneCommand(wandle.EmptyCmd) }
|
||||||
|
func (w *PromptForTagWiddle) SetDoneCommand(cmd func() wandle.Msg) { w.doneButton.SetCommand(cmd) }
|
@ -426,3 +426,12 @@ func SortedTagKeyList(m map[string]string) []string {
|
|||||||
sort.Strings(ret)
|
sort.Strings(ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StringSliceContains(sl []string, val string) bool {
|
||||||
|
for i := range sl {
|
||||||
|
if sl[i] == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user