diff options
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 +} |
