the golang way. everything in it's own repo

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2024-01-17 23:54:19 -06:00
commit b25f15ea78
33 changed files with 2017 additions and 0 deletions

13
Makefile Normal file
View File

@ -0,0 +1,13 @@
all: plugin
plugin:
GO111MODULE="off" go build -v -x -buildmode=plugin -o ../andlabs.so
goget:
GO111MODULE="off" go get -v -t -u
redomod:
rm -f go.*
GO111MODULE= go mod init
GO111MODULE= go mod tidy

310
action.go Normal file
View File

@ -0,0 +1,310 @@
package main
import (
"errors"
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
// this will check to make sure that the node
// is valid for making a New TK andlabs widget
// Basically, it makes sure there is a parent ID
// and that there already a widget created
func notNew(n *tree.Node) bool {
if n == nil {
log.Warn("ready() n = nil")
return true
}
if n.TK != nil {
log.Warn("ready() n.TK = nil", n.WidgetId, n.GetProgName())
return true
}
if n.Parent == nil {
log.Warn("ready() n.Parent = nil", n.WidgetId, n.GetProgName())
return true
}
if n.Parent.TK == nil {
log.Warn("ready() n.Parent.TK = nil", n.WidgetId, n.GetProgName())
log.Warn("ready() n.Parent.TK = nil", n.Parent.WidgetId, n.Parent.GetProgName())
return true
}
// this means you can add a new widgets
return false
}
func ready(n *tree.Node) bool {
if n == nil {
log.Warn("ready() n = nil")
return false
}
if n.TK == nil {
log.Warn("ready() n.TK = nil", n.WidgetId, n.GetProgName())
return false
}
if n.Parent == nil {
log.Warn("ready() n.Parent = nil", n.WidgetId, n.GetProgName())
return false
}
if n.Parent.TK == nil {
log.Warn("ready() n.Parent.TK = nil", n.WidgetId, n.GetProgName())
log.Warn("ready() n.Parent.TK = nil", n.Parent.WidgetId, n.Parent.GetProgName())
return false
}
return true
}
func (n *node) ready() bool {
if n == nil {
return false
}
if n.tk == nil {
return false
}
return true
}
func show(n *tree.Node, b bool) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
// tk = getTK(n)
if tk == nil {
return
}
if tk.uiControl == nil {
return
}
if b {
tk.uiControl.Show()
} else {
tk.uiControl.Hide()
}
}
func enable(n *tree.Node, b bool) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
if n == nil {
panic("WHAT? enable was passed nil. How does this even happen?")
}
if tk == nil {
return
}
if tk.uiControl == nil {
return
}
if b {
tk.uiControl.Enable()
} else {
tk.uiControl.Disable()
}
}
func (n *node) pad(b bool) {
log.Warn("pad() on WidgetId =", n.WidgetId)
t := n.tk
if t == nil {
log.Log(ERROR, "pad() toolkit struct == nil. for", n.WidgetId)
return
}
switch n.WidgetType {
case widget.Window:
t.uiWindow.SetMargined(b)
t.uiWindow.SetBorderless(b)
case widget.Tab:
tabSetMargined(t.uiTab, b)
case widget.Group:
t.uiGroup.SetMargined(b)
case widget.Grid:
t.uiGrid.SetPadded(b)
case widget.Box:
t.uiBox.SetPadded(b)
default:
log.Log(ERROR, "TODO: implement pad() for", n.WidgetType, n.progname)
}
}
func (n *node) move(newParent *node) {
p := n.parent
switch p.WidgetType {
case widget.Group:
case widget.Tab:
// tabSetMargined(tParent.uiTab, true)
case widget.Window:
// t.uiWindow.SetBorderless(false)
case widget.Grid:
// t.uiGrid.SetPadded(true)
case widget.Box:
log.Log(INFO, "TODO: move() where =", p.ParentId)
log.Log(INFO, "TODO: move() for widget =", n.WidgetId)
stretchy = true
if p.tk.uiBox != nil {
p.tk.uiBox.Append(n.tk.uiControl, stretchy)
}
default:
log.Log(ERROR, "TODO: need to implement move() for type =", n.WidgetType)
log.Log(ERROR, "TODO: need to implement move() for where =", p.ParentId)
log.Log(ERROR, "TODO: need to implement move() for widget =", n.WidgetId)
}
}
func (n *node) Delete() {
p := n.parent
log.Log(NOW, "uiDelete()", n.WidgetId, "to", p.WidgetId)
if n.WidgetType == widget.Window {
log.Warn("DESTROY uiWindow here")
log.Warn("NEED TO REMOVE n from parent.Children")
n.tk.uiWindow.Destroy()
n.tk.uiWindow = nil
for i, child := range p.children {
log.Warn("parent has child:", i, child.WidgetId, child.progname)
if n == child {
log.Warn("Found child ==", i, child.WidgetId, child.progname)
log.Warn("Found n ==", i, n.WidgetId, n.progname)
p.children = append(p.children[:i], p.children[i+1:]...)
}
// t.uiWindow.SetBorderless(false)
}
for i, child := range p.children {
log.Warn("parent now has child:", i, child.WidgetId, child.progname)
}
return
}
switch p.WidgetType {
case widget.Group:
// tParent.uiGroup.SetMargined(true)
case widget.Tab:
// tabSetMargined(tParent.uiTab, true)
case widget.Window:
case widget.Grid:
// t.uiGrid.SetPadded(true)
case widget.Box:
log.Log(NOW, "tWidget.boxC =", p.progname)
log.Log(NOW, "is there a tParent parent? =", p.parent)
if p.tk.boxC < 1 {
log.Log(NOW, "Can not delete from Box. already empty. tWidget.boxC =", p.tk.boxC)
return
}
p.tk.uiBox.Delete(0)
p.tk.boxC -= 1
// this didn't work:
// tWidget.uiControl.Disable()
// sleep(.8)
// tParent.uiBox.Append(tWidget.uiControl, stretchy)
default:
log.Log(ERROR, "TODO: need to implement uiDelete() for widget =", n.WidgetId, n.WidgetType)
log.Log(ERROR, "TODO: need to implement uiDelete() for parent =", p.WidgetId, p.WidgetType)
}
}
func rawAction(a *widget.Action) {
log.Log(INFO, "rawAction() START a.ActionType =", a.ActionType, "a.Value", a.Value)
if a.ActionType == widget.ToolkitInit {
Init()
return
}
switch a.WidgetType {
case widget.Root:
me.treeRoot = me.myTree.AddNode(a)
log.Log(INFO, "doAction() found treeRoot")
return
}
log.Warn("andlabs rawAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId, a.ActionType)
switch a.WidgetType {
case widget.Flag:
log.Log(ERROR, "rawAction() RE-IMPLEMENT LOG FLAGS")
return
}
if me.treeRoot == nil {
panic("me.treeRoot == nil")
}
n := me.treeRoot.FindWidgetId(a.WidgetId)
if a.ActionType == widget.Add {
me.treeRoot.ListWidgets()
// ui.QueueMain(func() {
add(a)
// })
// TODO: remove this artificial delay
// sleep(.001)
return
}
if a.ActionType == widget.Dump {
log.Log(NOW, "rawAction() Dump =", a.ActionType, a.WidgetType, n.State.ProgName)
// me.rootNode.listChildren(true)
return
}
if n == nil {
log.Error(errors.New("andlabs rawAction() ERROR findWidgetId found nil"), a.ActionType, a.WidgetType)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil", a.ActionType, a.WidgetType)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId)
me.treeRoot.ListWidgets()
return
panic("findWidgetId found nil for id = " + string(a.WidgetId))
}
switch a.ActionType {
case widget.Show:
show(n, true)
// n.show(true)
case widget.Hide:
show(n, false)
//n.show(false)
case widget.Enable:
enable(n, true)
// n.enable(true)
case widget.Disable:
log.Warn("andlabs got disable for", n.WidgetId, n.State.ProgName)
enable(n, false)
// n.enable(false)
case widget.Get:
// n.setText(a)
setText(n, a)
case widget.GetText:
switch a.WidgetType {
case widget.Textbox:
a.Value = n.State.Value
}
case widget.Set:
setText(n, a)
// n.setText(a)
case widget.SetText:
setText(n, a)
// n.setText(a)
case widget.AddText:
addText(n, a)
// n.addText(a)
/*
case widget.Margin:
n.pad(true)
case widget.Unmargin:
n.pad(false)
case widget.Pad:
n.pad(true)
case widget.Unpad:
n.pad(false)
case widget.Delete:
n.Delete()
case widget.Move:
log.Log(NOW, "rawAction() attempt to move() =", a.ActionType, a.WidgetType)
*/
default:
log.Log(ERROR, "rawAction() Unknown =", a.ActionType, a.WidgetType)
}
log.Log(INFO, "rawAction() END =", a.ActionType, a.WidgetType)
}

72
add.go Normal file
View File

@ -0,0 +1,72 @@
package main
import (
"go.wit.com/lib/widget"
"go.wit.com/log"
)
func add(a *widget.Action) {
log.Warn("andlabs add()", a.WidgetId, a.State.ProgName)
if a.WidgetType == widget.Root {
if me.treeRoot == nil {
me.treeRoot = me.myTree.AddNode(a)
}
return
}
// n := addNode(a)
n := me.myTree.AddNode(a)
p := n.Parent
switch n.WidgetType {
case widget.Window:
log.Warn("SPEEDY Add window", n.WidgetId, n.GetProgName())
newWindow(p, n)
return
case widget.Group:
log.Warn("SPEEDY Add Group", n.WidgetId, n.GetProgName())
newGroup(p, n)
return
case widget.Grid:
newGrid(n)
return
case widget.Box:
newBox(n)
return
/*
case widget.Tab:
newTab(n)
return
*/
case widget.Label:
newLabel(p, n)
return
case widget.Button:
newButton(p, n)
return
case widget.Checkbox:
newCheckbox(p, n)
return
case widget.Spinner:
newSpinner(p, n)
return
case widget.Slider:
newSlider(p, n)
return
case widget.Dropdown:
newDropdown(p, n)
return
case widget.Combobox:
newCombobox(p, n)
return
case widget.Textbox:
newTextbox(p, n)
return
/*
case widget.Image:
newImage(p, n)
return
*/
default:
log.Log(ERROR, "add() error TODO: ", n.WidgetType, n.State.ProgName)
}
}

44
addText.go Normal file
View File

@ -0,0 +1,44 @@
package main
import (
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
func compareStrings(n *tree.Node, ss []string) {
}
// func (n *node) addText(a *widget.Action) {
func addText(n *tree.Node, a *widget.Action) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Warn("andlabs addText() START with a.Value =", a.Value)
if tk == nil {
log.Log(ERROR, "addText error. tk == nil", n.State.ProgName, n.WidgetId)
return
}
log.Warn("andlabs addText() Attempt on", n.WidgetType, "with", a.Value)
switch n.WidgetType {
case widget.Dropdown:
for i, s := range a.State.Strings {
log.Warn("andlabs a.State.Strings =", i, s)
_, ok := n.Strings[s]
// If the key exists
if ok {
log.Warn("andlabs a.State.Strings is here", i, s)
} else {
log.Warn("andlabs is not here", i, s)
addDropdownName(n, s)
// TODO: make numbers
n.Strings[s] = 21
}
}
case widget.Combobox:
addComboboxName(n, widget.GetString(a.Value))
default:
log.Log(ERROR, "plugin Send() Don't know how to addText on", n.WidgetType, "yet", a.ActionType)
}
log.Log(CHANGE, "addText() END with a.Value =", a.Value)
}

65
box.go Normal file
View File

@ -0,0 +1,65 @@
package main
import (
"go.wit.com/lib/widget"
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
// make new Box here
func newBox(n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
var box *ui.Box
if n.State.Direction == widget.Horizontal {
box = ui.NewHorizontalBox()
} else {
box = ui.NewVerticalBox()
}
box.SetPadded(true)
newt.uiBox = box
newt.uiControl = box
newt.boxC = 0
n.TK = newt
place(n.Parent, n)
}
/*
rawBox -- hack to arbitrarily add a box in andlabs to work
around the problem that a "group" can not have one entry in it
TODO: fix this so that a box is "added on demand" that is,
if "go.wit.com/gui/gui" sends you a 2nd thing to add to a group,
automatically add a box then. The problem with this, is the macos, windows and linux gtk
will panic on a move when an chind object is disasociated from the group
I haven't had time to try to debug this, so, instead, it's just probably better to always
add a box here. There doesn't seem to be any real issue with forcing a box to be inserted
into the toolkits that is "outside" the binary tree of widgets. This only means, that on
a destroy of the tree, this box must be checked
even that is a probably not senario however since clicking on the close box in the toolkit
has the operating system destroy everything in the window. it may or may not be possible
to control that behavior. at this time, it's "undetermined" and the best course of action
is to detect the window is destroyed and then remove all the toolkit information
from all the nodes in the binary tree
TODO: handle user killing/closing a window using the OS
*/
// func (n *node) rawBox() *ui.Box {
func rawBox(n *tree.Node) *ui.Box {
var box *ui.Box
if n.State.Direction == widget.Horizontal {
box = ui.NewHorizontalBox()
} else {
box = ui.NewVerticalBox()
}
box.SetPadded(true)
return box
}

30
button.go Normal file
View File

@ -0,0 +1,30 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
// func (p *node) newButton(n *node) {
func newButton(p *tree.Node, n *tree.Node) {
if notNew(n) {
return
}
var ptk *guiWidget
ptk = p.TK.(*guiWidget)
newt := new(guiWidget)
b := ui.NewButton(n.GetLabel())
newt.uiButton = b
newt.uiControl = b
newt.parent = ptk
b.OnClicked(func(*ui.Button) {
me.myTree.DoUserEvent(n)
})
n.TK = newt
place(p, n)
}

30
checkbox.go Normal file
View File

@ -0,0 +1,30 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
func newCheckbox(p *tree.Node, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
newt.uiCheckbox = ui.NewCheckbox(n.GetLabel())
newt.uiControl = newt.uiCheckbox
newt.uiCheckbox.OnToggled(func(spin *ui.Checkbox) {
n.SetValue(newt.checked())
me.myTree.DoUserEvent(n)
})
n.TK = newt
place(p, n)
}
func (t *guiWidget) checked() bool {
return t.uiCheckbox.Checked()
}

79
combobox.go Normal file
View File

@ -0,0 +1,79 @@
package main
import (
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
func newCombobox(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
cb := ui.NewEditableCombobox()
newt.uiEditableCombobox = cb
newt.uiControl = cb
// initialize the index
newt.c = 0
newt.val = make(map[int]string)
cb.OnChanged(func(spin *ui.EditableCombobox) {
n.SetValue(spin.Text())
log.Warn("combobox changed =" + spin.Text() + ".")
me.myTree.DoUserEvent(n)
})
n.TK = newt
place(p, n)
log.Warn("add combobox entries on create:", n.State.Strings)
log.Warn("add combobox entries on create:", n.State.Strings)
log.Warn("add combobox entries on create:", n.State.Strings)
// add the initial combobox entries
for i, s := range n.State.Strings {
log.Warn("add combobox entries on create", n.GetProgName(), i, s)
addComboboxName(n, s)
}
cur := n.String()
log.Warn("add combobox: TODO: set default value on create", n.GetProgName(), cur)
setComboboxName(n, cur)
}
func addComboboxName(n *tree.Node, s string) {
if !ready(n) {
return
}
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "addComboboxName()", n.WidgetId, "add:", s)
tk.uiEditableCombobox.Append(s)
if tk.val == nil {
log.Log(INFO, "make map didn't work")
return
}
tk.val[tk.c] = s
// If this is the first menu added, set the dropdown to it
if tk.c == 0 {
log.Log(INFO, "THIS IS THE FIRST combobox", s)
tk.uiEditableCombobox.SetText(s)
}
tk.c = tk.c + 1
}
func setComboboxName(n *tree.Node, s string) bool {
if !ready(n) {
return false
}
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "SetComboboxName()", n.WidgetId, ",", s)
tk.uiEditableCombobox.SetText(s)
return false
}

61
common.go Normal file
View File

@ -0,0 +1,61 @@
package main
import (
"go.wit.com/lib/widget"
)
type node struct {
parent *node
children []*node
WidgetId int // widget ID
WidgetType widget.WidgetType
ParentId int // parent ID
state widget.State
// a reference name for programming and debuggign. Must be unique
progname string
// the text used for button labesl, window titles, checkbox names, etc
label string
// horizontal means layout widgets like books on a bookshelf
// vertical means layout widgets like books in a stack
// direction widget.Orientation
direction widget.Orientation
// This is how the values are passed back and forth
// values from things like checkboxes & dropdown's
value any
strings []string
// This is used for things like a slider(0,100)
X int
Y int
// This is for the grid size & widget position
W int
H int
AtW int
AtH int
vals []string // dropdown menu items
// horizontal bool `default:false`
hasTabs bool // does the window have tabs?
currentTab bool // the visible tab
// the internal plugin toolkit structure
// in the gtk plugin, it has gtk things like margin & border settings
// in the text console one, it has text console things like colors for menus & buttons
tk *guiWidget
}
/*
func (n *node) doUserEvent() {
log.Log(ERROR, "doUserEvent() ERROR")
}
*/

121
debug.go Normal file
View File

@ -0,0 +1,121 @@
package main
import (
"go.wit.com/log"
// "go.wit.com/gui/widget"
)
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 = false
var debugChange bool = false
var debugPlugin bool = false
var debugAction bool = false
var debugFlags bool = false
var debugGrid bool = false
var debugNow 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.Log(NOW, "Setting this toolkit to use the default behavior.")
log.Log(NOW, "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.Log(NOW, "This toolkit is set to ignore the default behavior.")
}
}
func (t *guiWidget) Dump(b bool) {
if !b {
return
}
log.Log(NOW, "Name = ", t.Width, t.Height)
if t.uiBox != nil {
log.Log(NOW, "uiBox =", t.uiBox)
}
if t.uiButton != nil {
log.Log(NOW, "uiButton =", t.uiButton)
}
if t.uiCombobox != nil {
log.Log(NOW, "uiCombobox =", t.uiCombobox)
}
if t.uiWindow != nil {
log.Log(NOW, "uiWindow =", t.uiWindow)
}
if t.uiTab != nil {
log.Log(NOW, "uiTab =", t.uiTab)
}
if t.uiGroup != nil {
log.Log(NOW, "uiGroup =", t.uiGroup)
}
if t.uiEntry != nil {
log.Log(NOW, "uiEntry =", t.uiEntry)
}
if t.uiMultilineEntry != nil {
log.Log(NOW, "uiMultilineEntry =", t.uiMultilineEntry)
}
if t.uiSlider != nil {
log.Log(NOW, "uiSlider =", t.uiSlider)
}
if t.uiCheckbox != nil {
log.Log(NOW, "uiCheckbox =", t.uiCheckbox)
}
}
/*
func GetDebugToolkit () bool {
return debugToolkit
}
*/
func (n *node) dumpWidget(b bool) {
var info, d string
if n == nil {
log.Log(ERROR, "dumpWidget() node == nil")
return
}
info = n.WidgetType.String()
d = string(n.WidgetId) + " " + info + " " + n.progname
var tabs string
for i := 0; i < listChildrenDepth; i++ {
tabs = tabs + defaultPadding
}
log.Log(NOW, tabs+d)
}
var defaultPadding string = " "
var listChildrenDepth int = 0
func (n *node) listChildren(dump bool) {
if n == nil {
return
}
n.dumpWidget(dump)
if len(n.children) == 0 {
return
}
for _, child := range n.children {
listChildrenDepth += 1
child.listChildren(dump)
listChildrenDepth -= 1
}
}

