From 1552eedc185e85b46498898e68867afaef308301 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Tue, 25 Mar 2025 07:27:37 -0500 Subject: save the output window state --- debug.go | 3 + eventBindingsStdout.go | 22 ++++ eventMouseDrag.go | 2 + find.go | 14 +++ init.go | 28 +++++ plugin.go | 2 +- structs.go | 10 +- table.go | 15 +-- treeAdd.go | 117 --------------------- treeDraw.go | 271 ------------------------------------------------- treeWidget.go | 126 ----------------------- widgetAdd.go | 117 +++++++++++++++++++++ widgetCommon.go | 126 +++++++++++++++++++++++ widgetDraw.go | 271 +++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 590 insertions(+), 534 deletions(-) delete mode 100644 treeAdd.go delete mode 100644 treeDraw.go delete mode 100644 treeWidget.go create mode 100644 widgetAdd.go create mode 100644 widgetCommon.go create mode 100644 widgetDraw.go diff --git a/debug.go b/debug.go index 84630f5..490b113 100644 --- a/debug.go +++ b/debug.go @@ -86,6 +86,9 @@ func (tk *guiWidget) dumpWidget(s string) { } else { end = fmt.Sprintf("%-8s %-8s %s", tk.WidgetType(), tk.cuiName, tk.String()) } + if tk.findParentTable() != nil { + end += " (table)" + } log.Log(GOCUI, s1, s, end) } diff --git a/eventBindingsStdout.go b/eventBindingsStdout.go index f48ed77..f1c574e 100644 --- a/eventBindingsStdout.go +++ b/eventBindingsStdout.go @@ -8,12 +8,14 @@ import ( "github.com/awesome-gocui/gocui" "go.wit.com/log" + "go.wit.com/toolkits/tree" ) func theStdout(g *gocui.Gui, v *gocui.View) error { // me.stdout.pager = 0 infos := fmt.Sprintf("pager=%d len(%d) ", me.stdout.pager, len(me.stdout.outputS)) infos += fmt.Sprintf("last(%d,%d)", me.stdout.lastW, me.stdout.lastH) + me.stdout.changed = true if me.stdout.outputOnTop { if me.stdout.outputOffscreen { @@ -22,18 +24,38 @@ func theStdout(g *gocui.Gui, v *gocui.View) error { me.stdout.lastW = me.stdout.tk.gocuiSize.w0 me.stdout.lastH = me.stdout.tk.gocuiSize.h0 relocateStdoutOffscreen() + new1 := new(tree.ToolkitConfig) + new1.Plugin = "gocui" + new1.Name = "stdoutoffscreen" + new1.Value = "true" + me.myTree.ConfigSave(new1) return nil } else { me.stdout.outputOffscreen = true log.Info("stdout moved on screen", infos) + new1 := new(tree.ToolkitConfig) + new1.Plugin = "gocui" + new1.Name = "stdoutoffscreen" + new1.Value = "false" + me.myTree.ConfigSave(new1) } // move the stdout window back onscreen me.stdout.tk.relocateStdout(me.stdout.lastW, me.stdout.lastH) me.stdout.outputOnTop = false setThingsOnTop() + new1 := new(tree.ToolkitConfig) + new1.Plugin = "gocui" + new1.Name = "stdoutlevel" + new1.Value = "bottom" + me.myTree.ConfigSave(new1) } else { me.stdout.outputOnTop = true setThingsOnTop() + new1 := new(tree.ToolkitConfig) + new1.Plugin = "gocui" + new1.Name = "stdoutlevel" + new1.Value = "top" + me.myTree.ConfigSave(new1) } return nil } diff --git a/eventMouseDrag.go b/eventMouseDrag.go index 5559fac..62aa916 100644 --- a/eventMouseDrag.go +++ b/eventMouseDrag.go @@ -48,6 +48,7 @@ func mouseMove(g *gocui.Gui) { // old hack. create the 'msg' view if it does not yet exist // TODO: put this somewhere more correct if widgetView, _ := g.View("msg"); widgetView == nil { + me.stdout.changed = true if createStdout(g) { return } @@ -138,5 +139,6 @@ func (tk *guiWidget) moveNew() { // log.Info("Resize false", w, h, newW, newH) } setThingsOnTop() // sets help, Stdout, etc on the top after windows have been redrawn + me.stdout.changed = true } } diff --git a/find.go b/find.go index 2cb94f3..13d9c0e 100644 --- a/find.go +++ b/find.go @@ -186,6 +186,20 @@ func (tk *guiWidget) findParentWindow() *guiWidget { return tk.parent.findParentWindow() } +func (tk *guiWidget) findParentTable() *guiWidget { + if tk.isTable { + log.Info("findParentTAble()", tk.labelN, tk.cuiName, tk.node.WidgetId) + return tk + } + if tk.node.WidgetId == 0 { + return nil + } + if tk.parent == nil { + return nil + } + return tk.parent.findParentWindow() +} + func (tk *guiWidget) findWidgetByName(name string) *guiWidget { if tk.cuiName == name { return tk diff --git a/init.go b/init.go index b13f634..2820bcf 100644 --- a/init.go +++ b/init.go @@ -14,10 +14,13 @@ import ( "runtime" "runtime/debug" "runtime/pprof" + "strconv" + "strings" "time" "github.com/awesome-gocui/gocui" "go.wit.com/log" + "go.wit.com/toolkits/tree" ) // sent via -ldflags @@ -184,6 +187,19 @@ func initPlugin() { me.stdout.lastW = 4 me.stdout.lastH = 20 + if val, err := me.myTree.ConfigFind("stdoutsize"); err == nil { + parts := strings.Fields(val) + if len(parts) == 4 { + log.Info("initial stdout settings:", parts) + me.stdout.w, _ = strconv.Atoi(parts[0]) + me.stdout.h, _ = strconv.Atoi(parts[1]) + me.stdout.lastW, _ = strconv.Atoi(parts[2]) + me.stdout.lastH, _ = strconv.Atoi(parts[3]) + } else { + log.Info("initial stdout settings parse error:", parts) + } + } + // just make up unique values for these me.dropdown.wId = -77 me.textbox.wId = -55 @@ -376,6 +392,18 @@ func refreshGocui() { me.newWindowTrigger <- me.treeRoot.TK.(*guiWidget) me.refresh = false } + if me.stdout.changed { + log.Log(NOW, "newWindowTrigger() TODO: gocui should save the stdout size & location here") + me.stdout.changed = false + me.stdout.tk.dumpWidget("save") + new1 := new(tree.ToolkitConfig) + new1.Plugin = "gocui" + new1.Name = "stdoutsize" + width := me.stdout.tk.gocuiSize.w1 - me.stdout.tk.gocuiSize.w0 + height := me.stdout.tk.gocuiSize.h1 - me.stdout.tk.gocuiSize.h0 + new1.Value = fmt.Sprintf("%d %d %d %d", width, height, me.stdout.tk.gocuiSize.w0, me.stdout.tk.gocuiSize.h0) + me.myTree.ConfigSave(new1) + } } // this code updates the clock diff --git a/plugin.go b/plugin.go index 7555c44..67def55 100644 --- a/plugin.go +++ b/plugin.go @@ -16,7 +16,7 @@ func newAdd(n *tree.Node) { return } if n.TK != nil { - log.Warn("Tree Add() sent a widget we aleady seem to have") + log.Log(INFO, "Tree Add() sent a widget we aleady seem to have") // this is done to protect the plugin being 'refreshed' with the // widget binary tree. TODO: find a way to keep them in sync return diff --git a/structs.go b/structs.go index fcd04cf..c9337b1 100644 --- a/structs.go +++ b/structs.go @@ -116,11 +116,10 @@ type stdout struct { disable bool // disable the stdout window. do not change os.Stdout & os.Stderr lastW int // the last 'w' location (used to move from offscreen to onscreen) lastH int // the last 'h' location (used to move from offscreen to onscreen) - // mouseOffsetW int // the current 'w' offset - // mouseOffsetH int // the current 'h' offset - init bool // moves the window offscreen on startup - outputS []string // the buffer of all the output - pager int // allows the user to page through the buffer + init bool // moves the window offscreen on startup + outputS []string // the buffer of all the output + pager int // allows the user to page through the buffer + changed bool // indicates the user has changed stdout. gocui should remember the state here } // settings for the dropdown window @@ -241,6 +240,7 @@ type guiWidget struct { color *colorT // what color to use colorLast colorT // the last color the widget had defaultColor *colorT // the default colors // TODO: make a function for this instead + isTable bool // is this a table? } // THIS IS GO COMPILER MAGIC diff --git a/table.go b/table.go index efc0b4e..df16fc2 100644 --- a/table.go +++ b/table.go @@ -13,20 +13,6 @@ import ( "go.wit.com/widget" ) -/* -func initGridPB(pb *guipb.Widget) *guiWidget { - var w *guiWidget - w = new(guiWidget) - - w.pb = pb - w.parent = me.treeRoot.TK.(*guiWidget) - w.wtype = widget.Window - w.cuiName = fmt.Sprintf("%d %s", pb.Id, "TK") - w.labelN = pb.Name - return w -} -*/ - func initGridPB(pb *guipb.Widget) *guiWidget { var w *guiWidget w = new(guiWidget) @@ -35,6 +21,7 @@ func initGridPB(pb *guipb.Widget) *guiWidget { w.wtype = widget.Grid w.cuiName = fmt.Sprintf("%d %s", pb.Id, "TK") w.labelN = pb.Name + w.isTable = true return w } diff --git a/treeAdd.go b/treeAdd.go deleted file mode 100644 index 6bb459b..0000000 --- a/treeAdd.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2017-2025 WIT.COM Inc. All rights reserved. -// Use of this source code is governed by the GPL 3.0 - -package main - -import ( - log "go.wit.com/log" - "go.wit.com/toolkits/tree" - "go.wit.com/widget" -) - -var fakeStartWidth int = me.FakeW -var fakeStartHeight int = me.TabH + me.FramePadH - -// setup fake labels for non-visible things off screen -func setFake(n *tree.Node) { - var w *guiWidget - w = n.TK.(*guiWidget) - w.isFake = true - - w.gocuiSetWH(fakeStartWidth, fakeStartHeight) - - fakeStartHeight += w.gocuiSize.Height() - // TODO: use the actual max hight of the terminal window - if fakeStartHeight > 24 { - fakeStartHeight = me.TabH - fakeStartWidth += me.FakeW - } -} - -// mostly just sets the colors of things -func addWidget(n *tree.Node) { - if !me.ok { - log.Log(INFO, "addWidget() START NOT OKAY") - log.Log(INFO, "addWidget() START NOT OKAY") - log.Log(INFO, "addWidget() START NOT OKAY") - waitOK() - } - tk := n.TK.(*guiWidget) - log.Log(INFO, "setStartWH() w.id =", n.WidgetId, "n.name", n.String()) - switch n.WidgetType { - case widget.Root: - log.Log(INFO, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.String()) - // tk.color = &colorRoot - setFake(n) - return - case widget.Flag: - // tk.color = &colorFlag - setFake(n) - return - case widget.Window: - tk.frame = false - tk.labelN = tk.GetText() + " X" - // tk.setColor(&colorWindow) - me.newWindowTrigger <- tk - redoWindows(0, 0) - return - case widget.Stdout: - tk.labelN = "moreSTDOUT" - n.State.ProgName = "moreSTDOUT" - n.State.Label = "moreSTDOUT" - tk.isFake = true - return - case widget.Tab: - // tk.color = &colorTab - return - case widget.Button: - tk.setColorButton() - if tk.IsEnabled() { - } else { - tk.setColorDisable() - } - return - case widget.Checkbox: - tk.setColorInput() - tk.labelN = "X " + n.State.Label - return - case widget.Dropdown: - tk.setColorInput() - return - case widget.Textbox: - n.State.Label = "" - tk.labelN = " " - // tk.color = &colorDropdown - tk.setColorInput() - return - case widget.Combobox: - // tk.color = &colorCombobox - tk.setColorInput() - return - case widget.Box: - // tk.color = &colorBox - tk.isFake = true - setFake(n) - return - case widget.Grid: - // tk.color = &colorGrid - tk.isFake = true - setFake(n) - return - case widget.Group: - tk.setColorLabel() - tk.frame = false - return - case widget.Label: - tk.setColorLabel() - tk.frame = false - return - default: - /* - if n.IsCurrent() { - n.updateCurrent() - } - */ - } - tk.dumpWidget("addWidget()unknown") -} diff --git a/treeDraw.go b/treeDraw.go deleted file mode 100644 index d678678..0000000 --- a/treeDraw.go +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2017-2025 WIT.COM Inc. All rights reserved. -// Use of this source code is governed by the GPL 3.0 - -package main - -import ( - "errors" - "fmt" - "strconv" - - "github.com/awesome-gocui/gocui" - log "go.wit.com/log" - "go.wit.com/widget" -) - -// don't draw widgets that are too far down the window -func (tk *guiWidget) doNotDraw() bool { - var check bool - switch tk.WidgetType() { - case widget.Button: - check = true - case widget.Label: - check = true - default: - } - if !check { - return false - } - win := tk.findParentWindow() - if win == nil { - // don't draw anything if you can't find the parent window - return true - } - - h := tk.gocuiSize.h0 - win.gocuiSize.h0 - - if h > 20 { - return true - } - - return false -} - -// page widgets in the window -func (tk *guiWidget) pageWidget() *rectType { - r := new(rectType) - - var check bool - switch tk.WidgetType() { - case widget.Button: - check = true - case widget.Label: - check = true - default: - } - if !check { - return nil - } - win := tk.findParentWindow() - if win == nil { - // don't draw anything if you can't find the parent window - return nil - } - - r.w0 = tk.gocuiSize.w0 - r.h0 = tk.gocuiSize.h0 - r.w1 = tk.gocuiSize.w1 - r.h1 = tk.gocuiSize.h1 - - // r.h0 = tk.gocuiSize.h0 - win.gocuiSize.h0 - - if r.h0 > 20 { - return r - } - - return r -} - -// display's the text of the widget in gocui -// deletes the old view if it exists and recreates it -func (tk *guiWidget) drawView() { - var err error - log.Log(INFO, "drawView() START", tk.WidgetType(), tk.String()) - if me.baseGui == nil { - log.Log(ERROR, "drawView() ERROR: me.baseGui == nil", tk) - return - } - - if tk.cuiName == "" { - log.Log(ERROR, "drawView() tk.cuiName was not set for widget", tk) - tk.cuiName = strconv.Itoa(tk.WidgetId()) + " TK" - } - log.Log(INFO, "drawView() labelN =", tk.labelN) - - // this deletes the button from gocui - me.baseGui.DeleteView(tk.cuiName) - tk.v = nil - - a := tk.gocuiSize.w0 - b := tk.gocuiSize.h0 - c := tk.gocuiSize.w1 - d := tk.gocuiSize.h1 - - /* - // testing code for paging large windows - if tk.doNotDraw() { - return - } - - if tk.window.pager != 0 { - if r := tk.pageWidget(); r == nil { - // if nil, draw whatever it is anyway - } else { - if r.Width() == 0 && r.Height() == 0 { - // don't draw empty stuff - return - } - a = r.w0 - b = r.h0 - c = r.w1 - d = r.h1 - } - } - - if tk.WidgetType() == widget.Window || tk.WidgetType() == widget.Flag { - if tk.window.pager != 0 { - if tk.gocuiSize.Height() > 40 { - tk.window.large = true - tk.gocuiSize.h1 = tk.gocuiSize.h0 + 40 - d = tk.gocuiSize.h1 - } - } - } - */ - - // this is all terrible. This sets the title. kinda - if tk.WidgetType() == widget.Window { - tk.textResize() - tk.full.w0 = tk.force.w0 - tk.full.h0 = tk.force.h0 - - // for windows, make it the full size - a = tk.full.w0 - b = tk.full.h0 - c = tk.full.w0 + tk.gocuiSize.Width() - d = tk.full.h0 + tk.gocuiSize.Height() - } else { - if tk.internal { - // do nothing - } else { - tk.textResize() // resize gocui frame to the widget text - } - a = tk.gocuiSize.w0 - b = tk.gocuiSize.h0 - c = tk.gocuiSize.w1 - d = tk.gocuiSize.h1 - } - - tk.v, err = me.baseGui.SetView(tk.cuiName, a, b, c, d, 0) - if err == nil { - tk.dumpWidget("drawView() err") - log.Log(ERROR, "drawView() internal plugin error err = nil") - return - } - - if !errors.Is(err, gocui.ErrUnknownView) { - tk.dumpWidget("drawView() err") - log.Log(ERROR, "drawView() internal plugin error error.IS()", err) - return - } - - if tk.v == nil { - log.Info("MUTEX FAIL. tk.v == nil here in drawView()") - log.Info("MUTEX FAIL. tk.v == nil here in drawView()") - log.Info("MUTEX FAIL. tk.v == nil here in drawView()") - return - } - - // this actually sends the text to display to gocui - tk.v.Wrap = true - tk.v.Frame = tk.frame - tk.v.Clear() - fmt.Fprint(tk.v, tk.labelN) - - // tmp hack to disable buttons on window open - if tk.WidgetType() == widget.Button { - if tk.IsEnabled() { - } else { - tk.setColorDisable() - } - } - - switch tk.WidgetType() { - case widget.Button: - if tk.IsEnabled() { - if tk.isWindowDense() && tk.isInGrid() { - tk.setColorButtonDense() - } else { - tk.setColorButton() - } - } else { - tk.setColorDisable() - } - default: - } - - if tk.v == nil { - log.Info("MUTEX FAIL 2. tk.v was deleted somehow tk.v == nil here in drawView()") - log.Info("MUTEX FAIL 2. tk.v == nil here in drawView()") - log.Info("MUTEX FAIL 2. tk.v == nil here in drawView()") - return - } - - // if you don't do this here, it will be black & white only - if tk.color != nil { - tk.v.FrameColor = tk.color.frame - tk.v.FgColor = tk.color.fg - tk.v.BgColor = tk.color.bg - tk.v.SelFgColor = tk.color.selFg - tk.v.SelBgColor = tk.color.selBg - } - - log.Log(INFO, "drawView() END") -} - -func (w *guiWidget) DrawAt(offsetW, offsetH int) { - // w.setColor(&colorActiveW) - w.placeWidgets(offsetW, offsetH) // compute the sizes & places for each widget - // w.dumpWidget(fmt.Sprintf("DrawAt(%d,%d)", offsetW, offsetH)) -} - -func (w *guiWidget) simpleDrawAt(offsetW, offsetH int) { - // w.setColor(&colorActiveW) - w.dumpWidget("simpleDrawAt()") -} - -// display the widgets in the binary tree -func (w *guiWidget) drawTree(draw bool) { - if w == nil { - return - } - w.dumpWidget("in drawTree()") - if draw { - // w.textResize() - w.Show() - } else { - w.Hide() - } - - for _, child := range w.children { - child.drawTree(draw) - } -} - -func (w *guiWidget) Show() { - if w.isFake { - // don't display fake widgets - return - } - - if w.Hidden() { - // recursively checks if the parent is hidden - // never show hidden widgets - return - } - if me.debug { - w.dumpWidget("drawView()") - } - - w.drawView() -} diff --git a/treeWidget.go b/treeWidget.go deleted file mode 100644 index 15d269c..0000000 --- a/treeWidget.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2017-2025 WIT.COM Inc. All rights reserved. -// Use of this source code is governed by the GPL 3.0 - -package main - -import ( - "strconv" - "strings" - - "go.wit.com/log" - "go.wit.com/toolkits/tree" - "go.wit.com/widget" -) - -func initWidget(n *tree.Node) *guiWidget { - var w *guiWidget - w = new(guiWidget) - - w.node = n - w.cuiName = strconv.Itoa(w.WidgetId()) + " TK" - // w.WidgetType() = n.WidgetType - w.labelN = n.State.Label - if w.labelN == "" { - // remove this debugging hack once things are stable and fixed - w.labelN = n.GetProgName() - } - w.frame = true - w.enable = n.State.Enable - - if n.WidgetType == widget.Root { - log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId) - } - - if n.WidgetType == widget.Grid { - w.widths = make(map[int]int) // how tall each row in the grid is - w.heights = make(map[int]int) // how wide each column in the grid is - } - - p := n.Parent - if p == nil { - log.Log(ERROR, "parent == nil", w.String(), n.WidgetId, w.WidgetType()) - return w - } - if p.TK == nil { - if n.WidgetId == 0 { - // this is a normal init condition - } else { - log.Log(ERROR, "parent.TK == nil", w.String(), n.WidgetId, w.WidgetType()) - } - return w - } - - // set the parent and append to parent children - var ptk *guiWidget - ptk = p.TK.(*guiWidget) - w.parent = ptk - ptk.children = append(ptk.children, w) - return w -} - -func setupCtrlDownWidget() { - a := new(widget.Action) - a.ProgName = "ctrlDown" - a.WidgetType = widget.Dialog - a.WidgetId = -1 - a.ParentId = 0 - // n := addNode(a) - n := me.myTree.AddNode(a) - - me.ctrlDown = n -} - -func (w *guiWidget) deleteView() { - // make sure the view isn't really there - // log.Log(GOCUI, "deleteView()", w.cuiName, w.WidgetType(), w.WidgetId()) - me.baseGui.DeleteView(w.cuiName) - w.v = nil -} - -func (tk *guiWidget) String() string { - // deprecate this? - curval := strings.TrimSpace(tk.labelN) - if curval != "" { - return curval - } - curval = strings.TrimSpace(tk.GetLabel()) - if curval != "" { - return curval - } - curval = tk.GetText() - if curval != "" { - return curval - } - curval = tk.node.String() - if curval != "" { - return curval - } - curval = strings.TrimSpace(tk.node.ProgName()) - if curval != "" { - return curval - } - return "" -} - -func (tk *guiWidget) Visible() bool { - if tk == nil { - return false - } - if tk.v == nil { - return false - } - tk.v.Visible = true - return true -} - -func (tk *guiWidget) Hide() { - tk.deleteView() -} - -func (tk *guiWidget) SetVisible(b bool) { - if b { - tk.Show() - } else { - tk.Hide() - } -} diff --git a/widgetAdd.go b/widgetAdd.go new file mode 100644 index 0000000..6bb459b --- /dev/null +++ b/widgetAdd.go @@ -0,0 +1,117 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + log "go.wit.com/log" + "go.wit.com/toolkits/tree" + "go.wit.com/widget" +) + +var fakeStartWidth int = me.FakeW +var fakeStartHeight int = me.TabH + me.FramePadH + +// setup fake labels for non-visible things off screen +func setFake(n *tree.Node) { + var w *guiWidget + w = n.TK.(*guiWidget) + w.isFake = true + + w.gocuiSetWH(fakeStartWidth, fakeStartHeight) + + fakeStartHeight += w.gocuiSize.Height() + // TODO: use the actual max hight of the terminal window + if fakeStartHeight > 24 { + fakeStartHeight = me.TabH + fakeStartWidth += me.FakeW + } +} + +// mostly just sets the colors of things +func addWidget(n *tree.Node) { + if !me.ok { + log.Log(INFO, "addWidget() START NOT OKAY") + log.Log(INFO, "addWidget() START NOT OKAY") + log.Log(INFO, "addWidget() START NOT OKAY") + waitOK() + } + tk := n.TK.(*guiWidget) + log.Log(INFO, "setStartWH() w.id =", n.WidgetId, "n.name", n.String()) + switch n.WidgetType { + case widget.Root: + log.Log(INFO, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.String()) + // tk.color = &colorRoot + setFake(n) + return + case widget.Flag: + // tk.color = &colorFlag + setFake(n) + return + case widget.Window: + tk.frame = false + tk.labelN = tk.GetText() + " X" + // tk.setColor(&colorWindow) + me.newWindowTrigger <- tk + redoWindows(0, 0) + return + case widget.Stdout: + tk.labelN = "moreSTDOUT" + n.State.ProgName = "moreSTDOUT" + n.State.Label = "moreSTDOUT" + tk.isFake = true + return + case widget.Tab: + // tk.color = &colorTab + return + case widget.Button: + tk.setColorButton() + if tk.IsEnabled() { + } else { + tk.setColorDisable() + } + return + case widget.Checkbox: + tk.setColorInput() + tk.labelN = "X " + n.State.Label + return + case widget.Dropdown: + tk.setColorInput() + return + case widget.Textbox: + n.State.Label = "" + tk.labelN = " " + // tk.color = &colorDropdown + tk.setColorInput() + return + case widget.Combobox: + // tk.color = &colorCombobox + tk.setColorInput() + return + case widget.Box: + // tk.color = &colorBox + tk.isFake = true + setFake(n) + return + case widget.Grid: + // tk.color = &colorGrid + tk.isFake = true + setFake(n) + return + case widget.Group: + tk.setColorLabel() + tk.frame = false + return + case widget.Label: + tk.setColorLabel() + tk.frame = false + return + default: + /* + if n.IsCurrent() { + n.updateCurrent() + } + */ + } + tk.dumpWidget("addWidget()unknown") +} diff --git a/widgetCommon.go b/widgetCommon.go new file mode 100644 index 0000000..15d269c --- /dev/null +++ b/widgetCommon.go @@ -0,0 +1,126 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "strconv" + "strings" + + "go.wit.com/log" + "go.wit.com/toolkits/tree" + "go.wit.com/widget" +) + +func initWidget(n *tree.Node) *guiWidget { + var w *guiWidget + w = new(guiWidget) + + w.node = n + w.cuiName = strconv.Itoa(w.WidgetId()) + " TK" + // w.WidgetType() = n.WidgetType + w.labelN = n.State.Label + if w.labelN == "" { + // remove this debugging hack once things are stable and fixed + w.labelN = n.GetProgName() + } + w.frame = true + w.enable = n.State.Enable + + if n.WidgetType == widget.Root { + log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId) + } + + if n.WidgetType == widget.Grid { + w.widths = make(map[int]int) // how tall each row in the grid is + w.heights = make(map[int]int) // how wide each column in the grid is + } + + p := n.Parent + if p == nil { + log.Log(ERROR, "parent == nil", w.String(), n.WidgetId, w.WidgetType()) + return w + } + if p.TK == nil { + if n.WidgetId == 0 { + // this is a normal init condition + } else { + log.Log(ERROR, "parent.TK == nil", w.String(), n.WidgetId, w.WidgetType()) + } + return w + } + + // set the parent and append to parent children + var ptk *guiWidget + ptk = p.TK.(*guiWidget) + w.parent = ptk + ptk.children = append(ptk.children, w) + return w +} + +func setupCtrlDownWidget() { + a := new(widget.Action) + a.ProgName = "ctrlDown" + a.WidgetType = widget.Dialog + a.WidgetId = -1 + a.ParentId = 0 + // n := addNode(a) + n := me.myTree.AddNode(a) + + me.ctrlDown = n +} + +func (w *guiWidget) deleteView() { + // make sure the view isn't really there + // log.Log(GOCUI, "deleteView()", w.cuiName, w.WidgetType(), w.WidgetId()) + me.baseGui.DeleteView(w.cuiName) + w.v = nil +} + +func (tk *guiWidget) String() string { + // deprecate this? + curval := strings.TrimSpace(tk.labelN) + if curval != "" { + return curval + } + curval = strings.TrimSpace(tk.GetLabel()) + if curval != "" { + return curval + } + curval = tk.GetText() + if curval != "" { + return curval + } + curval = tk.node.String() + if curval != "" { + return curval + } + curval = strings.TrimSpace(tk.node.ProgName()) + if curval != "" { + return curval + } + return "" +} + +func (tk *guiWidget) Visible() bool { + if tk == nil { + return false + } + if tk.v == nil { + return false + } + tk.v.Visible = true + return true +} + +func (tk *guiWidget) Hide() { + tk.deleteView() +} + +func (tk *guiWidget) SetVisible(b bool) { + if b { + tk.Show() + } else { + tk.Hide() + } +} diff --git a/widgetDraw.go b/widgetDraw.go new file mode 100644 index 0000000..d678678 --- /dev/null +++ b/widgetDraw.go @@ -0,0 +1,271 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "errors" + "fmt" + "strconv" + + "github.com/awesome-gocui/gocui" + log "go.wit.com/log" + "go.wit.com/widget" +) + +// don't draw widgets that are too far down the window +func (tk *guiWidget) doNotDraw() bool { + var check bool + switch tk.WidgetType() { + case widget.Button: + check = true + case widget.Label: + check = true + default: + } + if !check { + return false + } + win := tk.findParentWindow() + if win == nil { + // don't draw anything if you can't find the parent window + return true + } + + h := tk.gocuiSize.h0 - win.gocuiSize.h0 + + if h > 20 { + return true + } + + return false +} + +// page widgets in the window +func (tk *guiWidget) pageWidget() *rectType { + r := new(rectType) + + var check bool + switch tk.WidgetType() { + case widget.Button: + check = true + case widget.Label: + check = true + default: + } + if !check { + return nil + } + win := tk.findParentWindow() + if win == nil { + // don't draw anything if you can't find the parent window + return nil + } + + r.w0 = tk.gocuiSize.w0 + r.h0 = tk.gocuiSize.h0 + r.w1 = tk.gocuiSize.w1 + r.h1 = tk.gocuiSize.h1 + + // r.h0 = tk.gocuiSize.h0 - win.gocuiSize.h0 + + if r.h0 > 20 { + return r + } + + return r +} + +// display's the text of the widget in gocui +// deletes the old view if it exists and recreates it +func (tk *guiWidget) drawView() { + var err error + log.Log(INFO, "drawView() START", tk.WidgetType(), tk.String()) + if me.baseGui == nil { + log.Log(ERROR, "drawView() ERROR: me.baseGui == nil", tk) + return + } + + if tk.cuiName == "" { + log.Log(ERROR, "drawView() tk.cuiName was not set for widget", tk) + tk.cuiName = strconv.Itoa(tk.WidgetId()) + " TK" + } + log.Log(INFO, "drawView() labelN =", tk.labelN) + + // this deletes the button from gocui + me.baseGui.DeleteView(tk.cuiName) + tk.v = nil + + a := tk.gocuiSize.w0 + b := tk.gocuiSize.h0 + c := tk.gocuiSize.w1 + d := tk.gocuiSize.h1 + + /* + // testing code for paging large windows + if tk.doNotDraw() { + return + } + + if tk.window.pager != 0 { + if r := tk.pageWidget(); r == nil { + // if nil, draw whatever it is anyway + } else { + if r.Width() == 0 && r.Height() == 0 { + // don't draw empty stuff + return + } + a = r.w0 + b = r.h0 + c = r.w1 + d = r.h1 + } + } + + if tk.WidgetType() == widget.Window || tk.WidgetType() == widget.Flag { + if tk.window.pager != 0 { + if tk.gocuiSize.Height() > 40 { + tk.window.large = true + tk.gocuiSize.h1 = tk.gocuiSize.h0 + 40 + d = tk.gocuiSize.h1 + } + } + } + */ + + // this is all terrible. This sets the title. kinda + if tk.WidgetType() == widget.Window { + tk.textResize() + tk.full.w0 = tk.force.w0 + tk.full.h0 = tk.force.h0 + + // for windows, make it the full size + a = tk.full.w0 + b = tk.full.h0 + c = tk.full.w0 + tk.gocuiSize.Width() + d = tk.full.h0 + tk.gocuiSize.Height() + } else { + if tk.internal { + // do nothing + } else { + tk.textResize() // resize gocui frame to the widget text + } + a = tk.gocuiSize.w0 + b = tk.gocuiSize.h0 + c = tk.gocuiSize.w1 + d = tk.gocuiSize.h1 + } + + tk.v, err = me.baseGui.SetView(tk.cuiName, a, b, c, d, 0) + if err == nil { + tk.dumpWidget("drawView() err") + log.Log(ERROR, "drawView() internal plugin error err = nil") + return + } + + if !errors.Is(err, gocui.ErrUnknownView) { + tk.dumpWidget("drawView() err") + log.Log(ERROR, "drawView() internal plugin error error.IS()", err) + return + } + + if tk.v == nil { + log.Info("MUTEX FAIL. tk.v == nil here in drawView()") + log.Info("MUTEX FAIL. tk.v == nil here in drawView()") + log.Info("MUTEX FAIL. tk.v == nil here in drawView()") + return + } + + // this actually sends the text to display to gocui + tk.v.Wrap = true + tk.v.Frame = tk.frame + tk.v.Clear() + fmt.Fprint(tk.v, tk.labelN) + + // tmp hack to disable buttons on window open + if tk.WidgetType() == widget.Button { + if tk.IsEnabled() { + } else { + tk.setColorDisable() + } + } + + switch tk.WidgetType() { + case widget.Button: + if tk.IsEnabled() { + if tk.isWindowDense() && tk.isInGrid() { + tk.setColorButtonDense() + } else { + tk.setColorButton() + } + } else { + tk.setColorDisable() + } + default: + } + + if tk.v == nil { + log.Info("MUTEX FAIL 2. tk.v was deleted somehow tk.v == nil here in drawView()") + log.Info("MUTEX FAIL 2. tk.v == nil here in drawView()") + log.Info("MUTEX FAIL 2. tk.v == nil here in drawView()") + return + } + + // if you don't do this here, it will be black & white only + if tk.color != nil { + tk.v.FrameColor = tk.color.frame + tk.v.FgColor = tk.color.fg + tk.v.BgColor = tk.color.bg + tk.v.SelFgColor = tk.color.selFg + tk.v.SelBgColor = tk.color.selBg + } + + log.Log(INFO, "drawView() END") +} + +func (w *guiWidget) DrawAt(offsetW, offsetH int) { + // w.setColor(&colorActiveW) + w.placeWidgets(offsetW, offsetH) // compute the sizes & places for each widget + // w.dumpWidget(fmt.Sprintf("DrawAt(%d,%d)", offsetW, offsetH)) +} + +func (w *guiWidget) simpleDrawAt(offsetW, offsetH int) { + // w.setColor(&colorActiveW) + w.dumpWidget("simpleDrawAt()") +} + +// display the widgets in the binary tree +func (w *guiWidget) drawTree(draw bool) { + if w == nil { + return + } + w.dumpWidget("in drawTree()") + if draw { + // w.textResize() + w.Show() + } else { + w.Hide() + } + + for _, child := range w.children { + child.drawTree(draw) + } +} + +func (w *guiWidget) Show() { + if w.isFake { + // don't display fake widgets + return + } + + if w.Hidden() { + // recursively checks if the parent is hidden + // never show hidden widgets + return + } + if me.debug { + w.dumpWidget("drawView()") + } + + w.drawView() +} -- cgit v1.2.3