summaryrefslogtreecommitdiff
path: root/andlabs
diff options
context:
space:
mode:
Diffstat (limited to 'andlabs')
-rw-r--r--andlabs/Makefile7
-rw-r--r--andlabs/action.go265
-rw-r--r--andlabs/add.go157
-rw-r--r--andlabs/box.go29
-rw-r--r--andlabs/button.go31
-rw-r--r--andlabs/checkbox.go27
-rw-r--r--andlabs/combobox.go41
l---------andlabs/common.go1
-rw-r--r--andlabs/debug.go168
-rw-r--r--andlabs/delete.go51
-rw-r--r--andlabs/demo.go90
-rw-r--r--andlabs/dropdown.go79
-rw-r--r--andlabs/grid.go25
-rw-r--r--andlabs/group.go22
-rw-r--r--andlabs/icon.go27
-rw-r--r--andlabs/image.go50
-rw-r--r--andlabs/label.go18
-rw-r--r--andlabs/log.go24
-rw-r--r--andlabs/main.go57
-rw-r--r--andlabs/setText.go128
-rw-r--r--andlabs/slider.go22
-rw-r--r--andlabs/spinner.go22
-rw-r--r--andlabs/structs.go58
-rw-r--r--andlabs/tab.go116
-rw-r--r--andlabs/textbox.go32
-rw-r--r--andlabs/updateui.go97
-rw-r--r--andlabs/widget.go29
-rw-r--r--andlabs/window.go46
28 files changed, 1719 insertions, 0 deletions
diff --git a/andlabs/Makefile b/andlabs/Makefile
new file mode 100644
index 0000000..b839c33
--- /dev/null
+++ b/andlabs/Makefile
@@ -0,0 +1,7 @@
+all: plugin
+
+plugin:
+ GO111MODULE="off" go build -v -x -buildmode=plugin -o ../andlabs.so
+
+goget:
+ GO111MODULE="off" go get -v -t -u
diff --git a/andlabs/action.go b/andlabs/action.go
new file mode 100644
index 0000000..82acd58
--- /dev/null
+++ b/andlabs/action.go
@@ -0,0 +1,265 @@
+package main
+
+import (
+ "strconv"
+ "github.com/andlabs/ui"
+ "go.wit.com/gui/gui/toolkit"
+)
+
+func (n *node) show(b bool) {
+ if n.tk == nil {
+ return
+ }
+ if n.tk.uiControl == nil {
+ return
+ }
+ if (b) {
+ n.tk.uiControl.Show()
+ } else {
+ n.tk.uiControl.Hide()
+ }
+}
+
+func (n *node) enable(b bool) {
+ if n == nil {
+ panic("WHAT? enable was passed nil. How does this even happen?")
+ }
+ if n.tk == nil {
+ return
+ }
+ if n.tk.uiControl == nil {
+ return
+ }
+ if (b) {
+ n.tk.uiControl.Enable()
+ } else {
+ n.tk.uiControl.Disable()
+ }
+}
+
+func (n *node) pad(at toolkit.ActionType) {
+ log(logInfo, "pad() on WidgetId =", n.WidgetId)
+
+ t := n.tk
+ if (t == nil) {
+ log(logError, "pad() toolkit struct == nil. for", n.WidgetId)
+ return
+ }
+
+ switch n.WidgetType {
+ case toolkit.Group:
+ switch at {
+ case toolkit.Margin:
+ t.uiGroup.SetMargined(true)
+ case toolkit.Unmargin:
+ t.uiGroup.SetMargined(false)
+ case toolkit.Pad:
+ t.uiGroup.SetMargined(true)
+ case toolkit.Unpad:
+ t.uiGroup.SetMargined(false)
+ }
+ case toolkit.Tab:
+ switch at {
+ case toolkit.Margin:
+ tabSetMargined(t.uiTab, true)
+ case toolkit.Unmargin:
+ tabSetMargined(t.uiTab, false)
+ case toolkit.Pad:
+ tabSetMargined(t.uiTab, true)
+ case toolkit.Unpad:
+ tabSetMargined(t.uiTab, false)
+ }
+ case toolkit.Window:
+ switch at {
+ case toolkit.Margin:
+ t.uiWindow.SetMargined(true)
+ case toolkit.Unmargin:
+ t.uiWindow.SetMargined(false)
+ case toolkit.Pad:
+ t.uiWindow.SetBorderless(false)
+ case toolkit.Unpad:
+ t.uiWindow.SetBorderless(true)
+ }
+ case toolkit.Grid:
+ switch at {
+ case toolkit.Margin:
+ t.uiGrid.SetPadded(true)
+ case toolkit.Unmargin:
+ t.uiGrid.SetPadded(false)
+ case toolkit.Pad:
+ t.uiGrid.SetPadded(true)
+ case toolkit.Unpad:
+ t.uiGrid.SetPadded(false)
+ }
+ case toolkit.Box:
+ switch at {
+ case toolkit.Margin:
+ t.uiBox.SetPadded(true)
+ case toolkit.Unmargin:
+ t.uiBox.SetPadded(false)
+ case toolkit.Pad:
+ t.uiBox.SetPadded(true)
+ case toolkit.Unpad:
+ t.uiBox.SetPadded(false)
+ }
+ case toolkit.Textbox:
+ log(debugError, "TODO: implement ActionType =", at)
+ default:
+ log(debugError, "TODO: implement pad() for", at)
+ }
+}
+
+func (n *node) move(newParent *node) {
+ p := n.parent
+
+ switch p.WidgetType {
+ case toolkit.Group:
+ case toolkit.Tab:
+ // tabSetMargined(tParent.uiTab, true)
+ case toolkit.Window:
+ // t.uiWindow.SetBorderless(false)
+ case toolkit.Grid:
+ // t.uiGrid.SetPadded(true)
+ case toolkit.Box:
+ log(logInfo, "TODO: move() where =", p.ParentId)
+ log(logInfo, "TODO: move() for widget =", n.WidgetId)
+
+ stretchy = true
+ if (p.tk.uiBox != nil) {
+ p.tk.uiBox.Append(n.tk.uiControl, stretchy)
+ }
+ // log(debugNow, "is there a tParent parent? =", tParent.parent)
+ // tParent.uiBox.Delete(0)
+
+ // this didn't work:
+ // tWidget.uiControl.Disable()
+ // sleep(.8)
+ default:
+ log(logError, "TODO: need to implement move() for type =", n.WidgetType)
+ log(logError, "TODO: need to implement move() for where =", p.ParentId)
+ log(logError, "TODO: need to implement move() for widget =", n.WidgetId)
+ }
+}
+
+func (n *node) Delete() {
+ p := n.parent
+ log(debugNow, "uiDelete()", n.WidgetId, "to", p.WidgetId)
+
+ switch p.WidgetType {
+ case toolkit.Group:
+ // tParent.uiGroup.SetMargined(true)
+ case toolkit.Tab:
+ // tabSetMargined(tParent.uiTab, true)
+ case toolkit.Window:
+ // t.uiWindow.SetBorderless(false)
+ case toolkit.Grid:
+ // t.uiGrid.SetPadded(true)
+ case toolkit.Box:
+ log(debugNow, "tWidget.boxC =", p.Name)
+ log(debugNow, "is there a tParent parent? =", p.parent)
+ if (p.tk.boxC < 1) {
+ log(debugNow, "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(debugError, "TODO: need to implement uiDelete() for widget =", n.WidgetId, n.WidgetType)
+ log(debugError, "TODO: need to implement uiDelete() for parent =", p.WidgetId, p.WidgetType)
+ }
+}
+
+func rawAction(a *toolkit.Action) {
+ log(logInfo, "rawAction() START a.ActionType =", a.ActionType)
+ log(logInfo, "rawAction() START a.S =", a.S)
+
+ if (a.ActionType == toolkit.InitToolkit) {
+ // TODO: make sure to only do this once
+ // go uiMain.Do(func() {
+ // ui.Main(demoUI)
+ // go catchActionChannel()
+ // })
+ // try doing this on toolkit load in init()
+ return
+ }
+
+ log(logInfo, "rawAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId)
+ switch a.WidgetType {
+ case toolkit.Flag:
+ flag(a)
+ return
+ }
+
+ n := me.rootNode.findWidgetId(a.WidgetId)
+
+ if (a.ActionType == toolkit.Add) {
+ ui.QueueMain(func() {
+ add(a)
+ })
+ // TODO: remove this artificial delay
+ // sleep(.001)
+ return
+ }
+
+ if (a.ActionType == toolkit.Dump) {
+ log(debugNow, "rawAction() Dump =", a.ActionType, a.WidgetType, n.Name)
+ me.rootNode.listChildren(true)
+ return
+ }
+
+ if (n == nil) {
+ me.rootNode.listChildren(true)
+ log(true, "rawAction() ERROR findWidgetId found nil", a.ActionType, a.WidgetType)
+ log(true, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId)
+ log(true, "rawAction() ERROR findWidgetId found nil", a.ActionType, a.WidgetType)
+ log(true, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId)
+ return
+ panic("findWidgetId found nil for id = " + strconv.Itoa(a.WidgetId))
+ }
+
+ switch a.ActionType {
+ case toolkit.Show:
+ n.show(true)
+ case toolkit.Hide:
+ n.show(false)
+ case toolkit.Enable:
+ n.enable(true)
+ case toolkit.Disable:
+ n.enable(false)
+ case toolkit.Get:
+ n.setText(a)
+ case toolkit.GetText:
+ switch a.WidgetType {
+ case toolkit.Textbox:
+ a.S = n.S
+ }
+ case toolkit.Set:
+ n.setText(a)
+ case toolkit.SetText:
+ n.setText(a)
+ case toolkit.AddText:
+ n.setText(a)
+ case toolkit.Margin:
+ n.pad(toolkit.Unmargin)
+ case toolkit.Unmargin:
+ n.pad(toolkit.Margin)
+ case toolkit.Pad:
+ n.pad(toolkit.Pad)
+ case toolkit.Unpad:
+ n.pad(toolkit.Unpad)
+ case toolkit.Delete:
+ n.Delete()
+ case toolkit.Move:
+ log(debugNow, "rawAction() attempt to move() =", a.ActionType, a.WidgetType)
+ newParent := me.rootNode.findWidgetId(a.ParentId)
+ n.move(newParent)
+ default:
+ log(debugError, "rawAction() Unknown =", a.ActionType, a.WidgetType)
+ }
+ log(logInfo, "rawAction() END =", a.ActionType, a.WidgetType)
+}
diff --git a/andlabs/add.go b/andlabs/add.go
new file mode 100644
index 0000000..d78101f
--- /dev/null
+++ b/andlabs/add.go
@@ -0,0 +1,157 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+
+ "go.wit.com/gui/gui/toolkit"
+)
+
+func actionDump(b bool, a *toolkit.Action) {
+ log(b, "actionDump() Widget.Type =", a.ActionType)
+ log(b, "actionDump() Widget.S =", a.S)
+ log(b, "actionDump() Widget.I =", a.I)
+ log(b, "actionDump() WidgetId =", a.WidgetId)
+ log(b, "actionDump() ParentId =", a.ParentId)
+}
+
+func add(a *toolkit.Action) {
+ if (a.WidgetType == toolkit.Root) {
+ me.rootNode = addNode(a)
+ return
+ }
+ n := addNode(a)
+
+ p := n.parent
+ switch n.WidgetType {
+ case toolkit.Window:
+ newWindow(n)
+ return
+ case toolkit.Tab:
+ p.newTab(n)
+ return
+ case toolkit.Label:
+ p.newLabel(n)
+ return
+ case toolkit.Button:
+ p.newButton(n)
+ return
+ case toolkit.Grid:
+ p.newGrid(n)
+ return
+ case toolkit.Checkbox:
+ p.newCheckbox(n)
+ return
+ case toolkit.Spinner:
+ p.newSpinner(n)
+ return
+ case toolkit.Slider:
+ p.newSlider(n)
+ return
+ case toolkit.Dropdown:
+ p.newDropdown(n)
+ return
+ case toolkit.Combobox:
+ p.newCombobox(n)
+ return
+ case toolkit.Textbox:
+ p.newTextbox(n)
+ return
+ case toolkit.Group:
+ p.newGroup(n)
+ return
+ case toolkit.Box:
+ p.newBox(n)
+ return
+ case toolkit.Image:
+ p.newImage(n)
+ return
+ default:
+ log(debugError, "add() error TODO: ", n.WidgetType, n.Name)
+ }
+}
+
+// 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 (p *node) place(n *node) bool {
+ log(logInfo, "place() START", n.WidgetType, n.Name)
+
+ if (p.tk == nil) {
+ log(logError, "p.tk == nil", p.Name, p.ParentId, p.WidgetType, p.tk)
+ log(logError, "n = ", n.Name, n.ParentId, n.WidgetType, n.tk)
+ panic("p.tk == nil")
+ }
+
+ log(logInfo, "place() switch", p.WidgetType)
+ switch p.WidgetType {
+ case toolkit.Grid:
+ log(logInfo, "place() Grid try at Parent X,Y =", n.X, n.Y)
+ n.tk.gridX = n.AtW - 1
+ n.tk.gridY = n.AtH - 1
+ log(logInfo, "place() Grid try at gridX,gridY", n.tk.gridX, n.tk.gridY)
+ // at the very end, subtract 1 from X & Y since andlabs/ui starts counting at zero
+ p.tk.uiGrid.Append(n.tk.uiControl,
+ n.tk.gridX, n.tk.gridY, 1, 1,
+ false, ui.AlignFill, false, ui.AlignFill)
+ return true
+ case toolkit.Group:
+ if (p.tk.uiBox == nil) {
+ p.tk.uiGroup.SetChild(n.tk.uiControl)
+ log(logInfo, "place() hack Group to use this as the box?", n.Name, n.WidgetType)
+ p.tk.uiBox = n.tk.uiBox
+ } else {
+ p.tk.uiBox.Append(n.tk.uiControl, stretchy)
+ }
+ return true
+ case toolkit.Tab:
+ if (p.tk.uiTab == nil) {
+ log(logError, "p.tk.uiTab == nil for n.WidgetId =", n.WidgetId, "p.tk =", p.tk)
+ panic("p.tk.uiTab == nil")
+ }
+ if (n.tk.uiControl == nil) {
+ log(logError, "n.tk.uiControl == nil for n.WidgetId =", n.WidgetId, "n.tk =", n.tk)
+ panic("n.tk.uiControl == nil")
+ }
+ log(logError, "CHECK LOGIC ON THIS. APPENDING directly into a window without a tab")
+ // log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() node=", n.WidgetId, n.Name, n.Text, n.WidgetType)
+ // log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.Name, p.Text, p.WidgetType)
+ // panic("n.tk.uiControl == nil")
+ p.tk.uiTab.Append(n.Text, n.tk.uiControl)
+ p.tk.boxC += 1
+ return true
+ case toolkit.Box:
+ log(logInfo, "place() uiBox =", p.tk.uiBox)
+ log(logInfo, "place() uiControl =", n.tk.uiControl)
+ p.tk.uiBox.Append(n.tk.uiControl, stretchy)
+ p.tk.boxC += 1
+ return true
+ case toolkit.Window:
+ p.tk.uiWindow.SetChild(n.tk.uiControl)
+ return true
+ default:
+ log(debugError, "place() how? Parent =", p.WidgetId, p.WidgetType)
+ }
+ return false
+}
diff --git a/andlabs/box.go b/andlabs/box.go
new file mode 100644
index 0000000..e33b7a1
--- /dev/null
+++ b/andlabs/box.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+// make new Box here
+func (p *node) newBox(n *node) {
+ log(debugToolkit, "newBox()", n.Name)
+
+ newt := new(guiWidget)
+ var box *ui.Box
+
+ log(debugToolkit, "rawBox() create", n.Name)
+
+ if (n.B) {
+ box = ui.NewHorizontalBox()
+ } else {
+ box = ui.NewVerticalBox()
+ }
+ box.SetPadded(padded)
+
+ newt.uiBox = box
+ newt.uiControl = box
+ newt.boxC = 0
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/button.go b/andlabs/button.go
new file mode 100644
index 0000000..1dbad5c
--- /dev/null
+++ b/andlabs/button.go
@@ -0,0 +1,31 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newButton(n *node) {
+ log(debugToolkit, "newButton() START", n.Name)
+
+ t := p.tk
+ if (t == nil) {
+ log(debugToolkit, "newButton() toolkit struct == nil. name=", n.Name)
+ return
+ }
+
+ newt := new(guiWidget)
+
+ b := ui.NewButton(n.Text)
+ newt.uiButton = b
+ newt.uiControl = b
+ newt.parent = t
+
+ b.OnClicked(func(*ui.Button) {
+ n.doUserEvent()
+ })
+
+ n.tk = newt
+ p.place(n)
+ log(debugToolkit, "newButton() END", n.Name)
+}
diff --git a/andlabs/checkbox.go b/andlabs/checkbox.go
new file mode 100644
index 0000000..4c37fd6
--- /dev/null
+++ b/andlabs/checkbox.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newCheckbox(n *node) {
+ newt := new(guiWidget)
+ log(debugToolkit, "newCheckbox()", n.Name, n.WidgetType)
+
+ newt.uiCheckbox = ui.NewCheckbox(n.Text)
+ newt.uiControl = newt.uiCheckbox
+
+ newt.uiCheckbox.OnToggled(func(spin *ui.Checkbox) {
+ n.B = newt.checked()
+ log(debugChange, "val =", n.B)
+ n.doUserEvent()
+ })
+
+ n.tk = newt
+ p.place(n)
+}
+
+func (t *guiWidget) checked() bool {
+ return t.uiCheckbox.Checked()
+}
diff --git a/andlabs/combobox.go b/andlabs/combobox.go
new file mode 100644
index 0000000..283a29d
--- /dev/null
+++ b/andlabs/combobox.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newCombobox(n *node) {
+ newt := new(guiWidget)
+ log(debugToolkit, "newCombobox() START", n.Name)
+
+ 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.S = spin.Text()
+ n.doUserEvent()
+ })
+
+ n.tk = newt
+ p.place(n)
+}
+
+func (t *guiWidget) AddComboboxName(title string) {
+ t.uiEditableCombobox.Append(title)
+ if (t.val == nil) {
+ log(debugToolkit, "make map didn't work")
+ return
+ }
+ t.val[t.c] = title
+
+ // If this is the first menu added, set the dropdown to it
+ // if (t.c == 0) {
+ // }
+ t.c = t.c + 1
+}
diff --git a/andlabs/common.go b/andlabs/common.go
new file mode 120000
index 0000000..35417a1
--- /dev/null
+++ b/andlabs/common.go
@@ -0,0 +1 @@
+../nocui/common.go \ No newline at end of file
diff --git a/andlabs/debug.go b/andlabs/debug.go
new file mode 100644
index 0000000..c2ab2a2
--- /dev/null
+++ b/andlabs/debug.go
@@ -0,0 +1,168 @@
+package main
+
+import (
+ "strconv"
+ "go.wit.com/gui/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 = 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(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, "debugAction =", debugPlugin)
+ log(true, "debugFlags =", debugFlags)
+ log(true, "debugNow =", debugNow)
+ log(true, "debugError =", debugError)
+}
+
+func (t *guiWidget) Dump(b bool) {
+ if ! b {
+ return
+ }
+ log(b, "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)
+ }
+}
+
+/*
+func GetDebugToolkit () bool {
+ return debugToolkit
+}
+*/
+
+func flag(a *toolkit.Action) {
+ // should set the checkbox to this value
+ switch a.S {
+ case "Quiet":
+ logInfo = a.B
+ logVerbose = a.B
+ logWarn = a.B
+ logError = a.B
+ case "Error":
+ logError = a.B
+ case "Info":
+ logInfo = a.B
+ case "Verbose":
+ logInfo = a.B
+ logVerbose = a.B
+ logWarn = a.B
+ logError = a.B
+ debugToolkit = a.B
+ debugChange = a.B
+ debugPlugin = a.B
+ debugFlags = a.B
+ case "Toolkit":
+ debugToolkit = a.B
+ case "Change":
+ debugChange = a.B
+ case "Plugin":
+ debugPlugin = a.B
+ case "Flags":
+ debugFlags = a.B
+ case "Now":
+ debugNow = a.B
+ case "Show":
+ ShowDebug()
+ default:
+ log(debugError, "Can't set unknown flag", a.S)
+ }
+}
+
+func (n *node) dumpWidget(b bool) {
+ var info, d string
+
+ if (n == nil) {
+ log(debugError, "dumpWidget() node == nil")
+ return
+ }
+ info = n.WidgetType.String()
+
+ d = strconv.Itoa(n.WidgetId) + " " + info + " " + n.Name
+
+ var tabs string
+ for i := 0; i < listChildrenDepth; i++ {
+ tabs = tabs + defaultPadding
+ }
+ log(b, 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
+ }
+}
diff --git a/andlabs/delete.go b/andlabs/delete.go
new file mode 100644
index 0000000..591d75e
--- /dev/null
+++ b/andlabs/delete.go
@@ -0,0 +1,51 @@
+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/gui/gui/toolkit"
+
+// delete the child widget from the parent
+// p = parent, c = child
+func (n *node) destroy() {
+ pId := n.parent.WidgetId
+ cId := n.WidgetId
+ log(logNow, "delete()", pId, cId)
+
+ pt := n.parent.tk
+ ct := n.tk
+ if (ct == nil) {
+ log(true, "delete FAILED (ct = mapToolkit[c] == nil) for c", pId, cId)
+ // this pukes out a whole universe of shit
+ // listMap()
+ return
+ }
+
+ switch n.WidgetType {
+ case toolkit.Button:
+ log(true, "Should delete Button here:", n.Name)
+ log(true, "Parent:")
+ pt.Dump(true)
+ log(true, "Child:")
+ ct.Dump(true)
+ if (pt.uiBox == nil) {
+ log(true, "Don't know how to destroy this")
+ } else {
+ log(true, "Fuck it, destroy the whole box", n.parent.Name)
+ // 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 toolkit.Window:
+ log(true, "Should delete Window here:", n.Name)
+ default:
+ log(true, "Fuckit, let's destroy a button")
+ if (ct.uiButton != nil) {
+ pt.uiBox.Delete(4)
+ ct.uiButton.Destroy()
+ }
+ }
+}
diff --git a/andlabs/demo.go b/andlabs/demo.go
new file mode 100644
index 0000000..c3cd418
--- /dev/null
+++ b/andlabs/demo.go
@@ -0,0 +1,90 @@
+package main
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+/*
+ 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(debugToolkit, "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
+}
diff --git a/andlabs/dropdown.go b/andlabs/dropdown.go
new file mode 100644
index 0000000..89cbf1a
--- /dev/null
+++ b/andlabs/dropdown.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+
+ "go.wit.com/gui/gui/toolkit"
+)
+
+func (p *node) newDropdown(n *node) {
+ newt := new(guiWidget)
+ log(debugToolkit, "gui.Toolbox.newDropdown() START", n.Name)
+
+ 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(logError, "make map didn't work")
+ n.S = "map did not work. ui.Combobox error"
+ } else {
+ n.S = newt.val[i]
+ }
+ n.doUserEvent()
+ })
+
+ n.tk = newt
+ p.place(n)
+}
+
+func (t *guiWidget) addDropdownName(title string) {
+ t.uiCombobox.Append(title)
+ if (t.val == nil) {
+ log(debugToolkit, "make map didn't work")
+ return
+ }
+ t.val[t.c] = title
+
+ // If this is the first menu added, set the dropdown to it
+ if (t.c == 0) {
+ log(debugChange, "THIS IS THE FIRST Dropdown", title)
+ t.uiCombobox.SetSelected(0)
+ }
+ t.c = t.c + 1
+}
+
+func (t *guiWidget) SetDropdown(i int) {
+ t.uiCombobox.SetSelected(i)
+}
+
+func (n *node) AddDropdownName(s string) {
+ log(logInfo, "AddDropdownName()", n.WidgetId, "add:", s)
+
+ t := n.tk
+ if (t == nil) {
+ log(logInfo, "AddDropdownName() toolkit struct == nil. name=", n.Name, s)
+ return
+ }
+ t.addDropdownName(s)
+}
+
+func (n *node) SetDropdownName(a *toolkit.Action, s string) {
+ log(logInfo, "SetDropdown()", n.WidgetId, ",", s)
+
+ t := n.tk
+ if (t == nil) {
+ log(debugError, "SetDropdown() FAILED mapToolkits[w] == nil. name=", n.WidgetId, s)
+ return
+ }
+ t.SetDropdown(1)
+ // TODO: send back to wit/gui goroutine with the chan
+ n.S = s
+}
diff --git a/andlabs/grid.go b/andlabs/grid.go
new file mode 100644
index 0000000..6c47d1b
--- /dev/null
+++ b/andlabs/grid.go
@@ -0,0 +1,25 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+// Grid numbering by (X,Y)
+// -----------------------------
+// -- (1,1) -- (2,1) -- (3,1) --
+// -- (1,2) -- (2,1) -- (3,1) --
+// -----------------------------
+func (p *node) newGrid(n *node) {
+ var newt *guiWidget
+ log(debugToolkit, "newGrid()", n.WidgetId, "to", n.ParentId)
+
+ newt = new(guiWidget)
+
+ c := ui.NewGrid()
+ newt.uiGrid = c
+ newt.uiControl = c
+
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/group.go b/andlabs/group.go
new file mode 100644
index 0000000..b7c450e
--- /dev/null
+++ b/andlabs/group.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newGroup(n *node) {
+ log(debugToolkit, "NewGroup()", n.Name)
+
+ newt := new(guiWidget)
+
+ log(debugToolkit, "NewGroup() create", n.Name)
+
+ g := ui.NewGroup(n.Name)
+ g.SetMargined(margin)
+ newt.uiGroup = g
+ newt.uiControl = g
+
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/icon.go b/andlabs/icon.go
new file mode 100644
index 0000000..00c25f6
--- /dev/null
+++ b/andlabs/icon.go
@@ -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,
+}
diff --git a/andlabs/image.go b/andlabs/image.go
new file mode 100644
index 0000000..bab1a9e
--- /dev/null
+++ b/andlabs/image.go
@@ -0,0 +1,50 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+// make new Image using andlabs/ui
+func (p *node) newImage(n *node) {
+ newt := new(guiWidget)
+ var img *ui.Image
+
+ log(debugToolkit, "rawImage() create", n.Name)
+
+ 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)
+ }
+*/
diff --git a/andlabs/label.go b/andlabs/label.go
new file mode 100644
index 0000000..3f06546
--- /dev/null
+++ b/andlabs/label.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newLabel(n *node) {
+ log(logInfo, "NewLabel()", n.Name)
+
+ newt := new(guiWidget)
+ c := ui.NewLabel(n.Name)
+ newt.uiLabel = c
+ newt.uiControl = c
+
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/log.go b/andlabs/log.go
new file mode 100644
index 0000000..5f5b81b
--- /dev/null
+++ b/andlabs/log.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ witlog "go.wit.com/log"
+)
+
+// various debugging flags
+var logNow bool = true // useful for active development
+var logError bool = true
+var logWarn bool = true
+var logInfo bool = false
+var logVerbose bool = false
+
+func log(b bool, a ...any) {
+ witlog.Log(b, a...)
+}
+
+func sleep(a ...any) {
+ witlog.Sleep(a...)
+}
+
+func exit(a ...any) {
+ witlog.Exit(a...)
+}
diff --git a/andlabs/main.go b/andlabs/main.go
new file mode 100644
index 0000000..c1fc7ac
--- /dev/null
+++ b/andlabs/main.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "sync"
+ "go.wit.com/gui/gui/toolkit"
+
+ "github.com/andlabs/ui"
+ // the _ means we only need this for the init()
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+var uiMainUndef bool = true
+var uiMain sync.Once
+var muAction sync.Mutex
+
+func catchActionChannel() {
+ log(logInfo, "catchActionChannel() START")
+ for {
+ log(logInfo, "catchActionChannel() for loop")
+ select {
+ case a := <-pluginChan:
+ log(logInfo, "catchActionChannel() SELECT widget id =", a.WidgetId, a.Name)
+ log(logInfo, "catchActionChannel() STUFF", a.WidgetId, a.ActionType, a.WidgetType)
+ muAction.Lock()
+ // TODO ui.QueueMain(f)
+ // TODO ui.QueueMain( func() {rawAction(a)} )
+ ui.QueueMain( func() {rawAction(&a)} )
+ // rawAction(a)
+ muAction.Unlock()
+ log(logInfo, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
+ }
+ }
+}
+
+// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
+func init() {
+ log(logNow, "Init() START")
+ log(debugToolkit, "Init()")
+ // Can you pass values to a plugin init() ? Otherwise, there is no way to safely print
+ // log(debugToolkit, "init() Setting defaultBehavior = true")
+ setDefaultBehavior(true)
+
+
+ // 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 ui.Main(func() {
+ demoUI()
+ })
+
+ // andlabs = make(map[int]*andlabsT)
+ pluginChan = make(chan toolkit.Action, 1)
+
+ log(logNow, "Init() start channel reciever")
+ go catchActionChannel()
+ log(logNow, "Init() END")
+}
diff --git a/andlabs/setText.go b/andlabs/setText.go
new file mode 100644
index 0000000..7452982
--- /dev/null
+++ b/andlabs/setText.go
@@ -0,0 +1,128 @@
+package main
+
+import (
+ "go.wit.com/gui/gui/toolkit"
+)
+
+func (n *node) setText(a *toolkit.Action) {
+ log(debugChange, "setText() START with a.S =", a.S)
+ t := n.tk
+ if (t == nil) {
+ log(debugError, "setText error. tk == nil", n.Name, n.WidgetId)
+ actionDump(debugError, a)
+ return
+ }
+ log(debugChange, "setText() Attempt on", n.WidgetType, "with", a.S)
+
+ switch n.WidgetType {
+ case toolkit.Window:
+ t.uiWindow.SetTitle(a.S)
+ case toolkit.Tab:
+ case toolkit.Group:
+ t.uiGroup.SetTitle(a.S)
+ case toolkit.Checkbox:
+ switch a.ActionType {
+ case toolkit.SetText:
+ t.uiCheckbox.SetText(a.S)
+ case toolkit.Get:
+ n.B = t.uiCheckbox.Checked()
+ case toolkit.Set:
+ // TODO: commented out while working on chan
+ t.uiCheckbox.SetChecked(a.B)
+ default:
+ log(debugError, "setText() unknown", a.ActionType, "on checkbox", n.Name)
+ }
+ case toolkit.Textbox:
+ switch a.ActionType {
+ case toolkit.Set:
+ if (t.uiEntry != nil) {
+ t.uiEntry.SetText(a.S)
+ }
+ if (t.uiMultilineEntry != nil) {
+ t.uiMultilineEntry.SetText(a.S)
+ }
+ case toolkit.SetText:
+ if (t.uiEntry != nil) {
+ t.uiEntry.SetText(a.S)
+ }
+ if (t.uiMultilineEntry != nil) {
+ t.uiMultilineEntry.SetText(a.S)
+ }
+ default:
+ log(debugError, "setText() unknown", a.ActionType, "on checkbox", n.Name)
+ }
+ case toolkit.Label:
+ t.uiLabel.SetText(a.S)
+ case toolkit.Button:
+ t.uiButton.SetText(a.S)
+ case toolkit.Slider:
+ switch a.ActionType {
+ case toolkit.Get:
+ n.I = t.uiSlider.Value()
+ case toolkit.Set:
+ t.uiSlider.SetValue(a.I)
+ default:
+ log(debugError, "setText() unknown", a.ActionType, "on checkbox", n.Name)
+ }
+ case toolkit.Spinner:
+ switch a.ActionType {
+ case toolkit.Get:
+ n.I = t.uiSpinbox.Value()
+ case toolkit.Set:
+ t.uiSpinbox.SetValue(a.I)
+ default:
+ log(debugError, "setText() unknown", a.ActionType, "on checkbox", n.Name)
+ }
+ case toolkit.Dropdown:
+ switch a.ActionType {
+ case toolkit.AddText:
+ n.AddDropdownName(a.S)
+ case toolkit.Set:
+ var orig int
+ var i int = -1
+ var s string
+ orig = t.uiCombobox.Selected()
+ log(debugChange, "try to set the Dropdown to", a.S, "from", orig)
+ // try to find the string
+ for i, s = range t.val {
+ log(debugChange, "i, s", i, s)
+ if (a.S == s) {
+ t.uiCombobox.SetSelected(i)
+ log(debugChange, "setText() Dropdown worked.", n.S)
+ return
+ }
+ }
+ log(debugError, "setText() Dropdown did not find:", a.S)
+ // 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) {
+ t.uiCombobox.SetSelected(i)
+ }
+ case toolkit.Get:
+ // t.S = t.s
+ case toolkit.GetText:
+ // t.S = t.s
+ default:
+ log(debugError, "setText() unknown", a.ActionType, "on checkbox", n.Name)
+ }
+ case toolkit.Combobox:
+ switch a.ActionType {
+ case toolkit.AddText:
+ t.AddComboboxName(a.S)
+ case toolkit.Set:
+ t.uiEditableCombobox.SetText(a.S)
+ n.S = a.S
+ case toolkit.SetText:
+ t.uiEditableCombobox.SetText(a.S)
+ n.S = a.S
+ default:
+ log(debugError, "setText() unknown", a.ActionType, "on checkbox", n.Name)
+ }
+ default:
+ log(debugError, "plugin Send() Don't know how to setText on", n.WidgetType, "yet", a.ActionType)
+ }
+ log(debugChange, "setText() END with a.S =", a.S)
+}
diff --git a/andlabs/slider.go b/andlabs/slider.go
new file mode 100644
index 0000000..5098943
--- /dev/null
+++ b/andlabs/slider.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newSlider(n *node) {
+ newt := new(guiWidget)
+
+ s := ui.NewSlider(n.X, n.Y)
+ newt.uiSlider = s
+ newt.uiControl = s
+
+ s.OnChanged(func(spin *ui.Slider) {
+ n.I = newt.uiSlider.Value()
+ n.doUserEvent()
+ })
+
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/spinner.go b/andlabs/spinner.go
new file mode 100644
index 0000000..bab7a29
--- /dev/null
+++ b/andlabs/spinner.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newSpinner(n *node) {
+ newt := new(guiWidget)
+
+ s := ui.NewSpinbox(n.X, n.Y)
+ newt.uiSpinbox = s
+ newt.uiControl = s
+
+ s.OnChanged(func(s *ui.Spinbox) {
+ n.I = newt.uiSpinbox.Value()
+ n.doUserEvent()
+ })
+
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/structs.go b/andlabs/structs.go
new file mode 100644
index 0000000..81c4669
--- /dev/null
+++ b/andlabs/structs.go
@@ -0,0 +1,58 @@
+package main
+
+import "github.com/andlabs/ui"
+import _ "github.com/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 *node // the base of the binary tree. it should have id == 0
+}
+
+// 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
+}
diff --git a/andlabs/tab.go b/andlabs/tab.go
new file mode 100644
index 0000000..d075a51
--- /dev/null
+++ b/andlabs/tab.go
@@ -0,0 +1,116 @@
+package main
+
+import (
+ "go.wit.com/gui/gui/toolkit"
+
+ "github.com/andlabs/ui"
+ _ "github.com/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(debugError, "newTab() p == nil. how the fuck does this happen?", n.WidgetId, n.ParentId)
+ }
+ if (p.WidgetType != toolkit.Window) {
+ log(debugError, "newTab() uiWindow == nil. I can't add a toolbar without window", n.WidgetId, n.ParentId)
+ return
+ }
+ t := p.tk
+
+ log(debugToolkit, "newTab() START", n.WidgetId, n.ParentId)
+
+ if (t.uiTab == nil) {
+ // this means you have to make a new tab
+ log(debugToolkit, "newTab() GOOD. This should be the first tab:", n.WidgetId, n.ParentId)
+ newt = rawTab(t.uiWindow, n.Text)
+ t.uiTab = newt.uiTab
+ } else {
+ // this means you have to append a tab
+ log(debugToolkit, "newTab() GOOD. This should be an additional tab:", n.WidgetId, n.ParentId)
+ if (n.WidgetType == toolkit.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(n.Text)
+ }
+ }
+
+ 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(debugToolkit, "SetMargined", i, b)
+ tab.SetMargined(i, b)
+ }
+}
+
+func rawTab(w *ui.Window, name string) *guiWidget {
+ var newt guiWidget
+ log(debugToolkit, "rawTab() START", name)
+
+ if (w == nil) {
+ log(debugError, "UiWindow == nil. I can't add a tab without a window")
+ log(debugError, "UiWindow == nil. I can't add a tab without a window")
+ log(debugError, "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(debugToolkit, "rawTab() END", name)
+ return &newt
+}
+
+func (t *guiWidget) appendTab(name string) *guiWidget {
+ var newT guiWidget
+ log(debugToolkit, "appendTab() ADD", name)
+
+ if (t.uiTab == nil) {
+ log(debugToolkit, "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(debugToolkit, "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
+}
diff --git a/andlabs/textbox.go b/andlabs/textbox.go
new file mode 100644
index 0000000..7cb5d63
--- /dev/null
+++ b/andlabs/textbox.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (p *node) newTextbox(n *node) {
+ newt := new(guiWidget)
+
+ if (n.X == 1) {
+ e := ui.NewEntry()
+ newt.uiEntry = e
+ newt.uiControl = e
+
+ e.OnChanged(func(spin *ui.Entry) {
+ n.S = spin.Text()
+ n.doUserEvent()
+ })
+ } else {
+ e := ui.NewNonWrappingMultilineEntry()
+ newt.uiMultilineEntry = e
+ newt.uiControl = e
+
+ e.OnChanged(func(spin *ui.MultilineEntry) {
+ n.S = spin.Text()
+ n.doUserEvent()
+ })
+ }
+ n.tk = newt
+ p.place(n)
+}
diff --git a/andlabs/updateui.go b/andlabs/updateui.go
new file mode 100644
index 0000000..c43e15f
--- /dev/null
+++ b/andlabs/updateui.go
@@ -0,0 +1,97 @@
+package main
+
+import (
+ "github.com/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)
+}
+*/
diff --git a/andlabs/widget.go b/andlabs/widget.go
new file mode 100644
index 0000000..cf05a9e
--- /dev/null
+++ b/andlabs/widget.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+ "go.wit.com/gui/gui/toolkit"
+)
+
+// this is specific to the nocui toolkit
+func initWidget(n *node) *guiWidget {
+ var w *guiWidget
+ w = new(guiWidget)
+ // Set(w, "default")
+
+ if n.WidgetType == toolkit.Root {
+ log(logInfo, "setupWidget() FOUND ROOT w.id =", n.WidgetId)
+ n.WidgetId = 0
+ me.rootNode = n
+ return w
+ }
+
+ if (n.WidgetType == toolkit.Box) {
+ if (n.B) {
+ n.horizontal = true
+ } else {
+ n.horizontal = false
+ }
+ }
+
+ return w
+}
diff --git a/andlabs/window.go b/andlabs/window.go
new file mode 100644
index 0000000..f51536b
--- /dev/null
+++ b/andlabs/window.go
@@ -0,0 +1,46 @@
+package main
+
+import (
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+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(n *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.Name, n.X, n.Y, menubar)
+ win.SetBorderless(canvas)
+ win.SetMargined(margin)
+ win.OnClosing(func(*ui.Window) bool {
+ n.doUserEvent()
+ return true
+ })
+ newt.uiWindow = win
+ newt.uiControl = win
+
+ n.tk = newt
+ win.Show()
+ return
+}
+
+func (n *node) SetWindowTitle(title string) {
+ log(debugToolkit, "toolkit NewWindow", n.Text, "title", title)
+ win := n.tk.uiWindow
+ if (win == nil) {
+ log(debugError, "Error: no window", n.WidgetId)
+ } else {
+ win.SetTitle(title)
+ log(debugToolkit, "Setting the window title", title)
+ }
+}