54
delete.go Normal file
View File

@ -0,0 +1,54 @@
package main
// if you include more than just this import
// then your plugin might be doing something un-ideal (just a guess from 2023/02/27)
import (
"go.wit.com/lib/widget"
"go.wit.com/log"
)
// delete the child widget from the parent
// p = parent, c = child
func (n *node) destroy() {
pId := n.parent.WidgetId
cId := n.WidgetId
log.Log(NOW, "delete()", pId, cId)
pt := n.parent.tk
ct := n.tk
if ct == nil {
log.Log(NOW, "delete FAILED (ct = mapToolkit[c] == nil) for c", pId, cId)
// this pukes out a whole universe of shit
// listMap()
return
}
switch n.WidgetType {
case widget.Button:
log.Log(NOW, "Should delete Button here:", n.progname)
log.Log(NOW, "Parent:")
pt.Dump(true)
log.Log(NOW, "Child:")
ct.Dump(true)
if pt.uiBox == nil {
log.Log(NOW, "Don't know how to destroy this")
} else {
log.Log(NOW, "Fuck it, destroy the whole box", n.parent.progname)
// pt.uiBox.Destroy() // You have a bug: You cannot destroy a uiControl while it still has a parent.
pt.uiBox.SetPadded(false)
pt.uiBox.Delete(4)
ct.uiButton.Disable()
// ct.uiButton.Hide()
ct.uiButton.Destroy()
}
case widget.Window:
log.Log(NOW, "Should delete Window here:", n.progname)
default:
log.Log(NOW, "Fuckit, let's destroy a button")
if ct.uiButton != nil {
pt.uiBox.Delete(4)
ct.uiButton.Destroy()
}
}
}

