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 <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-03-26 17:19:20 -05:00
parent 4ae2022600
commit ed128fa566
19 changed files with 605 additions and 126 deletions

View File

@ -55,6 +55,7 @@ cmds-helloconsole:
github: github:
git push origin master git push origin master
git push github master git push github master
git push github devel
git push github --tags git push github --tags
@echo @echo
@echo check https://github.com/wit-go/gui @echo check https://github.com/wit-go/gui

View File

@ -119,6 +119,10 @@ external things which might be useful
Creates a window helpful for debugging this package Creates a window helpful for debugging this package
### func [ExampleCatcher](/chan.go#L37)
`func ExampleCatcher(f func())`
### func [Indent](/debug.go#L130) ### func [Indent](/debug.go#L130)
`func Indent(b bool, a ...interface{})` `func Indent(b bool, a ...interface{})`
@ -133,23 +137,12 @@ Creates a window helpful for debugging this package
loads and initializes a toolkit (andlabs/ui, gocui, etc) loads and initializes a toolkit (andlabs/ui, gocui, etc)
### func [Main](/main.go#L97) ### func [Main](/main.go#L118)
`func Main(f func())` `func Main(f func())`
This should not pass a function This should not pass a function
### func [Queue](/main.go#L127)
`func Queue(f func())`
Other goroutines must use this to access the GUI
You can not acess / process the GUI thread directly from
other goroutines. This is due to the nature of how
Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
For example: gui.Queue(NewWindow())
### func [SetDebug](/debug.go#L28) ### func [SetDebug](/debug.go#L28)
`func SetDebug(s bool)` `func SetDebug(s bool)`
@ -162,7 +155,7 @@ For example: gui.Queue(NewWindow())
`func ShowDebugValues()` `func ShowDebugValues()`
### func [StandardExit](/main.go#L147) ### func [StandardExit](/main.go#L170)
`func StandardExit()` `func StandardExit()`
@ -180,13 +173,13 @@ This goroutine can be used like a watchdog timer
## Types ## Types
### type [GuiArgs](/structs.go#L25) ### type [GuiArgs](/structs.go#L26)
`type GuiArgs struct { ... }` `type GuiArgs struct { ... }`
This struct can be used with the go-arg package This struct can be used with the go-arg package
### type [GuiConfig](/structs.go#L33) ### type [GuiConfig](/structs.go#L34)
`type GuiConfig struct { ... }` `type GuiConfig struct { ... }`
@ -196,7 +189,7 @@ This struct can be used with the go-arg package
var Config GuiConfig var Config GuiConfig
``` ```
### type [Node](/structs.go#L57) ### type [Node](/structs.go#L58)
`type Node struct { ... }` `type Node struct { ... }`
@ -251,6 +244,14 @@ func main() {
You get a window You get a window
``` ```
#### func [Start](/main.go#L96)
`func Start() *Node`
#### func [StartS](/main.go#L105)
`func StartS(name string) *Node`
### type [Symbol](/plugin.go#L16) ### type [Symbol](/plugin.go#L16)
`type Symbol any` `type Symbol any`

33
chan.go
View File

@ -8,8 +8,10 @@ import (
// "regexp" // "regexp"
// "git.wit.org/wit/gui/toolkit" // "git.wit.org/wit/gui/toolkit"
"sync" "sync"
"runtime"
"github.com/sourcegraph/conc" "github.com/sourcegraph/conc"
"github.com/sourcegraph/conc/stream" "github.com/sourcegraph/conc/stream"
"github.com/sourcegraph/conc/panics"
) )
func makeConc() { func makeConc() {
@ -17,15 +19,42 @@ func makeConc() {
defer wg.Wait() defer wg.Wait()
startTheThing(&wg) startTheThing(&wg)
log(debugError, "panic?")
sleep(2)
log(debugError, "panic? after sleep(5)")
} }
func startTheThing(wg *conc.WaitGroup) { func startTheThing(wg *conc.WaitGroup) {
wg.Go(func() { f := func() {
log(debugNow, "startTheThing()") log(debugError, "startTheThing() == about to panic now")
panic("test conc.WaitGroup") panic("test conc.WaitGroup")
}
wg.Go(func() {
ExampleCatcher(f)
}) })
} }
func ExampleCatcher(f func()) {
var pc panics.Catcher
i := 0
pc.Try(func() { i += 1 })
pc.Try(f)
pc.Try(func() { i += 1 })
recovered := pc.Recovered()
log(debugError, "panic.Recovered():", recovered.Value.(string))
frames := runtime.CallersFrames(recovered.Callers)
for {
frame, more := frames.Next()
log(debugError, "\t", frame.Function)
if !more {
break
}
}
}
func mapStream( func mapStream(
in chan int, in chan int,
out chan int, out chan int,

View File

@ -24,7 +24,9 @@ func main() {
arg.MustParse(&args) arg.MustParse(&args)
log.Println("Toolkit = ", args.Toolkit) log.Println("Toolkit = ", args.Toolkit)
// gui.InitPlugins([]string{"andlabs"}) gui.SetDebug(true)
// gui.InitPlugins([]string{"gocui"})
// gui.InitPlugins([]string{"democui"})
gui.Main(initGUI) gui.Main(initGUI)
} }

View File

@ -157,3 +157,50 @@ func commonCallback(n *Node) {
n.Custom() n.Custom()
} }
} }
func (n *Node) Margin() {
var a toolkit.Action
a.Type = toolkit.Margin
newaction(&a, n, nil)
}
func (n *Node) Unmargin() {
var a toolkit.Action
a.Type = toolkit.Unmargin
newaction(&a, n, nil)
}
func (n *Node) Pad() {
var a toolkit.Action
a.Type = toolkit.Pad
newaction(&a, n, nil)
}
func (n *Node) Unpad() {
var a toolkit.Action
a.Type = toolkit.Unpad
newaction(&a, n, nil)
}
func (n *Node) New2() *Node {
var newWin *Node
newWin = NewWindow()
log(debugError, "New2() END Main(f)")
return newWin
}
func (n *Node) Window(title string) *Node {
log(debugError, "Window()", n)
n.SetText(title)
return n
}
func (n *Node) Standard() *Node {
log(debugError, "Standard()")
return n
}
func (n *Node) DoMargin() *Node {
log(debugError, "DoMargin()")
return n
}

