diff options
Diffstat (limited to 'view.go')
| -rw-r--r-- | view.go | 233 |
1 files changed, 233 insertions, 0 deletions
@@ -0,0 +1,233 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "strings" + + "github.com/awesome-gocui/gocui" + + "go.wit.com/lib/widget" + "go.wit.com/log" +) + +func splitLines(s string) []string { + var lines []string + sc := bufio.NewScanner(strings.NewReader(s)) + for sc.Scan() { + lines = append(lines, sc.Text()) + } + return lines +} + +func (n *node) textResize() bool { + w := n.tk + var width, height int = 0, 0 + var changed bool = false + + for i, s := range splitLines(n.tk.label) { + log.Log(INFO, "textResize() len =", len(s), i, s) + if width < len(s) { + width = len(s) + } + height += 1 + } + if w.gocuiSize.w1 != w.gocuiSize.w0+width+me.FramePadW { + w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW + changed = true + } + if w.gocuiSize.h1 != w.gocuiSize.h0+height+me.FramePadH { + w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH + changed = true + } + if changed { + n.showWidgetPlacement(true, "textResize() changed") + } + return changed +} + +func (n *node) hideView() { + n.SetVisible(false) +} + +// display's the text of the widget in gocui +// will create a new gocui view if there isn't one or if it has been moved +func (n *node) showView() { + var err error + w := n.tk + + if w.cuiName == "" { + log.Log(ERROR, "showView() w.cuiName was not set for widget", w) + w.cuiName = string(n.WidgetId) + } + + // if the gocui element doesn't exist, create it + if w.v == nil { + n.recreateView() + } + x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName) + log.Log(INFO, "showView() w.v already defined for widget", n.progname, err) + + // n.smartGocuiSize() + changed := n.textResize() + + if changed { + log.Log(NOW, "showView() textResize() changed. Should recreateView here wId =", w.cuiName) + } else { + log.Log(NOW, "showView() Clear() and Fprint() here wId =", w.cuiName) + w.v.Clear() + fmt.Fprint(w.v, n.tk.label) + n.SetVisible(false) + n.SetVisible(true) + return + } + + // if the gocui element has changed where it is supposed to be on the screen + // recreate it + if x0 != w.gocuiSize.w0 { + n.recreateView() + return + } + if y0 != w.gocuiSize.h0 { + log.Log(ERROR, "showView() start hight mismatch id=", w.cuiName, "gocui h vs computed h =", w.gocuiSize.h0, y0) + n.recreateView() + return + } + if x1 != w.gocuiSize.w1 { + log.Log(ERROR, "showView() too wide", w.cuiName, "w,w", w.gocuiSize.w1, x1) + n.recreateView() + return + } + if y1 != w.gocuiSize.h1 { + log.Log(ERROR, "showView() too high", w.cuiName, "h,h", w.gocuiSize.h1, y1) + n.recreateView() + return + } + + n.SetVisible(true) +} + +// create or recreate the gocui widget visible +// deletes the old view if it exists and recreates it +func (n *node) recreateView() { + var err error + w := n.tk + log.Log(ERROR, "recreateView() START", n.WidgetType, n.progname) + if me.baseGui == nil { + log.Log(ERROR, "recreateView() ERROR: me.baseGui == nil", w) + return + } + + // this deletes the button from gocui + me.baseGui.DeleteView(w.cuiName) + w.v = nil + + if n.progname == "CLOUDFLARE_EMAIL" { + n.showWidgetPlacement(true, "n.progname="+n.progname+" n.tk.label="+n.tk.label+" "+w.cuiName) + n.dumpWidget("jwc") + n.textResize() + n.showWidgetPlacement(true, "n.progname="+n.progname+" n.tk.label="+n.tk.label+" "+w.cuiName) + } + + a := w.gocuiSize.w0 + b := w.gocuiSize.h0 + c := w.gocuiSize.w1 + d := w.gocuiSize.h1 + + w.v, err = me.baseGui.SetView(w.cuiName, a, b, c, d, 0) + if err == nil { + n.showWidgetPlacement(true, "recreateView()") + log.Log(ERROR, "recreateView() internal plugin error err = nil") + return + } + if !errors.Is(err, gocui.ErrUnknownView) { + n.showWidgetPlacement(true, "recreateView()") + log.Log(ERROR, "recreateView() internal plugin error error.IS()", err) + return + } + + // this sets up the keybinding for the name of the window + // does this really need to be done? I think we probably already + // know everything about where all the widgets are so we could bypass + // the gocui package and just handle all the mouse events internally here (?) + // for now, the w.v.Name is a string "1", "2", "3", etc from the widgetId + + // set the binding for this gocui view now that it has been created + // gocui handles overlaps of views so it will run on the view that is clicked on + me.baseGui.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click) + + // this actually sends the text to display to gocui + w.v.Wrap = true + w.v.Frame = w.frame + w.v.Clear() + fmt.Fprint(w.v, n.tk.label) + // n.showWidgetPlacement(true, "n.progname=" + n.progname + " n.tk.label=" + n.tk.label + " " + w.cuiName) + // n.dumpWidget("jwc 2") + + // if you don't do this here, it will be black & white only + if w.color != nil { + w.v.FrameColor = w.color.frame + w.v.FgColor = w.color.fg + w.v.BgColor = w.color.bg + w.v.SelFgColor = w.color.selFg + w.v.SelBgColor = w.color.selBg + } + if n.progname == "CLOUDFLARE_EMAIL" { + n.showWidgetPlacement(true, "n.progname="+n.progname+" n.tk.label="+n.tk.label+" "+w.cuiName) + n.dumpTree(true) + } + log.Log(ERROR, "recreateView() END") +} + +func (n *node) hideWidgets() { + w := n.tk + w.isCurrent = false + switch n.WidgetType { + case widget.Root: + case widget.Flag: + case widget.Window: + case widget.Box: + case widget.Grid: + default: + n.hideView() + } + for _, child := range n.children { + child.hideWidgets() + } +} + +func (n *node) hideFake() { + w := n.tk + if w.isFake { + n.hideView() + } + for _, child := range n.children { + child.hideFake() + } +} + +func (n *node) showFake() { + w := n.tk + if w.isFake { + n.setFake() + n.showWidgetPlacement(true, "showFake:") + n.showView() + } + for _, child := range n.children { + child.showFake() + } +} + +func (n *node) showWidgets() { + w := n.tk + if w.isFake { + // don't display by default + } else { + n.showWidgetPlacement(true, "current:") + n.showView() + } + for _, child := range n.children { + child.showWidgets() + } +} |