94
demo.go Normal file
View File

@ -0,0 +1,94 @@
package main
import (
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/log"
)
/*
This is a code example taken directly from the toolkit andlabs/ui
This code is here to double check that the toolkit itself still works
the same way. This is intended as a sanity check.
*/
func BlankWindow(w *ui.Window) *ui.Box {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
w.SetChild(hbox)
return hbox
}
func (t *guiWidget) DemoNumbersPage() {
var w *ui.Window
log.Log(NOW, "Starting wit/gui toolkit andlabs/ui DemoNumbersPage()")
w = t.uiWindow
t.uiBox = makeNumbersPage()
t.uiBox.SetPadded(true)
w.SetChild(t.uiBox)
w.SetTitle("Internal demo of andlabs/ui toolkit")
}
func makeNumbersPage() *ui.Box {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
group := ui.NewGroup("Numbers")
group.SetMargined(true)
hbox.Append(group, true)
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
group.SetChild(vbox)
spinbox := ui.NewSpinbox(0, 100)
slider := ui.NewSlider(0, 100)
pbar := ui.NewProgressBar()
spinbox.OnChanged(func(*ui.Spinbox) {
slider.SetValue(spinbox.Value())
pbar.SetValue(spinbox.Value())
})
slider.OnChanged(func(*ui.Slider) {
spinbox.SetValue(slider.Value())
pbar.SetValue(slider.Value())
})
vbox.Append(spinbox, false)
vbox.Append(slider, false)
vbox.Append(pbar, false)
ip := ui.NewProgressBar()
ip.SetValue(-1)
vbox.Append(ip, false)
group = ui.NewGroup("Lists")
group.SetMargined(true)
hbox.Append(group, true)
vbox = ui.NewVerticalBox()
vbox.SetPadded(true)
group.SetChild(vbox)
cbox := ui.NewCombobox()
cbox.Append("Combobox Item 1")
cbox.Append("Combobox Item 2")
cbox.Append("Combobox Item 3")
vbox.Append(cbox, false)
ecbox := ui.NewEditableCombobox()
ecbox.Append("Editable Item 1")
ecbox.Append("Editable Item 2")
ecbox.Append("Editable Item 3")
vbox.Append(ecbox, false)
rb := ui.NewRadioButtons()
rb.Append("Radio Button 1")
rb.Append("Radio Button 2")
rb.Append("Radio Button 3")
vbox.Append(rb, false)
return hbox
}

