summaryrefslogtreecommitdiff
path: root/toolkit/democui
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2023-03-29 23:03:04 -0500
committerJeff Carr <[email protected]>2023-03-29 23:03:04 -0500
commit4e28cde838683188bfbd9222746409538828592d (patch)
tree3c84fffc14352329bc41e6b58910ff278c99f08c /toolkit/democui
parentd4787a1ebdd08359746516dbb72f1feaf95be5b6 (diff)
add semi-working gocuiv0.7.4
commit 947169df5a22c9f9b53f825764747f648c70ff1e Author: Jeff Carr <[email protected]> Date: Wed Mar 29 22:44:08 2023 -0500 ready for version v0.7.4 start deprecating toolkit.Widget switch to variable name 'ParentId' use 'ActionType' and 'WidgetType' preliminary redraw() final definition of variables 'Name' and 'Text' more cleaning of the code remove lots of dumb code bind 'd' key press to dump out debugging info early color handling in gocui! Signed-off-by: Jeff Carr <[email protected]> commit 6013fde8332e8ecbffaf1a0977ba2e1da8ea8775 Author: Jeff Carr <[email protected]> Date: Sun Mar 26 17:19:20 2023 -0500 improvements towards a working dns control panel democui has the help menu try to add mouse support to gocui make a direct access method Margin() and Pad() tests add SPEW also push devel branch to github Signed-off-by: Jeff Carr <[email protected]> commit 6f91f5e080e06cdc0f34b13d23e5fd16ea37259a Author: Jeff Carr <[email protected]> Date: Fri Mar 24 20:14:18 2023 -0500 starting to try safe chan and goroutines fix tab title's right before attempting to add chan goroutines removed "where" widget pointer box added to tab experiement with log as it's own repo Signed-off-by: Jeff Carr <[email protected]> Signed-off-by: Jeff Carr <[email protected]>
Diffstat (limited to 'toolkit/democui')
-rw-r--r--toolkit/democui/,191
-rw-r--r--toolkit/democui/Makefile4
-rw-r--r--toolkit/democui/click.go49
-rw-r--r--toolkit/democui/common.go90
-rw-r--r--toolkit/democui/debug.go163
-rw-r--r--toolkit/democui/help.go46
-rw-r--r--toolkit/democui/keybindings.go45
-rw-r--r--toolkit/democui/log.go131
-rw-r--r--toolkit/democui/main.go67
-rw-r--r--toolkit/democui/mouse.go196
-rw-r--r--toolkit/democui/plugin.go109
-rw-r--r--toolkit/democui/structs.go127
-rw-r--r--toolkit/democui/view.go317
13 files changed, 1135 insertions, 400 deletions
diff --git a/toolkit/democui/, b/toolkit/democui/,
new file mode 100644
index 0000000..762f8eb
--- /dev/null
+++ b/toolkit/democui/,
@@ -0,0 +1,191 @@
+// Copyright 2014 The gocui Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "log"
+
+ "github.com/awesome-gocui/gocui"
+)
+
+func main() {
+ g, err := gocui.NewGui(gocui.OutputNormal, true)
+ if err != nil {
+ log.Panicln(err)
+ }
+ defer g.Close()
+
+ g.Cursor = false
+ g.Mouse = true
+
+ g.SetManagerFunc(layout)
+
+ if err := keybindings(g); err != nil {
+ log.Panicln(err)
+ }
+
+ if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
+ log.Panicln(err)
+ }
+}
+
+var initialMouseX, initialMouseY, xOffset, yOffset int
+var globalMouseDown, msgMouseDown, movingMsg bool
+
+func layout(g *gocui.Gui) error {
+ maxX, maxY := g.Size()
+ if _, err := g.View("msg"); msgMouseDown && err == nil {
+ moveMsg(g)
+ }
+ if v, err := g.SetView("global", -1, -1, maxX, maxY, 0); err != nil {
+ if !errors.Is(err, gocui.ErrUnknownView) {
+ return err
+ }
+ v.Frame = false
+ }
+ if v, err := g.SetView("but1", 2, 2, 22, 7, 0); err != nil {
+ if !errors.Is(err, gocui.ErrUnknownView) {
+ return err
+ }
+ v.SelBgColor = gocui.ColorGreen
+ v.SelFgColor = gocui.ColorBlack
+ fmt.Fprintln(v, "Button 1 - line 1")
+ fmt.Fprintln(v, "Button 1 - line 2")
+ fmt.Fprintln(v, "Button 1 - line 3")
+ fmt.Fprintln(v, "Button 1 - line 4")
+ if _, err := g.SetCurrentView("but1"); err != nil {
+ return err
+ }
+ }
+ if v, err := g.SetView("but2", 24, 2, 44, 4, 0); err != nil {
+ if !errors.Is(err, gocui.ErrUnknownView) {
+ return err
+ }
+ v.SelBgColor = gocui.ColorGreen
+ v.SelFgColor = gocui.ColorBlack
+ fmt.Fprintln(v, "Button 2 - line 1")
+ }
+ updateHighlightedView(g)
+ return nil
+}
+
+func keybindings(g *gocui.Gui) error {
+ if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
+ return err
+ }
+ for _, n := range []string{"but1", "but2"} {
+ if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil {
+ return err
+ }
+ }
+ if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil {
+ return err
+ }
+ if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil {
+ return err
+ }
+ if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil {
+ return err
+ }
+ return nil
+}
+
+func quit(g *gocui.Gui, v *gocui.View) error {
+ return gocui.ErrQuit
+}
+
+func showMsg(g *gocui.Gui, v *gocui.View) error {
+ var l string
+ var err error
+
+ if _, err := g.SetCurrentView(v.Name()); err != nil {
+ return err
+ }
+
+ _, cy := v.Cursor()
+ if l, err = v.Line(cy); err != nil {
+ l = ""
+ }
+
+ maxX, maxY := g.Size()
+ if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) {
+ v.Clear()
+ v.SelBgColor = gocui.ColorCyan
+ v.SelFgColor = gocui.ColorBlack
+ fmt.Fprintln(v, l)
+ }
+ return nil
+}
+
+func updateHighlightedView(g *gocui.Gui) {
+ mx, my := g.MousePosition()
+ for _, view := range g.Views() {
+ view.Highlight = false
+ }
+ if v, err := g.ViewByPosition(mx, my); err == nil {
+ v.Highlight = true
+ }
+}
+
+func moveMsg(g *gocui.Gui) {
+ mx, my := g.MousePosition()
+ if !movingMsg && (mx != initialMouseX || my != initialMouseY) {
+ movingMsg = true
+ }
+ g.SetView("msg", mx-xOffset, my-yOffset, mx-xOffset+20, my-yOffset+2, 0)
+}
+
+func msgDown(g *gocui.Gui, v *gocui.View) error {
+ initialMouseX, initialMouseY = g.MousePosition()
+ if vx, vy, _, _, err := g.ViewPosition("msg"); err == nil {
+ xOffset = initialMouseX - vx
+ yOffset = initialMouseY - vy
+ msgMouseDown = true
+ }
+ return nil
+}
+
+func globalDown(g *gocui.Gui, v *gocui.View) error {
+ mx, my := g.MousePosition()
+ if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil {
+ if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 {
+ return msgDown(g, v)
+ }
+ }
+ globalMouseDown = true
+ maxX, _ := g.Size()
+ msg := fmt.Sprintf("Mouse down at: %d,%d", mx, my)
+ x := mx - len(msg)/2
+ if x < 0 {
+ x = 0
+ } else if x+len(msg)+1 > maxX-1 {
+ x = maxX - 1 - len(msg) - 1
+ }
+ if v, err := g.SetView("globalDown", x, my-1, x+len(msg)+1, my+1, 0); err != nil {
+ if !errors.Is(err, gocui.ErrUnknownView) {
+ return err
+ }
+ v.WriteString(msg)
+ }
+ return nil
+}
+
+func mouseUp(g *gocui.Gui, v *gocui.View) error {
+ if msgMouseDown {
+ msgMouseDown = false
+ if movingMsg {
+ movingMsg = false
+ return nil
+ } else {
+ g.DeleteView("msg")
+ }
+ } else if globalMouseDown {
+ globalMouseDown = false
+ g.DeleteView("globalDown")
+ }
+ return nil
+}
diff --git a/toolkit/democui/Makefile b/toolkit/democui/Makefile
index 6f3f7d9..96b8928 100644
--- a/toolkit/democui/Makefile
+++ b/toolkit/democui/Makefile
@@ -9,3 +9,7 @@ plugin:
objdump:
objdump -t ../democui.so |less
+
+log:
+ reset
+ tail -f /tmp/witgui.* /tmp/guilogfile
diff --git a/toolkit/democui/click.go b/toolkit/democui/click.go
new file mode 100644
index 0000000..adc611c
--- /dev/null
+++ b/toolkit/democui/click.go
@@ -0,0 +1,49 @@
+package main
+
+import (
+ "fmt"
+ "errors"
+ "strconv"
+
+ "github.com/awesome-gocui/gocui"
+ // "git.wit.org/wit/gui/toolkit"
+)
+
+func click(g *gocui.Gui, v *gocui.View) error {
+ var l string
+ var err error
+
+ log(logNow, "click() START", v.Name())
+ i, err := strconv.Atoi(v.Name())
+ if (err != nil) {
+ log(logNow, "click() Can't find widget. error =", err)
+ } else {
+ log(logNow, "click() Found widget id =", i)
+ if (me.widgets[i] != nil) {
+ w := me.widgets[i]
+ log(logNow, "click() Found widget =", w)
+ }
+ }
+
+ if _, err := g.SetCurrentView(v.Name()); err != nil {
+ return err
+ }
+
+ _, cy := v.Cursor()
+ if l, err = v.Line(cy); err != nil {
+ l = ""
+ }
+
+ maxX, maxY := g.Size()
+ if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) {
+ v.Clear()
+ v.SelBgColor = gocui.ColorCyan
+ v.SelFgColor = gocui.ColorBlack
+ fmt.Fprintln(v, l)
+ }
+
+ // this seems to delete the button(?)
+ // g.SetViewOnBottom(v.Name())
+ log(logNow, "click() END")
+ return nil
+}
diff --git a/toolkit/democui/common.go b/toolkit/democui/common.go
new file mode 100644
index 0000000..799ac9c
--- /dev/null
+++ b/toolkit/democui/common.go
@@ -0,0 +1,90 @@
+package main
+
+import (
+ "github.com/awesome-gocui/gocui"
+ "git.wit.org/wit/gui/toolkit"
+)
+
+func setupWidgetT(a *toolkit.Action) *cuiWidget {
+ var w *cuiWidget
+ w = new(cuiWidget)
+
+ w.name = a.Name
+ w.text = a.Text
+
+ w.widgetType = a.WidgetType
+ w.id = a.WidgetId
+ if (w.id > me.highest) {
+ me.highest = w.id
+ }
+ w.parentId = a.ParentId
+ me.widgets[w.id] = w
+
+ // w.showWidgetPlacement(logNow)
+ return w
+}
+
+// ColorBlack ColorRed ColorGreen ColorYellow ColorBlue ColorMagenta ColorCyan ColorWhite
+// gocui.GetColor("#FFAA55") // Dark Purple
+func (w *cuiWidget) SetDefaultWidgetColor() {
+ log(logInfo, "SetDefaultWidgetColor() on", w.widgetType, w.name)
+ if (w.v == nil) {
+ log(logError, "SetDefaultWidgetColor() failed on view == nil")
+ return
+ }
+ w.SetDefaultHighlight()
+ switch w.widgetType {
+ case toolkit.Button:
+ w.v.BgColor = gocui.ColorGreen
+ w.v.FrameColor = gocui.ColorGreen
+ case toolkit.Checkbox:
+ w.v.BgColor = gocui.GetColor("#FFAA55") // Dark Purple
+ w.v.FrameColor = gocui.GetColor("#FFEE11")
+ case toolkit.Dropdown:
+ w.v.BgColor = gocui.ColorCyan
+ w.v.FrameColor = gocui.ColorGreen
+ case toolkit.Textbox:
+ w.v.BgColor = gocui.ColorYellow
+ w.v.FrameColor = gocui.ColorGreen
+ case toolkit.Slider:
+ w.v.BgColor = gocui.GetColor("#FFAA55") // Dark Purple
+ w.v.FrameColor = gocui.ColorRed
+ case toolkit.Label:
+ w.v.FrameColor = gocui.ColorRed
+ default:
+ w.v.BgColor = gocui.ColorYellow
+ }
+}
+
+// SetColor("#FFAA55") // purple
+func (w *cuiWidget) SetColor(c string) {
+ if (w.v == nil) {
+ log(logError, "SetColor() failed on view == nil")
+ return
+ }
+ w.v.SelBgColor = gocui.ColorCyan
+ w.v.SelFgColor = gocui.ColorBlack
+ switch c {
+ case "Green":
+ w.v.BgColor = gocui.ColorGreen
+ case "Purple":
+ w.v.BgColor = gocui.GetColor("#FFAA55")
+ case "Yellow":
+ w.v.BgColor = gocui.ColorYellow
+ case "Blue":
+ w.v.BgColor = gocui.ColorBlue
+ case "Red":
+ w.v.BgColor = gocui.ColorRed
+ default:
+ w.v.BgColor = gocui.GetColor(c)
+ }
+}
+
+func (w *cuiWidget) SetDefaultHighlight() {
+ if (w.v == nil) {
+ log(logError, "SetColor() failed on view == nil")
+ return
+ }
+ w.v.SelBgColor = gocui.ColorGreen
+ w.v.SelFgColor = gocui.ColorBlack
+}
diff --git a/toolkit/democui/debug.go b/toolkit/democui/debug.go
index d024925..bb2a06d 100644
--- a/toolkit/democui/debug.go
+++ b/toolkit/democui/debug.go
@@ -1,86 +1,46 @@
package main
-import "git.wit.org/wit/gui/toolkit"
+import (
+ "fmt"
+ "strconv"
-var defaultBehavior bool = true
+ "git.wit.org/wit/gui/toolkit"
+ "github.com/awesome-gocui/gocui"
+)
-var bookshelf bool // do you want things arranged in the box like a bookshelf or a stack?
-var canvas bool // if set to true, the windows are a raw canvas
-var menubar bool // for windows
-var stretchy bool // expand things like buttons to the maximum size
-var padded bool // add space between things like buttons
-var margin bool // add space around the frames of windows
-
-var debugToolkit bool
-var debugChange bool
-var debugPlugin bool
-var debugFlags bool
-var debugError bool = true
+// var debugError bool = true
// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
func setDefaultBehavior(s bool) {
- defaultBehavior = s
- if (defaultBehavior) {
- log(debugToolkit, "Setting this toolkit to use the default behavior.")
- log(debugToolkit, "This is the 'guessing' part as defined by the wit/gui 'Principles'. Refer to the docs.")
- stretchy = false
- padded = true
- menubar = true
- margin = true
- canvas = false
- bookshelf = true // 99% of the time, things make a vertical stack of objects
+ me.defaultBehavior = s
+ if (me.defaultBehavior) {
+ log(logInfo, "Setting this toolkit to use the default behavior.")
+ log(logInfo, "This is the 'guessing' part as defined by the wit/gui 'Principles'. Refer to the docs.")
+ me.stretchy = false
+ me.padded = true
+ me.menubar = true
+ me.margin = true
+ me.canvas = false
+ me.bookshelf = true // 99% of the time, things make a vertical stack of objects
} else {
- log(debugToolkit, "This toolkit is set to ignore the default behavior.")
+ log(logInfo, "This toolkit is set to ignore the default behavior.")
}
}
-func ShowDebug () {
- log(true, "debugToolkit =", debugToolkit)
- log(true, "debugChange =", debugChange)
- log(true, "debugPlugin =", debugPlugin)
- log(true, "debugFlags =", debugFlags)
- log(true, "debugError =", debugError)
-}
-
-/*
-func (t *gocuiT) Dump(b bool) {
- if ! b {
+func actionDump(b bool, a *toolkit.Action) {
+ if (a == nil) {
+ log(b, "action = nil")
return
}
- log(b, "Name = ", t.Name, t.Width, t.Height)
- if (t.uiBox != nil) {
- log(b, "uiBox =", t.uiBox)
- }
- if (t.uiButton != nil) {
- log(b, "uiButton =", t.uiButton)
- }
- if (t.uiCombobox != nil) {
- log(b, "uiCombobox =", t.uiCombobox)
- }
- if (t.uiWindow != nil) {
- log(b, "uiWindow =", t.uiWindow)
- }
- if (t.uiTab != nil) {
- log(b, "uiTab =", t.uiTab)
- }
- if (t.uiGroup != nil) {
- log(b, "uiGroup =", t.uiGroup)
- }
- if (t.uiEntry != nil) {
- log(b, "uiEntry =", t.uiEntry)
- }
- if (t.uiMultilineEntry != nil) {
- log(b, "uiMultilineEntry =", t.uiMultilineEntry)
- }
- if (t.uiSlider != nil) {
- log(b, "uiSlider =", t.uiSlider)
- }
- if (t.uiCheckbox != nil) {
- log(b, "uiCheckbox =", t.uiCheckbox)
- }
- widgetDump(b, t.tw)
+
+ log(b, "a.Name =", a.Name)
+ log(b, "a.Text =", a.Text)
+ log(b, "a.WidgetId =", a.WidgetId)
+ log(b, "a.ParentId =", a.ParentId)
+ log(b, "a.B =", a.B)
+ log(b, "a.S =", a.S)
+ widgetDump(b, a.Widget)
}
-*/
func widgetDump(b bool, w *toolkit.Widget) {
if (w == nil) {
@@ -88,6 +48,7 @@ func widgetDump(b bool, w *toolkit.Widget) {
return
}
+ /*
log(b, "widget.Name =", w.Name)
log(b, "widget.Type =", w.Type)
log(b, "widget.Custom =", w.Custom)
@@ -97,10 +58,66 @@ func widgetDump(b bool, w *toolkit.Widget) {
log(b, "widget.Height =", w.Height)
log(b, "widget.X =", w.X)
log(b, "widget.Y =", w.Y)
+ */
+}
+
+func dumpWidgets(g *gocui.Gui, v *gocui.View) {
+ for _, view := range g.Views() {
+ i, _ := strconv.Atoi(view.Name())
+ if (me.widgets[i] != nil) {
+ continue
+ }
+ log(logNow, "dump() not a widget. view.Name =", view.Name())
+ }
+
+ for i := 0; i <= me.highest; i++ {
+ w := me.widgets[i]
+ if (w == nil) {
+ continue
+ }
+ w.showWidgetPlacement(logNow, "")
+
+ if (w.v == nil) {
+ log(logError, "dump() ERROR w.v == nil")
+ } else {
+ if (strconv.Itoa(i) != w.v.Name()) {
+ log(logError, "dump() ERROR unequal str.Itoa(i) =", strconv.Itoa(i))
+ log(logError, "dump() ERROR unequal w.v.Name() =", w.v.Name())
+ }
+ }
+ }
+}
+
+func adjustWidgets() {
+ for i := 0; i <= me.highest; i++ {
+ w := me.widgets[i]
+ if (w == nil) {
+ continue
+ }
+ p := me.widgets[w.parentId]
+ if (p != nil) {
+ w.setParentLogical(p)
+ }
+ }
}
-/*
-func GetDebugToolkit () bool {
- return debugToolkit
+func (w *cuiWidget) showWidgetPlacement(b bool, s string) {
+ log(b, "dump()", s,
+ fmt.Sprintf("(wId,pId)=(%3d,%3d)", w.id, w.parentId),
+ fmt.Sprintf("real()=(%3d,%3d,%3d,%3d)", w.realSize.w0, w.realSize.h0, w.realSize.w1, w.realSize.h1),
+ "next()=(", w.nextX, ",", w.nextY, ")",
+ "logical()=(", w.logicalSize.w0, ",", w.logicalSize.h0, ",", w.logicalSize.w1, ",", w.logicalSize.h1, ")",
+ w.widgetType, ",", w.name)
+ if (w.realWidth != (w.realSize.w1 - w.realSize.w0)) {
+ log(b, "dump()", s,
+ "badsize()=(", w.realWidth, ",", w.realHeight, ")",
+ "badreal()=(", w.realSize.w0, ",", w.realSize.h0, ",", w.realSize.w1, ",", w.realSize.h1, ")",
+ w.widgetType, ",", w.name)
+ }
+ if (w.realHeight != (w.realSize.h1 - w.realSize.h0)) {
+ log(b, "dump()", s,
+ "badsize()=(", w.realWidth, ",", w.realHeight, ")",
+ "badreal()=(", w.realSize.w0, ",", w.realSize.h0, ",", w.realSize.w1, ",", w.realSize.h1, ")",
+ w.widgetType, ",", w.name)
+ }
}
-*/
diff --git a/toolkit/democui/help.go b/toolkit/democui/help.go
new file mode 100644
index 0000000..f012fef
--- /dev/null
+++ b/toolkit/democui/help.go
@@ -0,0 +1,46 @@
+// Copyright 2014 The gocui Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/awesome-gocui/gocui"
+)
+
+func addHelp() {
+ me.baseGui.SetManagerFunc(helplayout)
+}
+
+func helplayout(g *gocui.Gui) error {
+ var err error
+ maxX, _ := g.Size()
+
+ help, err := g.SetView("help", maxX-32, 0, maxX-1, 12, 0)
+ if err != nil {
+ if !errors.Is(err, gocui.ErrUnknownView) {
+ return err
+ }
+ help.SelBgColor = gocui.ColorGreen
+ help.SelFgColor = gocui.ColorBlack
+ fmt.Fprintln(help, "KEYBINDINGS")
+ fmt.Fprintln(help, "Enter: Click Button")
+ fmt.Fprintln(help, "Tab/Space: Switch Buttons")
+ fmt.Fprintln(help, "")
+ fmt.Fprintln(help, "h: Help")
+ fmt.Fprintln(help, "Backspace: Delete Button")
+ fmt.Fprintln(help, "Arrow keys: Move Button")
+ fmt.Fprintln(help, "t: Move Button to the top")
+ fmt.Fprintln(help, "b: Move Button to the button")
+ fmt.Fprintln(help, "STDOUT: /tmp/witgui.log")
+ fmt.Fprintln(help, "Ctrl-C or Q: Exit")
+ if _, err := g.SetCurrentView("help"); err != nil {
+ return err
+ }
+ }
+ me.helpLabel = help
+ return nil
+}
diff --git a/toolkit/democui/keybindings.go b/toolkit/democui/keybindings.go
new file mode 100644
index 0000000..8e5e937
--- /dev/null
+++ b/toolkit/democui/keybindings.go
@@ -0,0 +1,45 @@
+// Copyright 2014 The gocui Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "github.com/awesome-gocui/gocui"
+)
+
+func defaultKeybindings(g *gocui.Gui) error {
+ if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
+ return err
+ }
+ for _, n := range []string{"but1", "but2", "help", "but3"} {
+ if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil {
+ return err
+ }
+ }
+ if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil {
+ return err
+ }
+ if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil {
+ return err
+ }
+ if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil {
+ return err
+ }
+ addDebugKeys(g)
+ return nil
+}
+
+// dump out the widgets
+func addDebugKeys(g *gocui.Gui) {
+ g.SetKeybinding("", 'd', gocui.ModNone,
+ func(g *gocui.Gui, v *gocui.View) error {
+ dumpWidgets(g, v)
+ return nil
+ })
+ g.SetKeybinding("", 'r', gocui.ModNone,
+ func(g *gocui.Gui, v *gocui.View) error {
+ adjustWidgets()
+ return nil
+ })
+}
diff --git a/toolkit/democui/log.go b/toolkit/democui/log.go
index afd1280..2d7e27e 100644
--- a/toolkit/democui/log.go
+++ b/toolkit/democui/log.go
@@ -1,135 +1,30 @@
-//
-// version v1.3
-//
-// I like things to be easy.
-//
-// combining logging inside of a gui made me do this
-//
-// this means all the log settings are in one place. it should allow
-// things to be over-ridden externally to the library
-// but still allow command line --args to pass debugging settings
-//
-// I also have a generic sleep() and exit() in here because it's simple
-//
-// Usage:
-//
-// log("something", foo, bar)
-// var DEBUG bool = true
-// log(DEBUG, "something else", someOtherVariable) # if DEBUG == false, return doing nothing
-// log(SPEW, "something else", someOtherVariable) # this get's sent to spew.Dump(). Very useful for debugging!
-//
package main
import (
"os"
- golog "log"
- "time"
- "reflect"
- "github.com/davecgh/go-spew/spew"
+ witlog "git.wit.org/wit/gui/log"
)
-var LOGOFF bool = false // turn this off, all logging stops
-var WARN bool
-var INFO bool
+// various debugging flags
+var logNow bool = true // useful for active development
+var logError bool = true
+var logWarn bool = false
+var logInfo bool = false
+var logVerbose bool = false
-type spewt struct {
- a bool
+func log(a ...any) {
+ witlog.Where = "wit/democui"
+ witlog.Log(a...)
}
-var SPEW spewt
-
-
-/*
- sleep() # you know what this does? sleeps for 1 second. yep. dump. easy.
- sleep(.1) # you know what this does? yes, it sleeps for 1/10th of a second
-*/
func sleep(a ...any) {
- if (a == nil) {
- time.Sleep(time.Second)
- return
- }
-
- log(true, "sleep", a[0])
-
- switch a[0].(type) {
- case int:
- time.Sleep(time.Duration(a[0].(int)) * time.Second)
- case float64:
- time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond)
- default:
- log("sleep a[0], type = ", a[0], reflect.TypeOf(a[0]))
- }
+ witlog.Sleep(a...)
}
-/*
- exit() # yep. exits. I guess everything must be fine
- exit(3) # I guess 3 it is then
- exit("dont like apples") # ok. I'll make a note of that
-*/
func exit(a ...any) {
- log(true, "exit", a)
- //if (a) {
- // os.Exit(a)
- //}
- os.Exit(0)
-}
-
-/*
- I've spent, am spending, too much time thinking about 'logging'. 'log', 'logrus', 'zap', whatever.
- I'm not twitter. i don't give a fuck about how many nanoseconds it takes to log. Anyway, this
- implementation is probably faster than all of those because you just set one bool to FALSE
- and it all stops.
- Sometimes I need to capture to stdout, sometimes stdout can't
- work because it doesn't exist for the user. This whole thing is a PITA. Then it's spread
- over 8 million references in every .go file. I'm tapping out and putting
- it in one place. here it is. Also, this makes having debug levels really fucking easy.
- You can define whatever level of logging you want from anywhere (command line) etc.
-
- log() # doesn't do anything
- log(stuff) # sends it to whatever log you define in a single place. here is the place
-*/
-
-func log(a ...any) {
- if (LOGOFF) {
- return
- }
-
- if (a == nil) {
- return
- }
- var tbool bool
- if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) {
- if (a[0] == false) {
- return
- }
- a[0] = "GUI/Toolkit/gocui"
- }
-
- if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) {
- // a = a[1:]
- a[0] = "GUI/Toolkit/gocui"
- if (debugToolkit) {
- scs := spew.ConfigState{MaxDepth: 1}
- scs.Dump(a)
- // spew.Dump(a)
- }
- return
- }
-
- golog.Println(a...)
-}
-
-func logindent(depth int, format string, a ...interface{}) {
- var tabs string
- for i := 0; i < depth; i++ {
- tabs = tabs + format
- }
-
- // newFormat := tabs + strconv.Itoa(depth) + " " + format
- newFormat := tabs + format
- log(debugToolkit, newFormat, a)
+ witlog.Exit(a...)
}
func setOutput(f *os.File) {
- golog.SetOutput(f)
+ witlog.SetOutput(f)
}
diff --git a/toolkit/democui/main.go b/toolkit/democui/main.go
new file mode 100644
index 0000000..19b326d
--- /dev/null
+++ b/toolkit/democui/main.go
@@ -0,0 +1,67 @@
+// Copyright 2014 The gocui Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os"
+)
+
+/*
+func OnExit(f func(string)) {
+ Custom = f
+}
+*/
+
+func Init() {
+ log(logInfo, "Init() of democui")
+ me.widgets = make(map[int]*cuiWidget)
+ me.defaultWidth = 10
+ me.defaultHeight = 2
+ me.defaultBehavior = true
+}
+
+func Exit() {
+ // TODO: exit correctly
+ me.baseGui.Close()
+}
+
+/*
+func mouseClick(name string) {
+ // output screws up the console. Need to fix this by redirecting all console output to a file from log.Println()
+ // log.Println("g.Close()")
+ // g.Close()
+
+ log("Found andlabs Running custom function for the mouse click")
+ Custom(name)
+ // panic("got andlabs")
+}
+*/
+
+func Main(f func()) {
+ log("start Init()")
+
+ outf, err := os.OpenFile("/tmp/witgui.log", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
+ if err != nil {
+ exit("error opening file: %v", err)
+ }
+ defer outf.Close()
+
+ setOutput(outf)
+ log("This is a test log entry")
+
+ MouseMain()
+}
+
+/*
+func StartConsoleMouse() {
+ defer g.Close()
+ log("start Main()")
+
+ if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
+ exit(err)
+ }
+ log("exit Main()")
+}
+*/
diff --git a/toolkit/democui/mouse.go b/toolkit/democui/mouse.go
index efda307..fc74d27 100644
--- a/toolkit/democui/mouse.go
+++ b/toolkit/democui/mouse.go
@@ -7,146 +7,68 @@ package main
import (
"errors"
"fmt"
- "os"
"github.com/awesome-gocui/gocui"
)
-var g *gocui.Gui
-var err error
-var Custom func(string)
-
-func OnExit(f func(string)) {
- Custom = f
-}
-
-func Exit() {
- g.Close()
-}
-
-func mouseClick(name string) {
- // output screws up the console. Need to fix this by redirecting all console output to a file from log.Println()
- // log.Println("g.Close()")
- // g.Close()
-
- log("Found andlabs Running custom function for the mouse click")
- Custom(name)
- // panic("got andlabs")
-}
-
-func Init() {
- log("start Init()")
-
- f, err := os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
+func MouseMain() {
+ g, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
- exit("error opening file: %v", err)
+ panic(err)
}
- defer f.Close()
-
- setOutput(f)
- log("This is a test log entry")
+ defer g.Close()
- g, err = gocui.NewGui(gocui.OutputNormal, true)
- if err != nil {
- exit(err)
- }
+ me.baseGui = g
g.Cursor = true
g.Mouse = true
g.SetManagerFunc(layout)
- if err := keybindings(g); err != nil {
- exit(err)
+ if err := defaultKeybindings(g); err != nil {
+ panic(err)
}
- log("exit Init()")
-}
-
-func StartConsoleMouse() {
- defer g.Close()
- log("start Main()")
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
- exit(err)
+ panic(err)
}
- log("exit Main()")
}
func layout(g *gocui.Gui) error {
- if v, err := g.SetView("but1", 2, 2, 22, 17, 0); err != nil {
- if !errors.Is(err, gocui.ErrUnknownView) {
- return err
- }
- v.Highlight = true
- v.SelBgColor = gocui.ColorGreen
- v.SelFgColor = gocui.ColorBlack
- fmt.Fprintln(v, "andlabs")
- fmt.Fprintln(v, "addDemoTab")
- fmt.Fprintln(v, "DemoToolkitWindow")
- fmt.Fprintln(v, "DebugWindow")
- fmt.Fprintln(v, "do nothing")
- fmt.Fprintln(v, "exit")
- if _, err := g.SetCurrentView("but1"); err != nil {
- return err
- }
+ maxX, maxY := g.Size()
+ if _, err := g.View("msg"); msgMouseDown && err == nil {
+ moveMsg(g)
}
- if v, err := g.SetView("but2", 24, 2, 44, 4, 0); err != nil {
+ if v, err := g.SetView("global", -1, -1, maxX, maxY, 0); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
- v.Highlight = true
- v.SelBgColor = gocui.ColorGreen
- v.SelFgColor = gocui.ColorBlack
- fmt.Fprintln(v, "Button 2 - line 1")
+ v.Frame = false
}
- if v, err := g.SetView("but3", 24, 2, 44, 4, 0); err != nil {
+ if v, err := g.SetView("but1", 2, 2, 22, 7, 0); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
- v.Highlight = true
v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack
- fmt.Fprintln(v, "Button 2 - line 1")
- }
- if v, err := g.SetView("but4", 24, 2, 44, 4, 0); err != nil {
- if !errors.Is(err, gocui.ErrUnknownView) {
+ fmt.Fprintln(v, "Button 1 - line 1")
+ fmt.Fprintln(v, "Button 1 - line 2")
+ fmt.Fprintln(v, "Button 1 - line 3")
+ fmt.Fprintln(v, "Button 1 - line 4")
+ if _, err := g.SetCurrentView("but1"); err != nil {
return err
}
- v.Highlight = true
- v.SelBgColor = gocui.ColorGreen
- v.SelFgColor = gocui.ColorBlack
- fmt.Fprintln(v, "Button 2 - line 1")
}
- if v, err := g.SetView("but5", 24, 2, 44, 4, 0); err != nil {
+ if v, err := g.SetView("but2", 24, 2, 44, 4, 0); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
- v.Highlight = true
v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack
fmt.Fprintln(v, "Button 2 - line 1")
}
- return nil
-}
-
-func keybindings(g *gocui.Gui) error {
- if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
- return err
- }
- for _, n := range []string{"but1", "but2"} {
- if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil {
- return err
- }
- }
- if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, delMsg); err != nil {
- return err
- }
- if err := g.SetKeybinding("", gocui.MouseRight, gocui.ModNone, delMsg); err != nil {
- return err
- }
- if err := g.SetKeybinding("", gocui.MouseMiddle, gocui.ModNone, delMsg); err != nil {
- return err
- }
+ helplayout(g)
+ updateHighlightedView(g)
return nil
}
@@ -168,18 +90,80 @@ func showMsg(g *gocui.Gui, v *gocui.View) error {
}
maxX, maxY := g.Size()
- if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err != nil {
+ if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) {
+ v.Clear()
+ v.SelBgColor = gocui.ColorCyan
+ v.SelFgColor = gocui.ColorBlack
+ fmt.Fprintln(v, l)
+ }
+ return nil
+}
+
+func updateHighlightedView(g *gocui.Gui) {
+ mx, my := g.MousePosition()
+ for _, view := range g.Views() {
+ view.Highlight = false
+ }
+ if v, err := g.ViewByPosition(mx, my); err == nil {
+ v.Highlight = true
+ }
+}
+
+func moveMsg(g *gocui.Gui) {
+ mx, my := g.MousePosition()
+ if !movingMsg && (mx != initialMouseX || my != initialMouseY) {
+ movingMsg = true
+ }
+ g.SetView("msg", mx-xOffset, my-yOffset, mx-xOffset+20, my-yOffset+2, 0)
+}
+
+func msgDown(g *gocui.Gui, v *gocui.View) error {
+ initialMouseX, initialMouseY = g.MousePosition()
+ if vx, vy, _, _, err := g.ViewPosition("msg"); err == nil {
+ xOffset = initialMouseX - vx
+ yOffset = initialMouseY - vy
+ msgMouseDown = true
+ }
+ return nil
+}
+
+func globalDown(g *gocui.Gui, v *gocui.View) error {
+ mx, my := g.MousePosition()
+ if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil {
+ if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 {
+ return msgDown(g, v)
+ }
+ }
+ globalMouseDown = true
+ maxX, _ := g.Size()
+ msg := fmt.Sprintf("Mouse down at: %d,%d", mx, my)
+ x := mx - len(msg)/2
+ if x < 0 {
+ x = 0
+ } else if x+len(msg)+1 > maxX-1 {
+ x = maxX - 1 - len(msg) - 1
+ }
+ if v, err := g.SetView("globalDown", x, my-1, x+len(msg)+1, my+1, 0); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
- mouseClick(l)
- fmt.Fprintln(v, l)
+ v.WriteString(msg)
}
return nil
}
-func delMsg(g *gocui.Gui, v *gocui.View) error {
- // Error check removed, because delete could be called multiple times with the above keybindings
- g.DeleteView("msg")
+func mouseUp(g *gocui.Gui, v *gocui.View) error {
+ if msgMouseDown {
+ msgMouseDown = false
+ if movingMsg {
+ movingMsg = false
+ return nil
+ } else {
+ g.DeleteView("msg")
+ }
+ } else if globalMouseDown {
+ globalMouseDown = false
+ g.DeleteView("globalDown")
+ }
return nil
}
diff --git a/toolkit/democui/plugin.go b/toolkit/democui/plugin.go
index 2c0d42e..86125d4 100644
--- a/toolkit/democui/plugin.go
+++ b/toolkit/democui/plugin.go
@@ -4,112 +4,15 @@ import (
// if you include more than just this import
// then your plugin might be doing something un-ideal (just a guess from 2023/02/27)
"git.wit.org/wit/gui/toolkit"
-
- "github.com/awesome-gocui/gocui"
)
-// This is a map between the widgets in wit/gui and the internal structures of gocui
-var viewWidget map[*gocui.View]*toolkit.Widget
-var stringWidget map[string]*toolkit.Widget
-
func Quit() {
- g.Close()
-}
-
-// This lists out the know mappings
-func listMap() {
- for v, w := range viewWidget {
- log("view =", v.Name, "widget name =", w.Name)
- }
- for s, w := range stringWidget {
- log("string =", s, "widget =", w)
- }
+ me.baseGui.Close()
}
-
-//
-// This should be called ?
-// Pass() ?
-// This handles all interaction between the wit/gui package (what golang knows about)
-// and this plugin that talks to the OS and does scary and crazy things to make
-// a GUI on whatever OS or whatever GUI toolkit you might have (GTK, QT, WASM, libcurses)
-//
-// Once you are here, you should be in a protected goroutine created by the golang wit/gui package
-//
-// TODO: make sure you can't escape this goroutine
-//
-func Send(p *toolkit.Widget, c *toolkit.Widget) {
- if (p == nil) {
- log(debugPlugin, "Send() parent = nil")
- } else {
- log(debugPlugin, "Send() parent =", p.Name, ",", p.Type)
- }
- log(debugPlugin, "Send() child =", c.Name, ",", c.Type)
-
- /*
- if (c.Action == "SetMargin") {
- log(debugError, "need to implement SetMargin here")
- setMargin(c, c.B)
- return
- }
- */
-
- switch c.Type {
- /*
- case toolkit.Window:
- // doWindow(c)
- case toolkit.Tab:
- // doTab(p, c)
- case toolkit.Group:
- newGroup(p, c)
- case toolkit.Button:
- newButton(p, c)
- case toolkit.Checkbox:
- // doCheckbox(p, c)
- case toolkit.Label:
- // doLabel(p, c)
- case toolkit.Textbox:
- // doTextbox(p, c)
- case toolkit.Slider:
- // doSlider(p, c)
- case toolkit.Spinner:
- // doSpinner(p, c)
- case toolkit.Dropdown:
- // doDropdown(p, c)
- case toolkit.Combobox:
- // doCombobox(p, c)
- case toolkit.Grid:
- // doGrid(p, c)
- */
- /*
- case toolkit.Flag:
- // log(debugFlags, "plugin Send() flag parent =", p.Name, p.Type)
- // log(debugFlags, "plugin Send() flag child =", c.Name, c.Type)
- // log(debugFlags, "plugin Send() flag child.Action =", c.Action)
- // log(debugFlags, "plugin Send() flag child.S =", c.S)
- // log(debugFlags, "plugin Send() flag child.B =", c.B)
- // log(debugFlags, "plugin Send() what to flag?")
- // should set the checkbox to this value
- switch c.S {
- case "Toolkit":
- debugToolkit = c.B
- case "Change":
- debugChange = c.B
- case "Plugin":
- debugPlugin = c.B
- case "Flags":
- debugFlags = c.B
- case "Error":
- debugError = c.B
- case "Show":
- ShowDebug()
- default:
- log(debugError, "Can't set unknown flag", c.S)
- }
- */
- default:
- log(debugError, "plugin Send() unknown parent =", p.Name, p.Type)
- log(debugError, "plugin Send() unknown child =", c.Name, c.Type)
- log(debugError, "plugin Send() Don't know how to do", c.Type, "yet")
- }
+func Action(a *toolkit.Action) {
+ log(logNow, "Action()", a)
+ w := setupWidgetT(a)
+ place(w, a)
+ log(logInfo, "Action() END")
}
diff --git a/toolkit/democui/structs.go b/toolkit/democui/structs.go
new file mode 100644
index 0000000..37a8f28
--- /dev/null
+++ b/toolkit/democui/structs.go
@@ -0,0 +1,127 @@
+// LICENSE: same as the go language itself
+// Copyright 2023 WIT.COM
+
+// all structures and variables are local (aka lowercase)
+// since the plugin should be isolated to access only
+// by functions() to insure everything here is run
+// inside a dedicated goroutine
+
+package main
+
+import (
+ "fmt"
+ "sync"
+ "github.com/awesome-gocui/gocui"
+ "git.wit.org/wit/gui/toolkit"
+)
+
+// const delta = 1
+
+// It's probably a terrible idea to call this 'me'
+var me config
+
+type config struct {
+ highest int // highest widgetId
+ baseGui *gocui.Gui // the main gocui handle
+ widgets map[int]*cuiWidget
+ callback func(int)
+ helpLabel *gocui.View
+
+ defaultBehavior bool
+ defaultWidth int
+ defaultHeight int
+ nextW int // where the next window or tab flag should go
+
+ bookshelf bool // do you want things arranged in the box like a bookshelf or a stack?
+ canvas bool // if set to true, the windows are a raw canvas
+ menubar bool // for windows
+ stretchy bool // expand things like buttons to the maximum size
+ padded bool // add space between things like buttons
+ margin bool // add space around the frames of windows
+}
+
+/*
+// This is a map between the widgets in wit/gui and the internal structures of gocui
+var viewWidget map[*gocui.View]*toolkit.Widget
+var stringWidget map[string]*toolkit.Widget
+*/
+
+var (
+// g *gocui.Gui
+// Custom func(string)
+
+ initialMouseX, initialMouseY, xOffset, yOffset int
+ globalMouseDown, msgMouseDown, movingMsg bool
+
+// err error
+)
+
+// the gocui way
+// the logical size of the widget
+// corner starts at in the upper left corner
+type rectType struct {
+ // this is the gocui way
+ w0, h0, w1, h1 int // left top right bottom
+}
+
+/*
+type realSizeT struct {
+ width, height int
+}
+*/
+
+
+type cuiWidget struct {
+ id int // widget ID
+ parentId int
+ widgetType toolkit.WidgetType
+
+ name string // a descriptive name of the widget
+ text string // the current text being displayed
+
+ visable bool // widget types like 'box' are 'false'
+ realWidth int // the real width
+ realHeight int // the real height
+ realSize rectType // the display size of this widget
+ logicalSize rectType // the logical size. Includes all the child widgets
+
+ nextX int
+ nextY int
+
+ // horizontal=true means layout widgets like books on a bookshelf
+ // horizontal=false means layout widgets like books in a stack
+ horizontal bool `default:false`
+
+ tainted bool
+ v *gocui.View
+ baseGui *gocui.Gui // use gogui.Manager ? as 'workspaces?'
+
+ // writeMutex protects locks the write process
+ writeMutex sync.Mutex
+
+ // deprecate
+ // logicalWidth int `default:8`
+ // logicalHeight int `default:2`
+ // rect rectType
+ // current rectType // the logical size. Includes all the child widgets
+ // width int
+ // height int
+}
+
+// from the gocui devs:
+// Write appends a byte slice into the view's internal buffer. Because
+// View implements the io.Writer interface, it can be passed as parameter
+// of functions like fmt.Fprintf, fmt.Fprintln, io.Copy, etc. Clear must
+// be called to clear the view's buffer.
+
+func (w *cuiWidget) Write(p []byte) (n int, err error) {
+ w.tainted = true
+ w.writeMutex.Lock()
+ defer w.writeMutex.Unlock()
+ // v.makeWriteable(v.wx, v.wy)
+ // v.writeRunes(bytes.Runes(p))
+ fmt.Fprintln(w.v, p)
+ log(logNow, "widget.Write()")
+
+ return len(p), nil
+}
diff --git a/toolkit/democui/view.go b/toolkit/democui/view.go
new file mode 100644
index 0000000..8699bf6
--- /dev/null
+++ b/toolkit/democui/view.go
@@ -0,0 +1,317 @@
+package main
+
+import (
+ "fmt"
+ "errors"
+ "strconv"
+
+ "github.com/awesome-gocui/gocui"
+ "git.wit.org/wit/gui/toolkit"
+)
+
+var adjusted bool = false
+
+// expands the logical size of the parents
+func (w *cuiWidget) setParentLogical(p *cuiWidget) {
+ if (w.visable) {
+ // expand the parent logicalsize to include the widget realSize
+ if (p.logicalSize.w0 > w.realSize.w0) {
+ p.logicalSize.w0 = w.realSize.w0
+ adjusted = true
+ }
+ if (p.logicalSize.h0 > w.realSize.h0) {
+ p.logicalSize.h0 = w.realSize.h0
+ adjusted = true
+ }
+ if (p.logicalSize.w1 < w.realSize.w1) {
+ p.logicalSize.w1 = w.realSize.w1
+ adjusted = true
+ }
+ if (p.logicalSize.h1 < w.realSize.h1) {
+ p.logicalSize.h1 = w.realSize.h1
+ adjusted = true
+ }
+ } else {
+ // expand the parent logicalsize to include the widget logicalsize
+ if (p.logicalSize.w0 > w.logicalSize.w0) {
+ p.logicalSize.w0 = w.logicalSize.w0
+ adjusted = true
+ }
+ if (p.logicalSize.h0 > w.logicalSize.h0) {
+ p.logicalSize.h0 = w.logicalSize.h0
+ adjusted = true
+ }
+ if (p.logicalSize.w1 < w.logicalSize.w1) {
+ p.logicalSize.w1 = w.logicalSize.w1
+ adjusted = true
+ }
+ if (p.logicalSize.h1 < w.logicalSize.h1) {
+ p.logicalSize.h1 = w.logicalSize.h1
+ adjusted = true
+ }
+ }
+ if (w.visable) {
+ // adjust the widget realSize to the top left corner of the logicalsize
+ if (w.logicalSize.w0 > w.realSize.w0) {
+ w.realSize.w0 = w.logicalSize.w0
+ w.realSize.w1 = w.realSize.w0 + w.realWidth
+ adjusted = true
+ }
+ if (w.logicalSize.h0 > w.realSize.h0) {
+ w.realSize.h0 = w.logicalSize.h0
+ w.realSize.h1 = w.realSize.h0 + w.realHeight
+ adjusted = true
+ }
+ }
+ w.showWidgetPlacement(logNow, "setParentLogical() widget")
+ p.showWidgetPlacement(logNow, "setParentLogical() parent")
+ if (w.id == 0) || (p.id == 0) {
+ // stop resizing when you hit the root widget
+ return
+ }
+ // pass the logical resizing up
+ pP := me.widgets[p.parentId]
+ if (pP != nil) {
+ p.setParentLogical(pP)
+ }
+}
+
+var fakeStartWidth int = 80
+var fakeStartHeight int = 0
+func (w *cuiWidget) setFake() {
+ if (w.visable) {
+ return
+ }
+ // setup fake labels for non-visable things off screen
+ w.realWidth = me.defaultWidth
+ w.realHeight = me.defaultHeight
+ w.realSize.w0 = fakeStartWidth
+ w.realSize.h0 = fakeStartHeight
+ w.realSize.w1 = w.realSize.w0 + me.defaultWidth
+ w.realSize.h1 = w.realSize.h0 + me.defaultHeight
+ fakeStartHeight += 2
+ w.showWidgetPlacement(logNow, "setFake()")
+}
+
+func drawView(w *cuiWidget) *gocui.View {
+ var newName string = ""
+ newName = strconv.Itoa(w.id)
+ if (me.baseGui == nil) {
+ log(logError, "drawView() me.baseGui == nil")
+ return nil
+ }
+
+ a := w.realSize.w0
+ b := w.realSize.h0
+ c := w.realSize.w1
+ d := w.realSize.h1
+ v, err := me.baseGui.SetView(newName, a, b, c, d, 0)
+ if err == nil {
+ log(logError, "drawView() internal plugin error err = nil")
+ return nil
+ }
+ if !errors.Is(err, gocui.ErrUnknownView) {
+ log(logError, "drawView() internal plugin error error.IS()", err)
+ return nil
+ }
+ w.v = v
+
+ return v
+}
+
+func boxedPlace(w *cuiWidget) {
+ t := len(w.name)
+ if (w.id == 0) {
+ w.realWidth = 0
+ w.realHeight = 0
+ return
+ }
+ p := me.widgets[w.parentId]
+ if (p == nil) {
+ log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil")
+ return
+ }
+
+ switch p.widgetType {
+ case toolkit.Box:
+ w.realWidth = t + 3
+ w.realHeight = me.defaultHeight
+ w.realSize.w0 = p.nextX
+ w.realSize.h0 = p.nextY
+ w.realSize.w1 = p.nextX + w.realWidth
+ w.realSize.h1 = p.nextY + w.realHeight
+
+ w.logicalSize.w0 = p.nextX
+ w.logicalSize.h0 = p.nextY
+ w.logicalSize.w1 = p.nextX + w.realWidth
+ w.logicalSize.h1 = p.nextY + w.realHeight
+
+ w.nextX = p.nextX
+ w.nextY = p.nextY
+ if (w.horizontal) {
+ log(logNow, "PARENT BOX IS HORIZONTAL")
+ p.nextX += w.realWidth
+ } else {
+ log(logNow, "PARENT BOX IS VERTICAL")
+ p.nextY += w.realHeight
+ }
+ case toolkit.Group:
+ w.realWidth = t + 3
+ w.realHeight = me.defaultHeight
+
+ w.realSize.w0 = p.nextX
+ w.realSize.h0 = p.nextY
+ w.realSize.w1 = p.nextX + w.realWidth
+ w.realSize.h1 = p.nextY + w.realHeight
+
+ w.logicalSize.w0 = p.nextX
+ w.logicalSize.h0 = p.nextY
+ w.logicalSize.w1 = p.nextX + w.realWidth
+ w.logicalSize.h1 = p.nextY + w.realHeight
+
+ w.nextX = w.logicalSize.w0 + 3 // default group padding
+ w.nextY = w.logicalSize.h1
+
+ // increment parent
+ p.nextY += w.realHeight
+ default:
+ w.realWidth = t + 3
+ w.realHeight = me.defaultHeight
+ w.realSize.w0 = p.nextX
+ w.realSize.h0 = p.nextY
+ w.realSize.w1 = w.realSize.w0 + w.realWidth
+ w.realSize.h1 = w.realSize.h0 + w.realHeight
+
+ // increment parent
+ p.nextY += w.realHeight
+ }
+ p.showWidgetPlacement(logNow, "bP parent")
+ w.showWidgetPlacement(logNow, "bP widget")
+}
+
+func findPlace(w *cuiWidget, a *toolkit.Action) {
+ t := len(w.name)
+ w.visable = true
+ switch w.widgetType {
+ case toolkit.Root:
+ w.visable = false
+ w.setFake()
+ w.showWidgetPlacement(logNow, "Root:")
+ case toolkit.Flag:
+ w.visable = false
+ w.setFake()
+ w.showWidgetPlacement(logNow, "Flag:")
+ case toolkit.Window:
+ w.realWidth = t + 3
+ w.realHeight = me.defaultHeight
+
+ w.realSize.w0 = me.nextW
+ w.realSize.h0 = 0
+ w.realSize.w1 = w.realSize.w0 + w.realWidth
+ w.realSize.h1 = w.realHeight
+
+ w.logicalSize.w0 = me.nextW
+ w.logicalSize.h0 = 0
+ w.logicalSize.w1 = w.logicalSize.w0 + w.realWidth
+ w.logicalSize.h1 = w.realHeight
+
+ w.nextX = w.logicalSize.w0 + t // default group padding
+ w.nextY = w.logicalSize.h1
+
+ me.nextW += w.realWidth
+ w.showWidgetPlacement(logNow, "window:")
+ case toolkit.Tab:
+ w.realWidth = t + 3
+ w.realHeight = me.defaultHeight
+
+ w.realSize.w0 = me.nextW
+ w.realSize.h0 = 0
+ w.realSize.w1 = w.realSize.w0 + w.realWidth
+ w.realSize.h1 = w.realHeight
+
+ w.logicalSize.w0 = me.nextW
+ w.logicalSize.h0 = 0
+ w.logicalSize.w1 = w.logicalSize.w0 + w.realWidth
+ w.logicalSize.h1 = w.realHeight
+
+ w.nextX = w.logicalSize.w0 + t // default group padding
+ w.nextY = w.logicalSize.h1
+ me.nextW += w.realWidth
+ w.showWidgetPlacement(logNow, "tab:")
+ case toolkit.Grid:
+ p := me.widgets[w.parentId]
+ w.horizontal = a.B
+ w.visable = false
+ w.setFake()
+
+ if (p == nil) {
+ log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil")
+ return
+ }
+ w.logicalSize.w0 = p.nextX
+ w.logicalSize.h0 = p.nextY
+ w.logicalSize.w1 = p.nextX
+ w.logicalSize.h1 = p.nextY
+
+ w.nextX = p.nextX
+ w.nextY = p.nextY
+ w.showWidgetPlacement(logNow, "grid:")
+ case toolkit.Box:
+ p := me.widgets[w.parentId]
+ w.horizontal = a.B
+ w.visable = false
+ w.setFake()
+
+ if (p == nil) {
+ log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil")
+ return
+ }
+ w.logicalSize.w0 = p.nextX
+ w.logicalSize.h0 = p.nextY
+ w.logicalSize.w1 = p.nextX
+ w.logicalSize.h1 = p.nextY
+
+ w.nextX = p.nextX
+ w.nextY = p.nextY
+ w.showWidgetPlacement(logNow, "box:")
+ case toolkit.Group:
+ p := me.widgets[w.parentId]
+ w.horizontal = a.B
+ w.visable = false
+ w.setFake()
+
+ if (p == nil) {
+ log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil")
+ return
+ }
+ w.logicalSize.w0 = p.nextX
+ w.logicalSize.h0 = p.nextY
+ w.logicalSize.w1 = p.nextX
+ w.logicalSize.h1 = p.nextY
+
+ w.nextX = p.nextX
+ w.nextY = p.nextY
+ w.showWidgetPlacement(logNow, "group:")
+ default:
+ boxedPlace(w)
+ }
+}
+
+func place(w *cuiWidget, a *toolkit.Action) {
+ log(logInfo, "place() START")
+ findPlace(w, a)
+ v := drawView(w)
+ if (v == nil) {
+ log(logError, "place() drawView(w) returned nil")
+ return
+ }
+ me.baseGui.SetKeybinding(v.Name(), gocui.MouseLeft, gocui.ModNone, click)
+
+ v.Wrap = true
+ fmt.Fprintln(v, " " + w.name)
+
+ w.SetDefaultWidgetColor()
+
+ log(logInfo, "place() END")
+ return
+}