123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package main
- import (
- "context"
- "fmt"
- "github.com/gdamore/tcell/v2"
- "github.com/oklog/run"
- "github.com/rivo/tview"
- "io"
- )
- type UI struct {
- app *tview.Application
- flex *tview.Flex
- logbox *tview.TextView
- menu *tview.List
- running bool
- grp *run.Group
- pctx context.Context
- cncl context.CancelFunc
- tasks []*Task
- logwr io.Writer
- }
- func NewUI() *UI {
- ui := &UI{
- app: tview.NewApplication(),
- flex: tview.NewFlex(),
- logbox: tview.NewTextView(),
- menu: tview.NewList(),
- }
- ui.flex.AddItem(ui.menu, 32, 0, true)
- ui.flex.AddItem(ui.logbox, 0, 1, false)
- ui.flex.SetDirection(tview.FlexColumn)
- ui.logbox.SetScrollable(true)
- ui.logbox.SetBackgroundColor(tcell.ColorNavy)
- ui.logwr = tview.ANSIWriter(ui.logbox)
- ui.menu.AddItem("start", "", 0, ui.startTasks)
- ui.menu.AddItem("cancel parent", "", 0, ui.killParent)
- ui.menu.AddItem("cancel Task1", "", 0, func() {
- ui.killTask(0)
- })
- ui.menu.AddItem("cancel Task2", "", 0, func() {
- ui.killTask(1)
- })
- ui.menu.AddItem("cancel Task3", "", 0, func() {
- ui.killTask(2)
- })
- ui.app.SetRoot(ui.flex, true)
- ui.app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
- switch event.Key() {
- case tcell.KeyF1:
- {
- ui.app.SetFocus(ui.menu)
- break
- }
- case tcell.KeyF2:
- {
- ui.app.SetFocus(ui.logbox)
- break
- }
- default:
- {
- return event
- }
- }
- return nil
- })
- return ui
- }
- func (u *UI) killParent() {
- if u.running {
- _, _ = fmt.Fprintln(u, "[UI] cancel parent")
- u.cncl()
- } else {
- _, _ = fmt.Fprintln(u, "[UI] tasks not running")
- }
- }
- func (u *UI) startTasks() {
- if !u.running {
- u.grp = &run.Group{}
- ctx, cncl := context.WithCancel(context.Background())
- u.pctx = ctx
- u.cncl = cncl
- u.tasks = make([]*Task, 3)
- for i := 0; i < 3; i++ {
- t := NewTask(i+1, u.pctx, u)
- u.tasks[i] = t
- u.grp.Add(t.Task, t.Cancel)
- }
- go func() {
- _, _ = fmt.Fprintln(u, "[UI] run tasks.")
- u.running = true
- err := u.grp.Run()
- if err != nil {
- _, _ = fmt.Fprintln(u, "[UI] all tasks end, with error:", err)
- } else {
- _, _ = fmt.Fprintln(u, "[UI] all tasks end, with no error")
- }
- u.running = false
- }()
- } else {
- _, _ = fmt.Fprintln(u, "[UI] tasks already running")
- }
- }
- func (u *UI) killTask(id int) {
- if !u.running {
- _, _ = fmt.Fprintln(u, "[UI] tasks not running")
- return
- }
- v := u.tasks[id]
- if v != nil {
- _, _ = fmt.Fprintf(u, "[UI] cancel task %d\n", id+1)
- v.Cancel(nil)
- }
- }
- func (u *UI) Write(p []byte) (n int, err error) {
- return u.logwr.Write(p)
- }
- func (u *UI) Run() error {
- return u.app.Run()
- }
|