diff options
Diffstat (limited to 'toolkit/democui')
| -rw-r--r-- | toolkit/democui/Makefile | 11 | ||||
| -rw-r--r-- | toolkit/democui/debug.go | 107 | ||||
| -rw-r--r-- | toolkit/democui/log.go | 135 | ||||
| -rw-r--r-- | toolkit/democui/mouse.go | 185 | ||||
| -rw-r--r-- | toolkit/democui/plugin.go | 113 |
5 files changed, 551 insertions, 0 deletions
diff --git a/toolkit/democui/Makefile b/toolkit/democui/Makefile new file mode 100644 index 0000000..6f3f7d9 --- /dev/null +++ b/toolkit/democui/Makefile @@ -0,0 +1,11 @@ +all: plugin + ldd ../democui.so + +build: + GO111MODULE="off" go build + +plugin: + GO111MODULE="off" go build -buildmode=plugin -o ../democui.so + +objdump: + objdump -t ../democui.so |less diff --git a/toolkit/democui/debug.go b/toolkit/democui/debug.go new file mode 100644 index 0000000..817ee6e --- /dev/null +++ b/toolkit/democui/debug.go @@ -0,0 +1,107 @@ +package main + +import "git.wit.org/wit/gui/toolkit" + +var defaultBehavior bool = true + +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 + +// 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 + } else { + log(debugToolkit, "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 { + 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) +} +*/ + +func widgetDump(b bool, w *toolkit.Widget) { + if (w == nil) { + log(b, "widget = nil") + return + } + + log(b, "widget.Name =", w.Name) + log(b, "widget.Action =", w.Action) + log(b, "widget.Type =", w.Type) + log(b, "widget.Custom =", w.Custom) + log(b, "widget.B =", w.B) + log(b, "widget.I =", w.I) + log(b, "widget.Width =", w.Width) + log(b, "widget.Height =", w.Height) + log(b, "widget.X =", w.X) + log(b, "widget.Y =", w.Y) +} + +/* +func GetDebugToolkit () bool { + return debugToolkit +} +*/ diff --git a/toolkit/democui/log.go b/toolkit/democui/log.go new file mode 100644 index 0000000..afd1280 --- /dev/null +++ b/toolkit/democui/log.go @@ -0,0 +1,135 @@ +// +// 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" +) + +var LOGOFF bool = false // turn this off, all logging stops +var WARN bool +var INFO bool + +type spewt struct { + a bool +} + +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])) + } +} + +/* + 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) +} + +func setOutput(f *os.File) { + golog.SetOutput(f) +} diff --git a/toolkit/democui/mouse.go b/toolkit/democui/mouse.go new file mode 100644 index 0000000..efda307 --- /dev/null +++ b/toolkit/democui/mouse.go @@ -0,0 +1,185 @@ +// 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" + "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) + if err != nil { + exit("error opening file: %v", err) + } + defer f.Close() + + setOutput(f) + log("This is a test log entry") + + g, err = gocui.NewGui(gocui.OutputNormal, true) + if err != nil { + exit(err) + } + + g.Cursor = true + g.Mouse = true + + g.SetManagerFunc(layout) + + if err := keybindings(g); err != nil { + exit(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) + } + 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 + } + } + 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") + } + if v, err := g.SetView("but3", 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") + } + if v, err := g.SetView("but4", 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") + } + if v, err := g.SetView("but5", 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 + } + 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 { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + mouseClick(l) + fmt.Fprintln(v, l) + } + 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") + return nil +} diff --git a/toolkit/democui/plugin.go b/toolkit/democui/plugin.go new file mode 100644 index 0000000..0b26f8f --- /dev/null +++ b/toolkit/democui/plugin.go @@ -0,0 +1,113 @@ +package main + +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.Action, ",", 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") + } +} |