106
dropdown.go Normal file
View File

@ -0,0 +1,106 @@
package main
import (
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
func newDropdown(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
log.Log(INFO, "gui.Toolbox.newDropdown() START", n.GetProgName())
cb := ui.NewCombobox()
newt.uiCombobox = cb
newt.uiControl = cb
// initialize the index
newt.c = 0
newt.val = make(map[int]string)
cb.OnSelected(func(spin *ui.Combobox) {
i := spin.Selected()
if newt.val == nil {
log.Log(ERROR, "make map didn't work")
n.SetValue("map did not work. ui.Combobox error")
} else {
n.SetValue(newt.val[i])
}
me.myTree.DoUserEvent(n)
})
n.TK = newt
place(p, n)
log.Warn("add dropdown entries on create:", n.State.Strings)
log.Warn("add dropdown entries on create:", n.State.Strings)
log.Warn("add dropdown entries on create:", n.State.Strings)
if n.State.Strings == nil {
return
}
// add the initial dropdown entries
for i, s := range n.State.Strings {
log.Warn("add dropdown: add entries on create", n.GetProgName(), i, s)
addDropdownName(n, s)
}
cur := n.String()
log.Warn("add dropdown: set default value on create", n.GetProgName(), cur)
setDropdownName(n, cur)
}
func setDropdownInt(n *tree.Node, i int) {
if !ready(n) {
return
}
var tk *guiWidget
tk = n.TK.(*guiWidget)
tk.uiCombobox.SetSelected(i)
}
func addDropdownName(n *tree.Node, s string) {
if !ready(n) {
return
}
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "addDropdownName()", n.WidgetId, "add:", s)
tk.uiCombobox.Append(s)
if tk.val == nil {
log.Log(INFO, "make map didn't work")
return
}
tk.val[tk.c] = s
// If this is the first menu added, set the dropdown to it
if tk.c == 0 {
log.Log(INFO, "THIS IS THE FIRST Dropdown", s)
tk.uiCombobox.SetSelected(0)
}
tk.c = tk.c + 1
}
func setDropdownName(n *tree.Node, s string) bool {
if !ready(n) {
return false
}
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "SetDropdownName()", n.WidgetId, ",", s)
for i, tmp := range tk.val {
if s == tmp {
n.SetValue(s)
setDropdownInt(n, i)
log.Warn("SetDropdownInt() worked", tmp, i)
return true
}
}
log.Warn("SetDropdownName() failed", s)
return false
}

11
go.mod Normal file
View File

@ -0,0 +1,11 @@
module go.wit.com/gui/toolkits/andlabs
go 1.21.4
require (
go.wit.com/dev/andlabs/ui v0.0.1
go.wit.com/gui/widget v1.1.3
go.wit.com/log v0.5.4
)
require go.wit.com/dev/davecgh/spew v1.1.4 // indirect

12
go.sum Normal file
View File