View File

@ -74,7 +74,7 @@ func (n *Node) DebugTab(title string) *Node {
dropdownWindowWidgets(g1) dropdownWindowWidgets(g1)
}) })
g2 := newN.NewGroup("node things") g2 := newN.NewGroup("more things")
g2.NewButton("Node.ListChildren(true)", func () { g2.NewButton("Node.ListChildren(true)", func () {
if (activeWidget == nil) { if (activeWidget == nil) {
@ -87,6 +87,20 @@ func (n *Node) DebugTab(title string) *Node {
makeConc() makeConc()
}) })
g2.NewButton("List Plugins", func () {
for _, aplug := range allPlugins {
log("Loaded plugin:", aplug.name, aplug.filename)
}
})
g2.NewButton("load plugin 'gocui'", func () {
StartS("gocui")
})
g2.NewButton("load plugin 'democui'", func () {
StartS("democui")
})
return newN return newN
} }

View File

@ -29,17 +29,24 @@ import (
// "net" // "net"
) )
// 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
var LogSleep bool = false
var LOGOFF bool = false // turn this off, all logging stops var LOGOFF bool = false // turn this off, all logging stops
var debugToolkit bool = false // does spew stuff? var debugToolkit bool = false // does spew stuff?
var Where string = "gui/log" var Where string = "gui/log"
type spewt struct { type Spewt struct {
a bool a bool
} }
var SPEW spewt var SPEW Spewt
/* /*
sleep() # you know what this does? sleeps for 1 second. yep. dump. easy. sleep() # you know what this does? sleeps for 1 second. yep. dump. easy.
@ -51,7 +58,7 @@ func Sleep(a ...any) {
return return
} }
Log(true, "sleep", a[0]) Log(LogSleep, "sleep", a[0])
switch a[0].(type) { switch a[0].(type) {
case int: case int:
@ -69,7 +76,7 @@ func Sleep(a ...any) {
exit("dont like apples") # ok. I'll make a note of that exit("dont like apples") # ok. I'll make a note of that
*/ */
func Exit(a ...any) { func Exit(a ...any) {
Log(true, "exit", a) Log(LogError, "exit", a)
//if (a) { //if (a) {
// os.Exit(a) // os.Exit(a)
//} //}

29
main.go
View File

@ -57,7 +57,7 @@ func InitPlugins(names []string) {
log(debugGui, "Starting gui.Init()") log(debugGui, "Starting gui.Init()")
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(debugGui, "gui.LoadToolkit() already loaded toolkit plugin =", aplug.name) log(debugGui, "LoadToolkit() already loaded toolkit plugin =", aplug.name)
for _, name := range names { for _, name := range names {
if (name == aplug.name) { if (name == aplug.name) {
return return
@ -93,6 +93,27 @@ func InitPlugins(names []string) {
// StandardExit("golang wit/gui could not load a plugin TODO: do something to STDOUT (?)") // StandardExit("golang wit/gui could not load a plugin TODO: do something to STDOUT (?)")
} }
func Start() *Node {
log(logInfo, "Start() Main(f)")
f := func() {
}
go Main(f)
sleep(1)
return Config.master
}
func StartS(name string) *Node {
log(logInfo, "Start() Main(f) for name =", name)
if (LoadToolkit(name) == false) {
return Config.master
}
f := func() {
}
go Main(f)
sleep(1)
return Config.master
}
// This should not pass a function // This should not pass a function
func Main(f func()) { func Main(f func()) {
log(debugGui, "Starting gui.Main() (using gtk via andlabs/ui)") log(debugGui, "Starting gui.Main() (using gtk via andlabs/ui)")
@ -111,11 +132,12 @@ func Main(f func()) {
} }
aplug.MainOk = true aplug.MainOk = true
aplug.Main(f) aplug.Main(f)
// f()
} }
// toolkit.Main(f)
} }
/*
This is deprecated and will be implemented more correctly with waitgroups
// This should never be exposed(?) // This should never be exposed(?)
// Other goroutines must use this to access the GUI // Other goroutines must use this to access the GUI
@ -135,6 +157,7 @@ func Queue(f func()) {
aplug.Queue(f) aplug.Queue(f)
} }
} }
*/
// The window is destroyed but the application does not quit // The window is destroyed but the application does not quit
func (n *Node) StandardClose() { func (n *Node) StandardClose() {

View File

@ -55,9 +55,11 @@ func (n *Node) Parent() *Node {
return n.parent return n.parent
} }
/*
func (n *Node) Window() *Node { func (n *Node) Window() *Node {
return n.parent return n.parent
} }
*/
func (n *Node) Append(child *Node) { func (n *Node) Append(child *Node) {
n.children = append(n.children, child) n.children = append(n.children, child)

View File

@ -29,12 +29,12 @@ type aplug struct {
// TODO: make Main() main() and never allow the user to call it // TODO: make Main() main() and never allow the user to call it
// run plugin.Main() when the plugin is loaded // run plugin.Main() when the plugin is loaded
Main func(func ()) // this never returns. Each plugin must have it's own goroutine Main func(func ()) // this never returns. Each plugin must have it's own goroutine
Queue func(func ()) // Should this return right away? Should it wait (can it wait?) // Queue func(func ()) // Should this return right away? Should it wait (can it wait?)
Quit func() Quit func()
// NewWindow func(*toolkit.Widget) // NewWindow func(*toolkit.Widget)
// simplifies passing to the plugin // simplifies passing to the plugin
Send func(*toolkit.Widget, *toolkit.Widget) // Send func(*toolkit.Widget, *toolkit.Widget)
// should replace Send() // should replace Send()
Action func(*toolkit.Action) Action func(*toolkit.Action)
@ -74,7 +74,7 @@ func LoadToolkit(name string) bool {
newPlug.Main = loadFuncF(&newPlug, "Main") newPlug.Main = loadFuncF(&newPlug, "Main")
// should send things to the goroutine above // should send things to the goroutine above
newPlug.Queue = loadFuncF(&newPlug, "Queue") // newPlug.Queue = loadFuncF(&newPlug, "Queue")
// unload the plugin and restore state // unload the plugin and restore state
newPlug.Quit = loadFuncE(&newPlug, "Quit") newPlug.Quit = loadFuncE(&newPlug, "Quit")

View File

@ -2,6 +2,7 @@ package gui
import ( import (
"git.wit.org/wit/gui/toolkit" "git.wit.org/wit/gui/toolkit"
"sync"
) )
// //
@ -56,6 +57,7 @@ type GuiConfig struct {
// simply the name and the size of whatever GUI element exists // simply the name and the size of whatever GUI element exists
type Node struct { type Node struct {
id int id int
initOnce sync.Once
widget toolkit.Widget widget toolkit.Widget

View File

@ -35,9 +35,10 @@ func add(a *toolkit.Action) {
if (andlabs[a.WhereId] == nil) { if (andlabs[a.WhereId] == nil) {
// listMap(debugError) // memory corruption? // listMap(debugError) // memory corruption?
log(debugError, "add() Widget.Name =", a.Title, a.WidgetT) log(debugError, "add() Widget.Name =", a.Title)
// log(debugError, "add() Where.Name =", a.Where.Name) log(debugError, "add() Widget.Type =", a.WidgetT)
log(debugError, "ERROR add() ERROR a.Where map to t == nil.", a.WidgetId, a.WhereId) log(debugError, "ERROR add() ERROR a.Where map to t == nil. WidgetId =", a.WidgetId, "WhereId =", a.WhereId)
exit("can not add()")
return return
} }

191
toolkit/democui/, Normal file
View File

@ -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
}

40
toolkit/democui/help.go Normal file
View File

@ -0,0 +1,40 @@
// 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() {
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)
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")
}
return nil
}

View File

@ -5,7 +5,15 @@ import (
witlog "git.wit.org/wit/gui/log" witlog "git.wit.org/wit/gui/log"
) )
// 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
func log(a ...any) { func log(a ...any) {
witlog.Where = "wit/democui"
witlog.Log(a...) witlog.Log(a...)
} }

58
toolkit/democui/main.go Normal file
View File

@ -0,0 +1,58 @@
// 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("Init() of democui")
}
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 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()")
}
*/

View File

@ -7,49 +7,18 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"github.com/awesome-gocui/gocui" "github.com/awesome-gocui/gocui"
) )
var g *gocui.Gui func MouseMain() {
var err error g, err := gocui.NewGui(gocui.OutputNormal, true)
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 { if err != nil {
exit("error opening file: %v", err) panic(err)
} }
defer f.Close() defer g.Close()
setOutput(f) baseGui = g
log("This is a test log entry")
g, err = gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
exit(err)
}
g.Cursor = true g.Cursor = true
g.Mouse = true g.Mouse = true
@ -57,35 +26,35 @@ func Init() {
g.SetManagerFunc(layout) g.SetManagerFunc(layout)
if err := keybindings(g); err != nil { if err := keybindings(g); err != nil {
exit(err) panic(err)
} }
log("exit Init()")
}
func StartConsoleMouse() {
defer g.Close()
log("start Main()")
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
exit(err) panic(err)
} }
log("exit Main()")
} }
func layout(g *gocui.Gui) error { func layout(g *gocui.Gui) error {
if v, err := g.SetView("but1", 2, 2, 22, 17, 0); err != nil { 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) { if !errors.Is(err, gocui.ErrUnknownView) {
return err return err
} }
v.Highlight = true
v.SelBgColor = gocui.ColorGreen v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack v.SelFgColor = gocui.ColorBlack
fmt.Fprintln(v, "andlabs") fmt.Fprintln(v, "Button 1 - line 1")
fmt.Fprintln(v, "addDemoTab") fmt.Fprintln(v, "Button 1 - line 2")
fmt.Fprintln(v, "DemoToolkitWindow") fmt.Fprintln(v, "Button 1 - line 3")
fmt.Fprintln(v, "DebugWindow") fmt.Fprintln(v, "Button 1 - line 4")
fmt.Fprintln(v, "do nothing")
fmt.Fprintln(v, "exit")
if _, err := g.SetCurrentView("but1"); err != nil { if _, err := g.SetCurrentView("but1"); err != nil {
return err return err
} }
@ -94,38 +63,12 @@ func layout(g *gocui.Gui) error {
if !errors.Is(err, gocui.ErrUnknownView) { if !errors.Is(err, gocui.ErrUnknownView) {
return err 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.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack v.SelFgColor = gocui.ColorBlack
fmt.Fprintln(v, "Button 2 - line 1") fmt.Fprintln(v, "Button 2 - line 1")
} }
helplayout(g)
updateHighlightedView(g)
return nil return nil
} }
@ -138,13 +81,13 @@ func keybindings(g *gocui.Gui) error {
return err return err
} }
} }
if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, delMsg); err != nil { if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil {
return err return err
} }
if err := g.SetKeybinding("", gocui.MouseRight, gocui.ModNone, delMsg); err != nil { if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil {
return err return err
} }
if err := g.SetKeybinding("", gocui.MouseMiddle, gocui.ModNone, delMsg); err != nil { if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil {
return err return err
} }
return nil return nil
@ -168,18 +111,80 @@ func showMsg(g *gocui.Gui, v *gocui.View) error {
} }
maxX, maxY := g.Size() 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) {
if !errors.Is(err, gocui.ErrUnknownView) { v.Clear()
return err v.SelBgColor = gocui.ColorCyan
} v.SelFgColor = gocui.ColorBlack
mouseClick(l)
fmt.Fprintln(v, l) fmt.Fprintln(v, l)
} }
return nil return nil
} }
func delMsg(g *gocui.Gui, v *gocui.View) error { func updateHighlightedView(g *gocui.Gui) {
// Error check removed, because delete could be called multiple times with the above keybindings mx, my := g.MousePosition()
g.DeleteView("msg") 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 return nil
} }

View File

@ -113,3 +113,19 @@ func Send(p *toolkit.Widget, c *toolkit.Widget) {
log(debugError, "plugin Send() Don't know how to do", c.Type, "yet") log(debugError, "plugin Send() Don't know how to do", c.Type, "yet")
} }
} }
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)
}

View File

@ -0,0 +1,32 @@
// 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"
"github.com/awesome-gocui/gocui"
)
const delta = 1
var (
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
)