diff options
| author | Jeff Carr <[email protected]> | 2023-03-29 22:44:08 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2023-03-29 22:44:08 -0500 |
| commit | 947169df5a22c9f9b53f825764747f648c70ff1e (patch) | |
| tree | 3c84fffc14352329bc41e6b58910ff278c99f08c /toolkit/democui | |
| parent | 6013fde8332e8ecbffaf1a0977ba2e1da8ea8775 (diff) | |
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]>
Diffstat (limited to 'toolkit/democui')
| -rw-r--r-- | toolkit/democui/Makefile | 4 | ||||
| -rw-r--r-- | toolkit/democui/click.go | 49 | ||||
| -rw-r--r-- | toolkit/democui/common.go | 90 | ||||
| -rw-r--r-- | toolkit/democui/debug.go | 163 | ||||
| -rw-r--r-- | toolkit/democui/help.go | 32 | ||||
| -rw-r--r-- | toolkit/democui/keybindings.go | 45 | ||||
| -rw-r--r-- | toolkit/democui/main.go | 13 | ||||
| -rw-r--r-- | toolkit/democui/mouse.go | 25 | ||||
| -rw-r--r-- | toolkit/democui/plugin.go | 123 | ||||
| -rw-r--r-- | toolkit/democui/structs.go | 131 | ||||
| -rw-r--r-- | toolkit/democui/view.go | 317 |
11 files changed, 745 insertions, 247 deletions
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 index ce88b92..f012fef 100644 --- a/toolkit/democui/help.go +++ b/toolkit/democui/help.go @@ -12,29 +12,35 @@ import ( ) func addHelp() { - baseGui.SetManagerFunc(helplayout) + me.baseGui.SetManagerFunc(helplayout) } func helplayout(g *gocui.Gui) error { var err error maxX, _ := g.Size() - helpLabel, err = g.SetView("help", maxX-32, 0, maxX-1, 12, 0) + help, err := g.SetView("help", maxX-32, 0, maxX-1, 12, 0) if err != nil { if !errors.Is(err, gocui.ErrUnknownView) { return err } - fmt.Fprintln(helpLabel, "KEYBINDINGS") - fmt.Fprintln(helpLabel, "Enter: Click Button") - fmt.Fprintln(helpLabel, "Tab/Space: Switch Buttons") - fmt.Fprintln(helpLabel, "") - fmt.Fprintln(helpLabel, "h: Help") - fmt.Fprintln(helpLabel, "Backspace: Delete Button") - fmt.Fprintln(helpLabel, "Arrow keys: Move Button") - fmt.Fprintln(helpLabel, "t: Move Button to the top") - fmt.Fprintln(helpLabel, "b: Move Button to the button") - fmt.Fprintln(helpLabel, "STDOUT: /tmp/witgui.log") - fmt.Fprintln(helpLabel, "Ctrl-C or Q: Exit") + 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/main.go b/toolkit/democui/main.go index 1e0e3d8..19b326d 100644 --- a/toolkit/democui/main.go +++ b/toolkit/democui/main.go @@ -8,18 +8,26 @@ import ( "os" ) +/* func OnExit(f func(string)) { Custom = f } +*/ func Init() { - log("Init() of democui") + log(logInfo, "Init() of democui") + me.widgets = make(map[int]*cuiWidget) + me.defaultWidth = 10 + me.defaultHeight = 2 + me.defaultBehavior = true } func Exit() { - g.Close() + // 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()") @@ -29,6 +37,7 @@ func mouseClick(name string) { Custom(name) // panic("got andlabs") } +*/ func Main(f func()) { log("start Init()") diff --git a/toolkit/democui/mouse.go b/toolkit/democui/mouse.go index 659adb3..fc74d27 100644 --- a/toolkit/democui/mouse.go +++ b/toolkit/democui/mouse.go @@ -18,14 +18,14 @@ func MouseMain() { } defer g.Close() - baseGui = g + me.baseGui = g g.Cursor = true g.Mouse = true g.SetManagerFunc(layout) - if err := keybindings(g); err != nil { + if err := defaultKeybindings(g); err != nil { panic(err) } @@ -72,27 +72,6 @@ func layout(g *gocui.Gui) error { 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 } diff --git a/toolkit/democui/plugin.go b/toolkit/democui/plugin.go index 50d84a2..86125d4 100644 --- a/toolkit/democui/plugin.go +++ b/toolkit/democui/plugin.go @@ -4,128 +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) - } -} - - -// -// 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") - } + me.baseGui.Close() } func Action(a *toolkit.Action) { - log(logNow, "Action() START a.Type =", a.Type) - log(logNow, "Action() START a.S =", a.S) - log(logNow, "Action() START a.Widget =", a.Widget) - - log(logNow, "Action() START a.WidgetId =", a.WidgetId, "a.WhereId =", a.WhereId) - - switch a.Type { - case toolkit.Add: - log(logError, "Action() do add here() =", a.Type, a.Widget) - default: - log(logError, "Action() Unknown =", a.Type, a.Widget) - } - log(logNow, "Action() END =", a.Type, a.Widget) + 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 index a73b9e7..37a8f28 100644 --- a/toolkit/democui/structs.go +++ b/toolkit/democui/structs.go @@ -1,32 +1,127 @@ -// 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. +// 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 ( - "os" + "fmt" + "sync" "github.com/awesome-gocui/gocui" + "git.wit.org/wit/gui/toolkit" ) -const delta = 1 +// 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) +// g *gocui.Gui +// Custom func(string) initialMouseX, initialMouseY, xOffset, yOffset int globalMouseDown, msgMouseDown, movingMsg bool - views = []string{} - curView = -1 - idxView = 0 - currentX = 5 - currentY = 2 - groupSize = 0 - baseGui *gocui.Gui - helpLabel *gocui.View - err error - ch chan(func ()) - outf *os.File +// 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 +} |