@ -0,0 +1,12 @@
go.wit.com/dev/andlabs/ui v0.0.1 h1:SowOybLBu/qUOqp905EZikz5/iPa3GpmnCAPzNOYajM=
go.wit.com/dev/andlabs/ui v0.0.1/go.mod h1:mlKEEe05ZJURzjh1LtjzdGMHVbJm9a7BUaVpA9cHxsM=
go.wit.com/dev/davecgh/spew v1.1.3 h1:hqnB5qsPgC2cLZaJXqQJspQ5n/Ugry9kyL3tLk0hVzQ=
go.wit.com/dev/davecgh/spew v1.1.3/go.mod h1:sihvWmnQ/09FWplnEmozt90CCVqBtGuPXM811tgfhFA=
go.wit.com/dev/davecgh/spew v1.1.4 h1:C9hj/rjlUpdK+E6aroyLjCbS5MFcyNUOuP1ICLWdNek=
go.wit.com/dev/davecgh/spew v1.1.4/go.mod h1:sihvWmnQ/09FWplnEmozt90CCVqBtGuPXM811tgfhFA=
go.wit.com/gui/widget v1.1.3 h1:GvLzGSOF9tfmoh6HNbFdN+NSlBo2qeS/Ba2TnQQ1A1U=
go.wit.com/gui/widget v1.1.3/go.mod h1:A6/FaiFQtAHTjgo7c4FrokXe6bXX1Cowo35b2Lgi31E=
go.wit.com/log v0.5.3 h1:/zHkniOPusPEuX1R401rMny9uwSO/nSU/QOMx6qoEnE=
go.wit.com/log v0.5.3/go.mod h1:LzIzVxc2xJQxWQBtV9VbV605P4TOxmYDCl+BZF38yGE=
go.wit.com/log v0.5.4 h1:vijLRPTUgChb8J5tx/7Uma/lGTUxeSXosFbheAmL914=
go.wit.com/log v0.5.4/go.mod h1:BaJBfHFqcJSJLXGQ9RHi3XVhPgsStxSMZRlaRxW4kAo=

29
grid.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
// Grid numbering by (X,Y)
// -----------------------------
// -- (1,1) -- (2,1) -- (3,1) --
// -- (1,2) -- (2,1) -- (3,1) --
// -----------------------------
func newGrid(n *tree.Node) {
if notNew(n) {
return
}
var newt *guiWidget
newt = new(guiWidget)
c := ui.NewGrid()
newt.uiGrid = c
newt.uiControl = c
c.SetPadded(true)
n.TK = newt
place(n.Parent, n)
}

24
group.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
// "go.wit.com/gui/widget"
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
func newGroup(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
g := ui.NewGroup(n.GetLabel())
g.SetMargined(true)
newt.uiGroup = g
newt.uiControl = g
n.TK = newt
place(p, n)
}

27
icon.go Normal file
View File

@ -0,0 +1,27 @@
package main
var rawImage = []byte{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0xca, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0xa5, 0x93, 0xb1, 0x0d,
0xc2, 0x40, 0x0c, 0x45, 0x1d, 0xc4, 0x14, 0x0c, 0x12, 0x41, 0x0f, 0x62,
0x12, 0x46, 0x80, 0x8a, 0x2e, 0x15, 0x30, 0x02, 0x93, 0x20, 0x68, 0x11,
0x51, 0x06, 0x61, 0x0d, 0x88, 0x2d, 0x7f, 0xdb, 0x07, 0x87, 0x08, 0xdc,
0x49, 0x91, 0x7d, 0xf6, 0xf7, 0xf3, 0x4f, 0xa4, 0x54, 0xbb, 0xeb, 0xf6,
0x41, 0x05, 0x67, 0xcc, 0xb3, 0x9b, 0xfa, 0xf6, 0x17, 0x62, 0xdf, 0xcd,
0x48, 0x00, 0x32, 0xbd, 0xa8, 0x1d, 0x72, 0xee, 0x3c, 0x47, 0x16, 0xfb,
0x5c, 0x53, 0x8d, 0x03, 0x30, 0x14, 0x84, 0xf7, 0xd5, 0x89, 0x26, 0xc7,
0x25, 0x10, 0x36, 0xe4, 0x05, 0xa2, 0x51, 0xbc, 0xc4, 0x1c, 0xc3, 0x1c,
0xed, 0x30, 0x1c, 0x8f, 0x16, 0x3f, 0x02, 0x78, 0x33, 0x20, 0x06, 0x60,
0x97, 0x70, 0xaa, 0x45, 0x7f, 0x85, 0x60, 0x5d, 0xb6, 0xf4, 0xc2, 0xc4,
0x3e, 0x0f, 0x44, 0xcd, 0x1b, 0x20, 0x90, 0x0f, 0xed, 0x85, 0xa8, 0x55,
0x05, 0x42, 0x43, 0xb4, 0x9e, 0xce, 0x71, 0xb3, 0xe8, 0x0e, 0xb4, 0xc4,
0xc3, 0x39, 0x21, 0xb7, 0x73, 0xbd, 0xe4, 0x1b, 0xe4, 0x04, 0xb6, 0xaa,
0x4f, 0x18, 0x2c, 0xee, 0x42, 0x31, 0x01, 0x84, 0xfa, 0xe0, 0xd4, 0x00,
0xdf, 0xb6, 0x83, 0xf8, 0xea, 0xc2, 0x00, 0x10, 0xfc, 0x1a, 0x05, 0x30,
0x74, 0x3b, 0xe0, 0xd1, 0x45, 0xb1, 0x83, 0xaa, 0xf4, 0x77, 0x7e, 0x02,
0x87, 0x1f, 0x42, 0x7f, 0x9e, 0x2b, 0xe8, 0xdf, 0x00, 0x00, 0x00, 0x00,
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
}

49
image.go Normal file
View File

@ -0,0 +1,49 @@
package main
import (
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
// make new Image using andlabs/ui
func (p *node) newImage(n *node) {
newt := new(guiWidget)
var img *ui.Image
img = ui.NewImage(16, 16)
newt.uiImage = img
// newt.uiControl = img
n.tk = newt
// p.place(n)
}
/*
if (a.Name == "image") {
log(true, "NewTextbox() trying to add a new image")
i := ui.NewImage(16, 16)
img, _, err := image.Decode(bytes.NewReader(rawImage))
if err != nil {
panic(err)
}
nr, ok := img.(*image.RGBA)
if !ok {
i2 := image.NewRGBA(img.Bounds())
draw.Draw(i2, i2.Bounds(), img, img.Bounds().Min, draw.Src)
nr = i2
}
i.Append(nr)
t.uiBox.Append(i, true)
var img *ui.Image
var icon []byte
var imgA image.Image
icon, _ = res.ReadFile("resources/ping6.working.png")
// imgA, _, err := image.Decode(bytes.NewReader(b))
imgA, _, _ = image.Decode(icon)
img.Append(imgA)
img.Append(icon)
}
*/

21
label.go Normal file
View File

@ -0,0 +1,21 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
func newLabel(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
c := ui.NewLabel(n.GetLabel())
newt.uiLabel = c
newt.uiControl = c
n.TK = newt
place(p, n)
}

34
log.go Normal file
View File

@ -0,0 +1,34 @@
package main
/*
this enables command line options from other packages like 'gui' and 'log'
*/
import (
log "go.wit.com/log"
)
var NOW *log.LogFlag
var INFO *log.LogFlag
var SPEW *log.LogFlag
var WARN *log.LogFlag
var ERROR *log.LogFlag
var CHANGE *log.LogFlag
var TOOLKIT *log.LogFlag
func init() {
full := "toolkit/nocui"
short := "nocui"
NOW = log.NewFlag("NOW", true, full, short, "temp debugging stuff")
INFO = log.NewFlag("INFO", false, full, short, "normal debugging stuff")
WARN = log.NewFlag("WARN", true, full, short, "bad things")
SPEW = log.NewFlag("SPEW", false, full, short, "spew stuff")
ERROR = log.NewFlag("ERROR", false, full, short, "toolkit errors")
CHANGE = log.NewFlag("ERROR", false, full, short, "show when the user does things")
TOOLKIT = log.NewFlag("ERROR", false, full, short, "andlabs specific stuff")
}

70
main.go Normal file
View File

@ -0,0 +1,70 @@
package main
import (
"runtime/debug"
"sync"
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
// the _ means we only need this for the init()
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
var uiMainUndef bool = true
var uiMain sync.Once
var muAction sync.Mutex
func queueMain(currentA widget.Action) {
defer func() {
if r := recover(); r != nil {
log.Warn("YAHOOOO Recovered in queueMain() application:", r)
log.Println("Recovered from panic:", r)
log.Println("Stack trace:")
debug.PrintStack()
me.myTree.DoToolkitPanic()
}
}()
ui.QueueMain(func() {
rawAction(&currentA)
})
}
func guiMain() {
defer func() {
if r := recover(); r != nil {
log.Warn("YAHOOOO Recovered in guiMain application:", r)
log.Println("Recovered from panic:", r)
log.Println("Stack trace:")
debug.PrintStack()
me.myTree.DoToolkitPanic()
}
}()
ui.Main(func() {
demoUI()
})
}
func Init() {
log.Warn("Init() TODO: move init() to here")
}
// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
func init() {
log.Log(INFO, "Init() START")
log.Log(INFO, "Init()")
// Can you pass values to a plugin init() ? Otherwise, there is no way to safely print
// log.Log(INFO, "init() Setting defaultBehavior = true")
setDefaultBehavior(true)
me.myTree = tree.New()
me.myTree.PluginName = "andlabs"
me.myTree.ActionFromChannel = queueMain
// TODO: this is messed up. run ui.Main() from the first add? Initialize it with an empty thing first?
// fake out the OS toolkit by making a fake window. This is probably needed for macos & windows
// actually, this probably breaks the macos build
go guiMain()
}

112
place.go Normal file
View File

@ -0,0 +1,112 @@
package main
import (
// "os"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
// This routine is very specific to this toolkit
// It's annoying and has to be copied to each widget when there are changes
// it could be 'simplfied' maybe or made to be more generic, but this is as far as I've gotten
// it's probably not worth working much more on this toolkit, the andlabs/ui has been great and got me here!
// but it's time to write direct GTK, QT, macos and windows toolkit plugins
// -- jcarr 2023/03/09
// Grid numbering examples by (X,Y)
// ---------
// -- (1) --
// -- (2) --
// ---------
//
// -----------------------------
// -- (1,1) -- (1,2) -- (1,3) --
// -- (2,1) -- (2,2) -- (2,3) --
// -----------------------------
// internally for andlabs/ui
// (x&y flipped and start at zero)
// -----------------------------
// -- (0,0) -- (1,0) -- (1,0) --
// -- (0,1) -- (1,1) -- (1,1) --
// -----------------------------
func place(p *tree.Node, n *tree.Node) bool {
log.Warn("SPEEDY newplace() 1 START", n.WidgetId, n.GetProgName(), n.GetLabel(), n.String())
log.Warn("SPEEDY newplace() n.State.Strings =", n.State.Strings)
log.Log(INFO, "place() 1 START", n.WidgetType, n.GetProgName(), n.GetLabel())
if !ready(n) {
log.Warn("place() 1 START not ready()")
return false
}
log.Log(INFO, "place() 1 START ready()")
var tk, ptk *guiWidget
tk = n.TK.(*guiWidget)
ptk = p.TK.(*guiWidget)
log.Warn("SPEEDY newplace() 2 START", n.WidgetId, n.GetProgName(), n.GetLabel())
if ptk == nil {
log.Log(ERROR, "ptk == nil", p.GetProgName(), p.ParentId, p.WidgetType, ptk)
log.Log(ERROR, "n = ", n.GetProgName(), n.ParentId, n.WidgetType, tk)
log.Warn("SPEEDY ptk == nil", n.WidgetId, n.GetProgName())
log.Sleep(1)
panic("ptk == nil")
}
log.Log(INFO, "place() switch", p.WidgetType)
log.Warn("SPEEDY newplace() before switch", n.WidgetId, n.GetProgName())
switch p.WidgetType {
case widget.Grid:
tk.gridX = n.State.GridOffset.X - 1
tk.gridY = n.State.GridOffset.Y - 1
log.Warn("place() on Grid at gridX,gridY", tk.gridX, tk.gridY)
ptk.uiGrid.Append(tk.uiControl,
tk.gridX, tk.gridY, 1, 1,
false, ui.AlignFill, false, ui.AlignFill)
return true
case widget.Group:
if ptk.uiBox == nil {
log.Log(WARN, "place() andlabs hack group to use add a box", n.GetProgName(), n.WidgetType)
ptk.uiBox = rawBox(n)
ptk.uiGroup.SetChild(ptk.uiBox)
}
ptk.uiBox.Append(tk.uiControl, stretchy)
return true
case widget.Tab:
if ptk.uiTab == nil {
log.Log(ERROR, "ptk.uiTab == nil for n.WidgetId =", n.WidgetId, "ptk =", ptk)
panic("ptk.uiTab == nil")
}
if tk.uiControl == nil {
log.Log(ERROR, "tk.uiControl == nil for n.WidgetId =", n.WidgetId, "tk =", tk)
panic("tk.uiControl == nil")
}
log.Log(ERROR, "CHECK LOGIC ON THIS. APPENDING directly into a window without a tab")
// log.Log(ERROR, "THIS SHOULD NEVER HAPPEN ??????? trying to place() node=", n.WidgetId, n.GetProgName(), n.Text, n.WidgetType)
// log.Log(ERROR, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.GetProgName(), p.Text, p.WidgetType)
// panic("tk.uiControl == nil")
ptk.uiTab.Append(widget.GetString(n.State.Value), tk.uiControl)
ptk.boxC += 1
return true
case widget.Box:
log.Warn("SPEEDY Add Something to Box", n.WidgetId, n.GetProgName())
log.Log(INFO, "place() uiBox =", ptk.uiBox)
log.Log(INFO, "place() uiControl =", tk.uiControl)
ptk.uiBox.Append(tk.uiControl, stretchy)
ptk.boxC += 1
return true
case widget.Window:
log.Warn("SPEEDY Add Something to Window", n.WidgetId, n.GetProgName())
ptk.uiWindow.SetChild(tk.uiControl)
return true
default:
log.Log(ERROR, "place() how? Parent =", p.WidgetId, p.WidgetType)
}
log.Warn("SPEEDY newplace() return", n.WidgetId, n.GetProgName())
return false
}

76
setText.go Normal file
View File

@ -0,0 +1,76 @@
package main
import (
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
// func (n *node) setText(a *widget.Action) {
func setText(n *tree.Node, a *widget.Action) {
name := widget.GetString(a.Value)
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(CHANGE, "setText() START with text =", name)
if tk == nil {
log.Log(ERROR, "setText error. tk == nil", n.GetProgName(), n.WidgetId)
return
}
log.Log(CHANGE, "setText() Attempt on", n.WidgetType, "with", name)
switch n.WidgetType {
case widget.Window:
log.Warn("setText() Attempt to set the title to", name)
tk.uiWindow.SetTitle(name)
case widget.Tab:
case widget.Group:
tk.uiGroup.SetTitle(name)
case widget.Checkbox:
tk.uiCheckbox.SetText(name)
case widget.Textbox:
if tk.uiEntry != nil {
tk.uiEntry.SetText(name)
}
if tk.uiMultilineEntry != nil {
tk.uiMultilineEntry.SetText(name)
}
case widget.Label:
tk.uiLabel.SetText(name)
case widget.Button:
tk.uiButton.SetText(name)
case widget.Slider:
log.Log(ERROR, "setText() on slider unknown", a.ActionType, "on checkbox", n.GetProgName())
case widget.Spinner:
log.Log(ERROR, "setText() on spinner unknown", a.ActionType, "on checkbox", n.GetProgName())
case widget.Dropdown:
var orig int
var i int = -1
var s string
orig = tk.uiCombobox.Selected()
log.Log(CHANGE, "try to set the Dropdown to", name, "from", orig)
// try to find the string
for i, s = range tk.val {
log.Log(CHANGE, "i, s", i, s)
if name == s {
tk.uiCombobox.SetSelected(i)
log.Log(CHANGE, "setText() Dropdown worked.", name)
return
}
}
log.Log(ERROR, "setText() Dropdown did not find:", name)
// if i == -1, then there are not any things in the menu to select
if i == -1 {
return
}
// if the string was never set, then set the dropdown to the last thing added to the menu
if orig == -1 {
tk.uiCombobox.SetSelected(i)
}
case widget.Combobox:
tk.uiEditableCombobox.SetText(name)
default:
log.Log(ERROR, "plugin Send() Don't know how to setText on", n.WidgetType, "yet", a.ActionType)
}
log.Log(CHANGE, "setText() END with name =")
}

31
slider.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
func newSlider(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
var x, y int
x = n.State.Range.Low
y = n.State.Range.High
s := ui.NewSlider(x, y)
newt.uiSlider = s
newt.uiControl = s
s.OnChanged(func(spin *ui.Slider) {
n.SetValue(newt.uiSlider.Value())
me.myTree.DoUserEvent(n)
})
n.TK = newt
place(p, n)
}

27
spinner.go Normal file
View File

@ -0,0 +1,27 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
func newSpinner(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
s := ui.NewSpinbox(n.State.Range.Low, n.State.Range.High)
newt.uiSpinbox = s
newt.uiControl = s
s.OnChanged(func(s *ui.Spinbox) {
n.SetValue(newt.uiSpinbox.Value())
me.myTree.DoUserEvent(n)
})
n.TK = newt
place(p, n)
}

64
structs.go Normal file
View File

@ -0,0 +1,64 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
// var andlabs map[int]*andlabsT
// var callback func(int) bool
// var callback chan toolkit.Action
// It's probably a terrible idea to call this 'me'
var me config
type config struct {
rootNode *tree.Node // the base of the binary tree. it should have id == 0
treeRoot *tree.Node // the base of the binary tree. it should have id == 0
myTree *tree.TreeInfo
}
// stores the raw toolkit internals
type guiWidget struct {
Width int
Height int
// tw *toolkit.Widget
parent *guiWidget
children []*guiWidget
// used to track if a tab has a child widget yet
child bool
uiControl ui.Control
uiBox *ui.Box
uiButton *ui.Button
uiCombobox *ui.Combobox
uiCheckbox *ui.Checkbox
uiEntry *ui.Entry
uiGroup *ui.Group
uiLabel *ui.Label
uiSlider *ui.Slider
uiSpinbox *ui.Spinbox
uiTab *ui.Tab
uiWindow *ui.Window
uiMultilineEntry *ui.MultilineEntry
uiEditableCombobox *ui.EditableCombobox
uiImage *ui.Image
uiGrid *ui.Grid
gridX int
gridY int
// used as a counter to work around limitations of widgets like combobox
// this is probably fucked up and in many ways wrong because of unsafe goroutine threading
// but it's working for now due to the need for need for a correct interaction layer betten toolkits
c int
val map[int]string
// andlabs/ui only accesses widget id numbers
boxC int // how many things on in a box or how many tabs
}

117
tab.go Normal file
View File

@ -0,0 +1,117 @@
package main
import (
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
/*
This adds a tab
andlabs/ui is goofy in the sense that you have to determine
if the ui.Window already has a tab in it. If it does, then
you need to add this tab and not run SetChild() on the window
or instead it replaces the existing tab with the new one
I work around this by always sending a Toolkit that is a tab
once there is one. If you send a Window here, it will replace
any existing tabs rather than adding a new one
*/
func (p *node) newTab(n *node) {
var newt *guiWidget
if p == nil {
log.Log(ERROR, "newTab() p == nil. how the fuck does this happen?", n.WidgetId, n.ParentId)
}
if p.WidgetType != widget.Window {
log.Log(ERROR, "newTab() uiWindow == nil. I can't add a toolbar without window", n.WidgetId, n.ParentId)
return
}
t := p.tk
log.Log(TOOLKIT, "newTab() START", n.WidgetId, n.ParentId)
if t.uiTab == nil {
// this means you have to make a new tab
log.Log(TOOLKIT, "newTab() GOOD. This should be the first tab:", n.WidgetId, n.ParentId)
newt = rawTab(t.uiWindow, widget.GetString(n.value))
t.uiTab = newt.uiTab
} else {
// this means you have to append a tab
log.Log(TOOLKIT, "newTab() GOOD. This should be an additional tab:", n.WidgetId, n.ParentId)
if n.WidgetType == widget.Tab {
// andlabs doesn't have multiple tab widgets so make a fake one?
// this makes a guiWidget internal structure with the parent values
newt = new(guiWidget)
newt.uiWindow = t.uiWindow
newt.uiTab = t.uiTab
} else {
newt = t.appendTab(widget.GetString(n.value))
}
}
n.tk = newt
}
// This sets _all_ the tabs to Margin = true
//
// TODO: do proper tab tracking (will be complicated). low priority
func tabSetMargined(tab *ui.Tab, b bool) {
c := tab.NumPages()
for i := 0; i < c; i++ {
log.Log(TOOLKIT, "SetMargined", i, b)
tab.SetMargined(i, b)
}
}
func rawTab(w *ui.Window, name string) *guiWidget {
var newt guiWidget
log.Log(TOOLKIT, "rawTab() START", name)
if w == nil {
log.Log(ERROR, "UiWindow == nil. I can't add a tab without a window")
log.Log(ERROR, "UiWindow == nil. I can't add a tab without a window")
log.Log(ERROR, "UiWindow == nil. I can't add a tab without a window")
// sleep(1)
return nil
}
tab := ui.NewTab()
w.SetChild(tab)
newt.uiTab = tab
newt.uiControl = tab
log.Log(TOOLKIT, "rawTab() END", name)
return &newt
}
func (t *guiWidget) appendTab(name string) *guiWidget {
var newT guiWidget
log.Log(TOOLKIT, "appendTab() ADD", name)
if t.uiTab == nil {
log.Log(TOOLKIT, "UiWindow == nil. I can't add a widget without a place to put it")
panic("should never have happened. wit/gui/toolkit has ui.Tab == nil")
}
log.Log(TOOLKIT, "appendTab() START name =", name)
var hbox *ui.Box
if defaultBehavior {
hbox = ui.NewHorizontalBox()
} else {
if bookshelf {
hbox = ui.NewHorizontalBox()
} else {
hbox = ui.NewVerticalBox()
}
}
hbox.SetPadded(padded)
t.uiTab.Append(name, hbox)
newT.uiWindow = t.uiWindow
newT.uiTab = t.uiTab
newT.uiBox = hbox
return &newT
}

37
textbox.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"go.wit.com/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
func newTextbox(p, n *tree.Node) {
if notNew(n) {
return
}
newt := new(guiWidget)
if n.State.Range.Low == 1 {
e := ui.NewEntry()
newt.uiEntry = e
newt.uiControl = e
e.OnChanged(func(spin *ui.Entry) {
n.SetValue(spin.Text())
me.myTree.DoUserEvent(n)
})
} else {
e := ui.NewNonWrappingMultilineEntry()
newt.uiMultilineEntry = e
newt.uiControl = e
e.OnChanged(func(spin *ui.MultilineEntry) {
n.SetValue(spin.Text())
me.myTree.DoUserEvent(n)
})
}
n.TK = newt
place(p, n)
}

31
tree.go Normal file
View File

@ -0,0 +1,31 @@
package main
/*
This code should be common to all gui plugins
There are some helper functions that are probably going to be
the same everywhere. Mostly due to handling the binary tree structure
and the channel communication
For now, it's just a symlink to the 'master' version in
./toolkit/nocui/common.go
*/
import (
"go.wit.com/lib/widget"
)
// 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.)
//
// this sets the channel to send user events back from the plugin
func Callback(guiCallback chan widget.Action) {
me.myTree.Callback(guiCallback)
}
func PluginChannel() chan widget.Action {
return me.myTree.PluginChannel()
}

97
updateui.go Normal file
View File

@ -0,0 +1,97 @@
package main
import (
"go.wit.com/dev/andlabs/ui"
)
// Example showing how to update the UI using the QueueMain function
// especially if the update is coming from another goroutine
//
// see QueueMain in 'main.go' for detailed description
var count int
func demoUI() {
mainWindow := ui.NewWindow("libui Updating UI", 640, 480, true)
mainWindow.OnClosing(func(*ui.Window) bool {
ui.Quit()
return true
})
ui.OnShouldQuit(func() bool {
mainWindow.Destroy()
return true
})
vbContainer := ui.NewVerticalBox()
vbContainer.SetPadded(true)
inputGroup := ui.NewGroup("Input")
inputGroup.SetMargined(true)
vbInput := ui.NewVerticalBox()
vbInput.SetPadded(true)
inputForm := ui.NewForm()
inputForm.SetPadded(true)
message := ui.NewEntry()
message.SetText("Hello World")
inputForm.Append("What message do you want to show?", message, false)
showMessageButton := ui.NewButton("Show message")
clearMessageButton := ui.NewButton("Clear message")
vbInput.Append(inputForm, false)
vbInput.Append(showMessageButton, false)
vbInput.Append(clearMessageButton, false)
inputGroup.SetChild(vbInput)
messageGroup := ui.NewGroup("Message")
messageGroup.SetMargined(true)
vbMessage := ui.NewVerticalBox()
vbMessage.SetPadded(true)
messageLabel := ui.NewLabel("")
vbMessage.Append(messageLabel, false)
messageGroup.SetChild(vbMessage)
countGroup := ui.NewGroup("Counter")
countGroup.SetMargined(true)
vbCounter := ui.NewVerticalBox()
vbCounter.SetPadded(true)
countLabel := ui.NewLabel("blah")
vbCounter.Append(countLabel, false)
countGroup.SetChild(vbCounter)
vbContainer.Append(inputGroup, false)
vbContainer.Append(messageGroup, false)
vbContainer.Append(countGroup, false)
mainWindow.SetChild(vbContainer)
showMessageButton.OnClicked(func(*ui.Button) {
// Update the UI directly as it is called from the main thread
messageLabel.SetText(message.Text())
})
clearMessageButton.OnClicked(func(*ui.Button) {
// Update the UI directly as it is called from the main thread
messageLabel.SetText("")
})
// this is messed up.
// mainWindow.Show()
}
/*
func main() {
ui.Main(setupUI)
}
*/

18
widget.go Normal file
View File

@ -0,0 +1,18 @@
package main
import (
"go.wit.com/lib/widget"
"go.wit.com/toolkits/tree"
)
func initWidget(n *tree.Node) *guiWidget {
var w *guiWidget
w = new(guiWidget)
if n.WidgetType == widget.Root {
n.WidgetId = 0
me.treeRoot = n
return w
}
return w
}

51
window.go Normal file
View File

@ -0,0 +1,51 @@
package main
import (
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/lib/widget"
"go.wit.com/log"
"go.wit.com/toolkits/tree"
)
func (t *guiWidget) MessageWindow(msg1 string, msg2 string) {
ui.MsgBox(t.uiWindow, msg1, msg2)
}
func (t *guiWidget) ErrorWindow(msg1 string, msg2 string) {
ui.MsgBoxError(t.uiWindow, msg1, msg2)
}
func newWindow(p, n *tree.Node) {
var newt *guiWidget
newt = new(guiWidget)
// menubar bool is if the OS defined border on the window should be used
win := ui.NewWindow(n.GetProgName(), 640, 480, menubar)
win.SetBorderless(canvas)
win.SetMargined(margin)
win.OnClosing(func(*ui.Window) bool {
// show(n, false)
me.myTree.DoWindowCloseEvent(n)
return false
})
newt.uiWindow = win
newt.uiControl = win
n.TK = newt
place(p, n)
win.Show()
return
}
func (n *node) SetWindowTitle(title string) {
log.Log(CHANGE, "toolkit NewWindow", widget.GetString(n.value), "title", title)
win := n.tk.uiWindow
if win == nil {
log.Log(ERROR, "Error: no window", n.WidgetId)
} else {
win.SetTitle(title)
log.Log(CHANGE, "Setting the window title", title)
}
}