summaryrefslogtreecommitdiff
path: root/toolkit/andlabs-direct
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2022-11-14 14:30:28 -0600
committerJeff Carr <[email protected]>2022-11-14 14:30:28 -0600
commit355e5ec968427c2b07b78fec12224f31a65df740 (patch)
tree99754f9f6888c166a435d14e3a71cc9304f14970 /toolkit/andlabs-direct
parent207cf7ea16f1da8fa9f893504d77a2856298cc22 (diff)
setup building without plugins on windowsv0.5.1
notes from github remote keep removing os.Exit() rename from andlabs2 back to andlabs rename files for windows andlabs/ui gocui always sets STDOUT a file in /tmp/ Signed-off-by: Jeff Carr <[email protected]>
Diffstat (limited to 'toolkit/andlabs-direct')
-rw-r--r--toolkit/andlabs-direct/box.go66
-rw-r--r--toolkit/andlabs-direct/button.go79
-rw-r--r--toolkit/andlabs-direct/checkbox.go34
-rw-r--r--toolkit/andlabs-direct/common.go61
-rw-r--r--toolkit/andlabs-direct/demo.go92
-rw-r--r--toolkit/andlabs-direct/dropdown.go55
-rw-r--r--toolkit/andlabs-direct/group.go42
-rw-r--r--toolkit/andlabs-direct/label.go21
-rw-r--r--toolkit/andlabs-direct/main.go31
-rw-r--r--toolkit/andlabs-direct/old/area.go136
-rw-r--r--toolkit/andlabs-direct/old/color.go31
-rw-r--r--toolkit/andlabs-direct/old/seperator.go25
-rw-r--r--toolkit/andlabs-direct/old/structs.go273
-rw-r--r--toolkit/andlabs-direct/old/table.go150
-rw-r--r--toolkit/andlabs-direct/old/tableCallbacks.go108
-rw-r--r--toolkit/andlabs-direct/slider.go31
-rw-r--r--toolkit/andlabs-direct/spinner.go30
-rw-r--r--toolkit/andlabs-direct/structs.go249
-rw-r--r--toolkit/andlabs-direct/tab.go133
-rw-r--r--toolkit/andlabs-direct/textbox.go34
-rw-r--r--toolkit/andlabs-direct/window.go66
21 files changed, 1747 insertions, 0 deletions
diff --git a/toolkit/andlabs-direct/box.go b/toolkit/andlabs-direct/box.go
new file mode 100644
index 0000000..29a8331
--- /dev/null
+++ b/toolkit/andlabs-direct/box.go
@@ -0,0 +1,66 @@
+package toolkit
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+// create a new box
+func (t *Toolkit) GetBox() *ui.Box {
+ return t.uiBox
+}
+
+// create a new box
+func (t *Toolkit) NewBox() *Toolkit {
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewBox() START create default")
+ }
+ t.Dump()
+ if (t.uiGroup != nil) {
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() is a Group")
+ }
+ var newTK Toolkit
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(padded)
+ t.uiGroup.SetChild(vbox)
+ newTK.uiBox = vbox
+
+ return &newTK
+ }
+ if (t.uiBox != nil) {
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() is a Box")
+ }
+ var newTK Toolkit
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(padded)
+ t.uiBox.Append(vbox, stretchy)
+ newTK.uiBox = vbox
+ newTK.Name = t.Name
+
+ return &newTK
+ }
+ if (t.uiWindow != nil) {
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() is a Window")
+ }
+ var newT Toolkit
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(padded)
+ t.uiWindow.SetChild(vbox)
+ newT.uiBox = vbox
+ newT.Name = t.Name
+
+ // panic("WTF")
+ return &newT
+ }
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box")
+ }
+ t.Dump()
+ return nil
+}
diff --git a/toolkit/andlabs-direct/button.go b/toolkit/andlabs-direct/button.go
new file mode 100644
index 0000000..e0b7d97
--- /dev/null
+++ b/toolkit/andlabs-direct/button.go
@@ -0,0 +1,79 @@
+package toolkit
+
+import "log"
+// import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+// make new Group here
+func (t Toolkit) NewButton(name string) *Toolkit {
+ var newt Toolkit
+ var b *ui.Button
+
+ if t.broken() {
+ return nil
+ }
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewButton() create", name)
+ }
+ b = ui.NewButton(name)
+ newt.uiButton = b
+
+ b.OnClicked(func(*ui.Button) {
+ log.Println("TODO: IN TOOLKIT GOROUTINE. SHOULD LEAVE HERE VIA channels. button name =", name)
+ t.Dump()
+ newt.Dump()
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() Should do something here")
+ }
+ if (newt.Custom == nil) {
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() toolkit.Custom == nil")
+ }
+ } else {
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() toolkit.Custom() START")
+ }
+ newt.Custom()
+ return
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() toolkit.Custom() END")
+ }
+ }
+ if (t.Custom == nil) {
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() parent toolkit.Custom == nil")
+ }
+ } else {
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() START (IS THIS A BAD IDEA?)")
+ }
+ t.Custom()
+ return
+ if (DebugToolkit) {
+ log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() END (IS THIS A BAD IDEA?)")
+ }
+ }
+ log.Println("TODO: LEFT TOOLKIT GOROUTINE WITH NOTHING TO DO button name =", name)
+ })
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewButton() about to append to Box parent t:", name)
+ t.Dump()
+ log.Println("gui.Toolbox.NewButton() about to append to Box new t:", name)
+ newt.Dump()
+ }
+ if (t.uiBox != nil) {
+ t.uiBox.Append(b, stretchy)
+ } else if (t.uiWindow != nil) {
+ t.uiWindow.SetChild(b)
+ } else {
+ log.Println("ERROR: wit/gui andlabs couldn't place this button in a box or a window")
+ log.Println("ERROR: wit/gui andlabs couldn't place this button in a box or a window")
+ return &t
+ }
+
+ return &newt
+}
diff --git a/toolkit/andlabs-direct/checkbox.go b/toolkit/andlabs-direct/checkbox.go
new file mode 100644
index 0000000..b3b3121
--- /dev/null
+++ b/toolkit/andlabs-direct/checkbox.go
@@ -0,0 +1,34 @@
+package toolkit
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t Toolkit) NewCheckbox(name string) *Toolkit {
+ log.Println("gui.Toolkit.NewCheckbox()", name)
+ var newt Toolkit
+
+ if t.broken() {
+ return nil
+ }
+
+ c := ui.NewCheckbox(name)
+ newt.uiCheckbox = c
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(c, stretchy)
+
+ c.OnToggled(func(spin *ui.Checkbox) {
+ newt.commonChange("Checkbox")
+ })
+
+ return &newt
+}
+
+func (t Toolkit) Checked() bool {
+ if t.broken() {
+ return false
+ }
+
+ return t.uiCheckbox.Checked()
+}
diff --git a/toolkit/andlabs-direct/common.go b/toolkit/andlabs-direct/common.go
new file mode 100644
index 0000000..451f9d6
--- /dev/null
+++ b/toolkit/andlabs-direct/common.go
@@ -0,0 +1,61 @@
+package toolkit
+
+import "log"
+
+func init() {
+ if (DebugToolkit) {
+ log.Println("gui/toolkit init() Setting defaultBehavior = true")
+ }
+ setDefaultBehavior(true)
+}
+
+func (t Toolkit) commonChange(widget string) {
+ s := t.String()
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.ui.OnChanged() =", s)
+ }
+ if (t.OnChanged != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.OnChanged() trying to run toolkit.OnChanged() entered val =", s)
+ }
+ t.OnChanged(&t)
+ return
+ }
+ if (t.Custom != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.OnChanged() Running toolkit.Custom()")
+ t.Dump()
+ }
+ t.Custom()
+ return
+ }
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.OnChanged() ENDED without finding any callback")
+ }
+}
+
+// does some sanity checks on the internal structs of the binary tree
+// TODO: probably this should not panic unless it's running in devel mode (?)
+func (t *Toolkit) broken() bool {
+ if (t.uiBox == nil) {
+ if (t.uiWindow != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.UiBox == nil. This is an empty window. Try to add a box")
+ }
+ t.NewBox()
+ return false
+ }
+ log.Println("gui.Toolkit.UiBox == nil. I can't add a widget without a place to put it")
+ // log.Println("probably could just make a box here?")
+ // corruption or something horrible?
+ panic("wit/gui toolkit/andlabs func broken() invalid goroutine access into this toolkit?")
+ panic("wit/gui toolkit/andlabs func broken() this probably should not cause the app to panic here (?)")
+ return true
+ }
+ if (t.uiWindow == nil) {
+ log.Println("gui.Toolkit.UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)")
+ forceDump(t)
+ return false
+ }
+ return false
+}
diff --git a/toolkit/andlabs-direct/demo.go b/toolkit/andlabs-direct/demo.go
new file mode 100644
index 0000000..7ba1822
--- /dev/null
+++ b/toolkit/andlabs-direct/demo.go
@@ -0,0 +1,92 @@
+package toolkit
+
+import "log"
+
+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 *Toolkit) DemoNumbersPage() {
+ var w *ui.Window
+
+ log.Println("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/toolkit/andlabs-direct/dropdown.go b/toolkit/andlabs-direct/dropdown.go
new file mode 100644
index 0000000..ca09a99
--- /dev/null
+++ b/toolkit/andlabs-direct/dropdown.go
@@ -0,0 +1,55 @@
+package toolkit
+
+import "log"
+import "os"
+// import "time"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t *Toolkit) NewDropdown(title string) *Toolkit {
+ // make new node here
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewDropdownCombobox()", title)
+ }
+ var newt Toolkit
+
+ if t.broken() {
+ return nil
+ }
+
+ s := ui.NewCombobox()
+ newt.uiCombobox = s
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(s, stretchy)
+
+ // initialize the index
+ newt.c = 0
+ newt.val = make(map[int]string)
+
+ s.OnSelected(func(spin *ui.Combobox) {
+ i := spin.Selected()
+ if (newt.val == nil) {
+ log.Println("make map didn't work")
+ os.Exit(0)
+ }
+ newt.text = newt.val[i]
+ newt.commonChange("Dropdown")
+ })
+
+ return &newt
+}
+
+func (t *Toolkit) AddDropdown(title string) {
+ t.uiCombobox.Append(title)
+ if (t.val == nil) {
+ log.Println("make map didn't work")
+ return
+ }
+ t.val[t.c] = title
+ t.c = t.c + 1
+}
+
+func (t Toolkit) SetDropdown(i int) {
+ t.uiCombobox.SetSelected(i)
+}
diff --git a/toolkit/andlabs-direct/group.go b/toolkit/andlabs-direct/group.go
new file mode 100644
index 0000000..5b315a4
--- /dev/null
+++ b/toolkit/andlabs-direct/group.go
@@ -0,0 +1,42 @@
+package toolkit
+
+import "log"
+import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+// make new Group here
+func (t Toolkit) NewGroup(title string) *Toolkit {
+ var newt Toolkit
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewGroup() create", title)
+ }
+ g := ui.NewGroup(title)
+ g.SetMargined(margin)
+
+ if (t.uiBox != nil) {
+ t.uiBox.Append(g, stretchy)
+ } else if (t.uiWindow != nil) {
+ t.uiWindow.SetChild(g)
+ } else {
+ log.Println("gui.ToolboxNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
+ log.Println("probably could just make a box here?")
+ os.Exit(0)
+ }
+
+ hbox := ui.NewVerticalBox()
+ hbox.SetPadded(padded)
+ g.SetChild(hbox)
+
+ newt.uiGroup = g
+ newt.uiBox = hbox
+ newt.uiWindow = t.uiWindow
+ newt.Name = title
+
+ t.Dump()
+ newt.Dump()
+ // panic("toolkit.NewGroup")
+ return &newt
+}
diff --git a/toolkit/andlabs-direct/label.go b/toolkit/andlabs-direct/label.go
new file mode 100644
index 0000000..2819ff1
--- /dev/null
+++ b/toolkit/andlabs-direct/label.go
@@ -0,0 +1,21 @@
+package toolkit
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t *Toolkit) NewLabel(name string) *Toolkit {
+ // make new node here
+ log.Println("gui.Toolbox.NewLabel", name)
+
+ if t.broken() {
+ return nil
+ }
+ var newt Toolkit
+ newt.uiLabel = ui.NewLabel(name)
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(newt.uiLabel, false)
+
+ return &newt
+}
diff --git a/toolkit/andlabs-direct/main.go b/toolkit/andlabs-direct/main.go
new file mode 100644
index 0000000..da639fa
--- /dev/null
+++ b/toolkit/andlabs-direct/main.go
@@ -0,0 +1,31 @@
+package toolkit
+
+import (
+ "log"
+
+ "github.com/andlabs/ui"
+ // the _ means we only need this for the init()
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func Main(f func()) {
+ if (DebugToolkit) {
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ }
+ ui.Main(f)
+}
+
+// Other goroutines must use this to access the GUI
+//
+// You can not acess / process the GUI thread directly from
+// other goroutines. This is due to the nature of how
+// Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
+//
+// For example: Queue(NewWindow())
+//
+func Queue(f func()) {
+ if (DebugToolkit) {
+ log.Println("Sending function to gui.Main() (using gtk via andlabs/ui)")
+ }
+ ui.QueueMain(f)
+}
diff --git a/toolkit/andlabs-direct/old/area.go b/toolkit/andlabs-direct/old/area.go
new file mode 100644
index 0000000..7c42c6c
--- /dev/null
+++ b/toolkit/andlabs-direct/old/area.go
@@ -0,0 +1,136 @@
+package gui
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "github.com/davecgh/go-spew/spew"
+
+func makeGenericArea(gb *GuiBox, newText *ui.AttributedString, custom func(*GuiButton)) {
+ // make this button just to get the default font (but don't display the button)
+ // There should be another way to do this (?)
+ var newB *GuiButton
+ newB = CreateFontButton(gb, "AREA")
+ newB.Box = gb
+ newB.Custom = custom
+
+ gw := gb.Window
+ // initialize the GuiArea{}
+ gw.Area = new(GuiArea)
+ gw.Area.Button = newB
+ gw.Area.Box = gb
+ gw.Area.UiAttrstr = newText
+ gw.Area.UiArea = ui.NewArea(gw.Area)
+
+ if (Config.Debug) {
+ spew.Dump(gw.Area.UiArea)
+ log.Println("DEBUGGING", Config.Debug)
+ } else {
+ log.Println("NOT DEBUGGING AREA mhAH.Button =", gw.Area.Button)
+ }
+}
+
+func AreaAppendText(newText *ui.AttributedString, what string, attrs ...ui.Attribute) {
+ start := len(newText.String())
+ end := start + len(what)
+ newText.AppendUnattributed(what)
+ for _, a := range attrs {
+ newText.SetAttribute(a, start, end)
+ }
+}
+
+func appendWithAttributes(newText *ui.AttributedString, what string, attrs ...ui.Attribute) {
+ start := len(newText.String())
+ end := start + len(what)
+ newText.AppendUnattributed(what)
+ for _, a := range attrs {
+ newText.SetAttribute(a, start, end)
+ }
+}
+
+func (ah GuiArea) Draw(a *ui.Area, p *ui.AreaDrawParams) {
+ tl := ui.DrawNewTextLayout(&ui.DrawTextLayoutParams{
+ String: ah.UiAttrstr,
+ DefaultFont: ah.Button.FB.Font(),
+ Width: p.AreaWidth,
+ Align: ui.DrawTextAlign(1),
+ })
+ p.Context.Text(tl, 0, 0)
+ defer tl.Free()
+}
+
+func (ah GuiArea) MouseEvent(a *ui.Area, me *ui.AreaMouseEvent) {
+ if (Config.Debug) {
+ log.Println("GOT MouseEvent() ah.Button =", ah.Button)
+ spew.Dump(me)
+ }
+ if (me.Down == 1) {
+ log.Println("GOT MOUSE DOWN")
+ log.Println("GOT MOUSE DOWN ah.Button =", ah.Button)
+ log.Println("GOT MOUSE UP ah.Button.FB =", ah.Button.FB)
+ }
+ if (me.Up == 1) {
+ log.Println("GOT MOUSE UP")
+ log.Println("GOT MOUSE UP ah.Button =", ah.Button)
+ log.Println("GOT MOUSE UP ah.Button.FB =", ah.Button.FB)
+ if (ah.Button.Custom != nil) {
+ ah.Button.Custom(ah.Button)
+ } else if (Data.MouseClick != nil) {
+ Data.MouseClick(ah.Button)
+ }
+ }
+}
+
+func (ah GuiArea) MouseCrossed(a *ui.Area, left bool) {
+ log.Println("GOT MouseCrossed()")
+}
+
+func (ah GuiArea) DragBroken(a *ui.Area) {
+ log.Println("GOT DragBroken()")
+}
+
+// TODO: fix KeyEvents
+func (ah GuiArea) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) {
+ log.Println("GOT KeyEvent()")
+ if (ke.Key == 10) {
+ log.Println("GOT ENTER")
+ log.Println("GOT ENTER")
+ log.Println("GOT ENTER")
+ }
+ if (ke.Key == 32) {
+ log.Println("GOT ENTER")
+ log.Println("GOT ENTER")
+ log.Println("GOT ENTER")
+ }
+ spew.Dump(ke)
+ return false
+}
+
+func (b *GuiBox) ShowTextBox(newText *ui.AttributedString, custom func(*GuiButton), name string) {
+ log.Println("ShowTextBox() START")
+
+ gw := b.Window
+ if (gw == nil) {
+ log.Println("ShowTextBox() ERROR gw = nil")
+ return
+ }
+ log.Println("ShowTextBox() START gw =", gw)
+
+ /*
+ var newbox *GuiBox
+ newbox = new(GuiBox)
+ newbox.Window = gw
+ newbox.Name = name
+ hbox := ui.NewVerticalBox()
+ newbox.UiBox = hbox
+ */
+
+ // TODO: allow padded & axis here
+ b.UiBox.SetPadded(true)
+
+ // add(gw.BoxMap["MAINBOX"], newbox)
+
+ makeGenericArea(b, newText, custom)
+ b.UiBox.Append(b.Window.Area.UiArea, true)
+}
diff --git a/toolkit/andlabs-direct/old/color.go b/toolkit/andlabs-direct/old/color.go
new file mode 100644
index 0000000..cf4a362
--- /dev/null
+++ b/toolkit/andlabs-direct/old/color.go
@@ -0,0 +1,31 @@
+package gui
+
+//
+// convert between 'standard' golang Color and andlabs/ui Color
+//
+
+// import "log"
+// import "fmt"
+import "image/color"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func libuiColorToGOlangColor(rgba color.RGBA) ui.TableColor {
+ /* a hack to see if colors work differently on macos or windows
+ if (rgba.R == 72) {
+ log.Println("SETTING COLOR TO NIL")
+ log.Println("SETTING COLOR TO NIL")
+ log.Println("SETTING COLOR TO NIL")
+ return ui.TableColor{}
+ }
+ */
+ return ui.TableColor{float64(rgba.R) / 256, float64(rgba.G) / 256, float64(rgba.B) / 256, float64(rgba.A) / 256}
+}
+
+/*
+func golangColorGOlibuiColorTo (ui.TableColor) (rgba color.RGBA) {
+ color.RGBA{float64(, 100, 200, 100}
+ return ui.TableColor{float64(rgba.R) / 256, float64(rgba.G) / 256, float64(rgba.B) / 256, float64(rgba.A) / 256}
+}
+*/
diff --git a/toolkit/andlabs-direct/old/seperator.go b/toolkit/andlabs-direct/old/seperator.go
new file mode 100644
index 0000000..ca152a8
--- /dev/null
+++ b/toolkit/andlabs-direct/old/seperator.go
@@ -0,0 +1,25 @@
+package gui
+
+import "log"
+import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func HorizontalBreak(box *GuiBox) {
+ log.Println("VerticalSeparator added to box =", box.Name)
+ tmp := ui.NewHorizontalSeparator()
+ if (box == nil) {
+ return
+ }
+ if (box.UiBox == nil) {
+ return
+ }
+ box.UiBox.Append(tmp, false)
+}
+
+func VerticalBreak(box *GuiBox) {
+ log.Println("VerticalSeparator added to box =", box.Name)
+ tmp := ui.NewVerticalSeparator()
+ box.UiBox.Append(tmp, false)
+}
diff --git a/toolkit/andlabs-direct/old/structs.go b/toolkit/andlabs-direct/old/structs.go
new file mode 100644
index 0000000..4a16438
--- /dev/null
+++ b/toolkit/andlabs-direct/old/structs.go
@@ -0,0 +1,273 @@
+package gui
+
+import (
+ "image/color"
+
+ "github.com/andlabs/ui"
+// "golang.org/x/image/font"
+
+ // "github.com/davecgh/go-spew/spew"
+
+ // _ "github.com/andlabs/ui/winmanifest"
+)
+
+//
+// All GUI Data Structures and functions that are external
+// If you need cross platform support, these might only
+// be the safe way to interact with the GUI
+//
+var Data GuiData
+var Config GuiConfig
+
+type GuiConfig struct {
+ Title string
+ Width int
+ Height int
+ Exit func(*Node)
+
+ Debug bool
+ DebugNode bool
+ DebugTabs bool
+ DebugTable bool
+ DebugWindow bool
+ DebugToolkit bool
+
+ depth int
+ counter int // used to make unique ID's
+ prefix string
+}
+
+type GuiData struct {
+ // a fallback default function to handle mouse events
+ // if nothing else is defined to handle them
+ MouseClick func(*GuiButton)
+
+ // A map of all the entry boxes
+ // AllEntries []*GuiEntry
+ WindowMap map[string]*GuiWindow
+
+ // Store access to everything via binary tree's
+ NodeMap map[string]*Node
+ NodeArray []*Node
+ NodeSlice []*Node
+
+ // A map of all buttons everywhere on all
+ // windows, all tabs, across all goroutines
+ // This is "GLOBAL"
+ //
+ // This has to work this way because of how
+ // andlabs/ui & andlabs/libui work
+ AllButtons []*GuiButton
+// buttonMap map[*ui.Button]*GuiButton
+}
+
+/*
+type GuiTab struct {
+ Name string // field for human readable name
+ Number int // the andlabs/ui tab index
+ Window *GuiWindow // the parent Window
+}
+*/
+
+//
+// stores information on the 'window'
+//
+// This merges the concept of andlabs/ui *Window and *Tab
+//
+// More than one Window is not supported in a cross platform
+// sense & may never be. On Windows and MacOS, you have to have
+// 'tabs'. Even under Linux, more than one Window is currently
+// unstable
+//
+// This code will make a 'GuiWindow' regardless of if it is
+// a stand alone window (which is more or less working on Linux)
+// or a 'tab' inside a window (which is all that works on MacOS
+// and MSWindows.
+//
+// This struct keeps track of what is in the window so you
+// can destroy and replace it with something else
+//
+type GuiWindow struct {
+ Name string // field for human readable name
+ Width int
+ Height int
+ Axis int // does it add items to the X or Y axis
+ TabNumber *int // the andlabs/ui tab index
+
+ // the callback function to make the window contents
+ // MakeWindow func(*GuiBox) *GuiBox
+
+ // the components of the window
+ BoxMap map[string]*GuiBox
+ // EntryMap map[string]*GuiEntry
+
+ node *Node
+
+ // andlabs/ui abstraction mapping
+ UiWindow *ui.Window
+ UiTab *ui.Tab // if this != nil, the window is 'tabbed'
+}
+
+/*
+func (w *GuiWindow) Dump() {
+ log.Println("gui.GuiWindow.Dump() Name = ", w.Name)
+ log.Println("gui.GuiWindow.Dump() node = ", w.node)
+ log.Println("gui.GuiWindow.Dump() Width = ", w.Width)
+ log.Println("gui.GuiWindow.Dump() Height = ", w.Height)
+}
+*/
+
+// GuiBox is any type of ui.Hbox or ui.Vbox
+// There can be lots of these for each GuiWindow
+type GuiBox struct {
+ Name string // field for human readable name
+ Axis int // does it add items to the X or Y axis
+ Window *GuiWindow // the parent Window
+
+ node *Node
+
+ // andlabs/ui abstraction mapping
+ UiBox *ui.Box
+}
+
+func (b *GuiBox) Append(child ui.Control, x bool) {
+ if b.UiBox == nil {
+ // spew.Dump(b)
+ // b.Dump()
+ panic("GuiBox.Append() can't work. UiBox == nil")
+ return
+ }
+ b.UiBox.Append(child, x)
+}
+
+// Note: every mouse click is handled
+// as a 'Button' regardless of where
+// the user clicks it. You could probably
+// call this 'GuiMouseClick'
+type GuiButton struct {
+ Name string // field for human readable name
+ Box *GuiBox // what box the button click was in
+
+ // a callback function for the main application
+ Custom func(*GuiButton)
+ Values interface{}
+ Color color.RGBA
+
+ // andlabs/ui abstraction mapping
+ B *ui.Button
+ FB *ui.FontButton
+ CB *ui.ColorButton
+}
+
+/*
+//
+// AREA STRUCTURES START
+// AREA STRUCTURES START
+// AREA STRUCTURES START
+//
+type GuiArea struct {
+ Button *GuiButton // what button handles mouse events
+ Box *GuiBox
+
+ UiAttrstr *ui.AttributedString
+ UiArea *ui.Area
+}
+
+type FontString struct {
+ S string
+ Size int
+ F font.Face
+ W font.Weight
+}
+
+//
+// AREA STRUCTURES END
+// AREA STRUCTURES END
+// AREA STRUCTURES END
+//
+
+//
+// TABLE DATA STRUCTURES START
+// TABLE DATA STRUCTURES START
+// TABLE DATA STRUCTURES START
+//
+
+//
+// This is the structure that andlabs/ui uses to pass information
+// to the GUI. This is the "authoritative" data.
+//
+type TableData struct {
+ RowCount int // This is the number of 'rows' which really means data elements not what the human sees
+ RowWidth int // This is how wide each row is
+ Rows []RowData // This is all the table data by row
+ generatedColumnTypes []ui.TableValue // generate this dynamically
+
+ Cells [20]CellData
+ Human [20]HumanMap
+
+ Box *GuiBox
+
+ lastRow int
+ lastColumn int
+}
+
+//
+// This maps the andlabs/ui & libui components into a "human"
+// readable cell reference list. The reason is that there
+// are potentially 3 values for each cell. The Text, the Color
+// and an image. These are not always needed so the number
+// of fields varies between 1 and 3. Internally, the toolkit
+// GUI abstraction needs to list all of them, but it's then
+// hard to figure out which column goes with the columns that
+// you see when you visually are looking at it like a spreadsheet
+//
+// This makes a map so that we can say "give me the value at
+// row 4 and column 2" and find the fields that are needed
+//
+// TODO: re-add images and the progress bar (works in andlabs/ui)
+//
+type HumanCellData struct {
+ Name string // what kind of row is this?
+ Text string
+ TextID int
+ Color color.RGBA
+ ColorID int
+ Button *GuiButton
+}
+
+type HumanMap struct {
+ Name string // what kind of row is this?
+ TextID int
+ ColorID int
+}
+
+type TableColumnData struct {
+ Index int
+ CellType string
+ Heading string
+ Color string
+}
+
+type CellData struct {
+ Index int
+ HumanID int
+ Name string // what type of cell is this?
+}
+
+// hmm. will this stand the test of time?
+type RowData struct {
+ Name string // what kind of row is this?
+ Status string // status of the row?
+ //
+ // TODO: These may or may not be implementable
+ // depending on if it's possible to detect the bgcolor or what row is selected
+ // click func() // what function to call if the user clicks on it
+ // doubleclick func() // what function to call if the user double clicks on it
+ //
+ HumanData [20]HumanCellData
+}
+*/
+
+//
+// TABLE DATA STRUCTURES END
+//
diff --git a/toolkit/andlabs-direct/old/table.go b/toolkit/andlabs-direct/old/table.go
new file mode 100644
index 0000000..92ae871
--- /dev/null
+++ b/toolkit/andlabs-direct/old/table.go
@@ -0,0 +1,150 @@
+// based off andlabs/ui/examples/table.go
+
+package gui
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+// import "github.com/davecgh/go-spew/spew"
+
+func initRowBTcolor(mh *TableData, intBG int, cell TableColumnData) {
+ humanInt := cell.Index
+
+ // setup mapping from human readable indexes to internal libUI indexes
+ mh.Human[humanInt].Name = "BG"
+ mh.Human[humanInt].ColorID = intBG
+ mh.Human[humanInt].TextID = -1
+
+ mh.Cells[intBG].Name = "BG"
+ mh.Cells[intBG].HumanID = humanInt
+
+ log.Println("intBG, humanInt", intBG, humanInt)
+}
+
+func initRowButtonColumn(mh *TableData, buttonID int, junk string, cell TableColumnData) {
+ humanInt := cell.Index
+
+ // setup mapping from human readable indexes to internal libUI indexes
+ mh.Human[humanInt].Name = "BUTTON"
+ mh.Human[humanInt].ColorID = -1
+ mh.Human[humanInt].TextID = buttonID
+
+ mh.Cells[buttonID].Name = "BUTTON"
+ mh.Cells[buttonID].HumanID = humanInt
+
+ log.Println("buttonID, humanInt", buttonID, humanInt)
+}
+
+func initRowTextColorColumn(mh *TableData, stringID int, colorID int, junk string, color ui.TableColor, cell TableColumnData) {
+ humanInt := cell.Index
+
+ // setup mapping from human readable indexes to internal libUI indexes
+ mh.Human[humanInt].Name = "EDIT"
+ mh.Human[humanInt].ColorID = colorID
+ mh.Human[humanInt].TextID = stringID
+
+ // text for Column humanInt
+ mh.Cells[stringID].Name = "EDIT"
+ mh.Cells[stringID].HumanID = humanInt
+
+ mh.Cells[colorID].Name = "COLOR"
+ mh.Cells[colorID].HumanID = humanInt
+}
+
+func initRowTextColumn(mh *TableData, stringID int, junk string, cell TableColumnData) {
+ humanInt := cell.Index
+
+ // setup mapping from human readable indexes to internal libUI indexes
+ mh.Human[humanInt].Name = "EDIT"
+ mh.Human[humanInt].ColorID = -1
+ mh.Human[humanInt].TextID = stringID
+
+ mh.Cells[stringID].Name = "EDIT"
+ mh.Cells[stringID].HumanID = humanInt
+}
+
+func InitColumns(mh *TableData, parts []TableColumnData) {
+ tmpBTindex := 0
+ humanID := 0
+ for key, foo := range parts {
+ log.Println("key, foo =", key, foo)
+
+ parts[key].Index = humanID
+ humanID += 1
+
+ if (foo.CellType == "BG") {
+ mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableColor{})
+ initRowBTcolor (mh, tmpBTindex, parts[key])
+ tmpBTindex += 1
+ } else if (foo.CellType == "BUTTON") {
+ mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableString(""))
+ initRowButtonColumn (mh, tmpBTindex, parts[key].Heading, parts[key])
+ tmpBTindex += 1
+ } else if (foo.CellType == "TEXTCOLOR") {
+ mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableString(""))
+ mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableColor{})
+ initRowTextColorColumn(mh, tmpBTindex, tmpBTindex + 1, parts[key].Heading, ui.TableColor{0.0, 0, 0.9, 1}, parts[key])
+ tmpBTindex += 2
+ } else if (foo.CellType == "TEXT") {
+ mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableString(""))
+ initRowTextColumn (mh, tmpBTindex, parts[key].Heading, parts[key])
+ tmpBTindex += 1
+ } else {
+ panic("I don't know what this is in initColumnNames")
+ }
+ }
+}
+
+func AddTableTab(gw *GuiWindow, name string, rowcount int, parts []TableColumnData) *TableData {
+ node := NewWindow()
+ b := node.box
+ return b.AddTableBox(name, rowcount, parts)
+}
+
+func (b *GuiBox) AddTableBox(name string, rowcount int, parts []TableColumnData) *TableData {
+ mh := new(TableData)
+
+ mh.RowCount = rowcount
+ mh.Rows = make([]RowData, mh.RowCount)
+
+ InitColumns(mh, parts)
+
+ model := ui.NewTableModel(mh)
+ table := ui.NewTable(
+ &ui.TableParams{
+ Model: model,
+ RowBackgroundColorModelColumn: 0, // Row Background color is always index zero
+ })
+
+ tmpBTindex := 0
+ for key, foo := range parts {
+ log.Println(key, foo)
+ if (foo.CellType == "BG") {
+ } else if (foo.CellType == "BUTTON") {
+ tmpBTindex += 1
+ table.AppendButtonColumn(foo.Heading, tmpBTindex, ui.TableModelColumnAlwaysEditable)
+ } else if (foo.CellType == "TEXTCOLOR") {
+ tmpBTindex += 1
+ table.AppendTextColumn(foo.Heading, tmpBTindex, ui.TableModelColumnAlwaysEditable,
+ &ui.TableTextColumnOptionalParams{
+ ColorModelColumn: tmpBTindex + 1,
+ });
+ tmpBTindex += 1
+ } else if (foo.CellType == "TEXT") {
+ tmpBTindex += 1
+ table.AppendTextColumn(foo.Heading, tmpBTindex, ui.TableModelColumnAlwaysEditable, nil)
+ } else {
+ panic("I don't know what this is in initColumnNames")
+ }
+ }
+
+ // is this needed?
+ // gw.BoxMap[name] = box
+ mh.Box = b
+
+ b.UiBox.Append(table, true)
+
+ return mh
+}
diff --git a/toolkit/andlabs-direct/old/tableCallbacks.go b/toolkit/andlabs-direct/old/tableCallbacks.go
new file mode 100644
index 0000000..6eefd8d
--- /dev/null
+++ b/toolkit/andlabs-direct/old/tableCallbacks.go
@@ -0,0 +1,108 @@
+package gui
+
+//
+// These functions are the hooks to the andlabs libui
+// They eventually feed information to the OS native GUI toolkits
+// and feed back user interaction with the GUI
+//
+
+import "log"
+// import "fmt"
+import "image/color"
+import "runtime"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (mh *TableData) NumRows(m *ui.TableModel) int {
+ if (Config.Debug) {
+ log.Println("NumRows = mh.RowCount = ", mh.RowCount, "(last Row & Column =", mh.lastRow, mh.lastColumn, ")")
+ }
+ return mh.RowCount
+}
+
+// FYI: this routine seems to be called around 10 to 100 times a second for each table
+func (mh *TableData) ColumnTypes(m *ui.TableModel) []ui.TableValue {
+ if (Config.DebugTable) {
+ log.Println("ColumnTypes = ", mh.generatedColumnTypes)
+ }
+ return mh.generatedColumnTypes
+}
+
+// TODO: Figure out why this is being called 1000 times a second (10 times for each row & column)
+//
+// Nevermind that TODO. Who gives a shit. This is a really smart way to treat the OS toolkits
+func (mh *TableData) CellValue(m *ui.TableModel, row, column int) ui.TableValue {
+ if (Config.DebugTable) {
+ log.Println("CellValue() row, column =", row, column)
+ }
+ mh.lastRow = row
+ mh.lastColumn = column
+ humanID := mh.Cells[column].HumanID
+ if (column == mh.Human[humanID].TextID) {
+ return ui.TableString(mh.Rows[row].HumanData[humanID].Text)
+ }
+ if (column == mh.Human[humanID].ColorID) {
+ if (column == 0) {
+ // ignore BG color on windows for now
+ if (runtime.GOOS == "windows") {
+ // TODO: fix colors on windows
+ // log.Println("CellValue() WINDOWS is BG COLOR row, column =", row, column)
+ // return nil
+ }
+
+ if (mh.Rows[row].HumanData[humanID].Color == color.RGBA{255, 255, 255, 255}) {
+ log.Println("CellValue() color.RGBA{255, 255, 255, 255} so return nil. row, column =", row, column)
+ return nil
+ }
+
+ bgcolor := libuiColorToGOlangColor(mh.Rows[row].HumanData[humanID].Color)
+ if (Config.Debug) {
+ log.Println("CellValue() BGCOLOR =", bgcolor)
+ }
+ return bgcolor
+ }
+ return libuiColorToGOlangColor(mh.Rows[row].HumanData[humanID].Color)
+ }
+ log.Println("CellValue() FAILURE")
+ log.Println("CellValue() FAILURE")
+ log.Println("CellValue() row, column = ", row, column)
+ log.Println("CellValue() FAILURE")
+ log.Println("CellValue() FAILURE")
+ log.Println("CellValue() mh.Cells", mh.Cells)
+ log.Println("CellValue() mh.Human", mh.Human)
+ panic("CellValue() not sure what sort of ui.TableValue to return in CellValue()")
+ return ui.TableString("")
+}
+
+func (mh *TableData) SetCellValue(m *ui.TableModel, row, column int, value ui.TableValue) {
+ log.Println("SetCellValue() START row=", row, "column=", column, "value=", value)
+
+ defaultSetCellValue(mh, row, column)
+
+ log.Println("mh.Cells[column].HumanID =", mh.Cells[column].HumanID)
+ // log.Println("mh.Rows[row].Cells[column].HumanID =", mh.Rows[row].Cells[column].HumanID)
+
+ humanID := mh.Cells[column].HumanID
+ log.Println("mh.Human[humanID].ColorID =", mh.Human[humanID].ColorID)
+ log.Println("mh.Human[humanID].TextID =", mh.Human[humanID].TextID)
+
+ log.Println("SetCellValue() END")
+}
+
+func defaultSetCellValue(mh *TableData, row int, column int) {
+ if (mh.Cells[column].Name == "BUTTON") {
+ humanID := mh.Cells[column].HumanID
+ log.Println("defaultSetCellValue() FOUND THE TABLE BUTTON ", row, humanID)
+
+ button := mh.Rows[row].HumanData[humanID].Button
+ if (button != nil) {
+ guiButtonClick(button)
+ return
+ }
+ log.Println("defaultSetCellValue() ERROR: UNKNOWN BUTTON IN TABLE")
+ if (Config.Debug) {
+ panic("defaultSetCellValue() GOT AN UNKNOWN BUTTON CLICK IN TABLE")
+ }
+ }
+}
diff --git a/toolkit/andlabs-direct/slider.go b/toolkit/andlabs-direct/slider.go
new file mode 100644
index 0000000..ad801f8
--- /dev/null
+++ b/toolkit/andlabs-direct/slider.go
@@ -0,0 +1,31 @@
+package toolkit
+
+import "log"
+import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t Toolkit) NewSlider(title string, x int, y int) *Toolkit {
+ // make new node here
+ log.Println("gui.Toolkit.NewSpinbox()", x, y)
+ var newt Toolkit
+
+ if (t.uiBox == nil) {
+ log.Println("gui.ToolkitNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
+ log.Println("probably could just make a box here?")
+ os.Exit(0)
+ return nil
+ }
+
+ s := ui.NewSlider(x, y)
+ newt.uiSlider = s
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(s, stretchy)
+
+ s.OnChanged(func(spin *ui.Slider) {
+ newt.commonChange("Slider")
+ })
+
+ return &newt
+}
diff --git a/toolkit/andlabs-direct/spinner.go b/toolkit/andlabs-direct/spinner.go
new file mode 100644
index 0000000..885192c
--- /dev/null
+++ b/toolkit/andlabs-direct/spinner.go
@@ -0,0 +1,30 @@
+package toolkit
+
+import "log"
+import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t Toolkit) NewSpinner(title string, x int, y int) *Toolkit {
+ // make new node here
+ log.Println("gui.Toolkit.NewSpinner()", x, y)
+ var newt Toolkit
+
+ if (t.uiBox == nil) {
+ log.Println("gui.ToolkitNode.NewSpinner() node.UiBox == nil. I can't add a range UI element without a place to put it")
+ os.Exit(0)
+ return nil
+ }
+
+ s := ui.NewSpinbox(x, y)
+ newt.uiSpinbox = s
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(s, stretchy)
+
+ s.OnChanged(func(s *ui.Spinbox) {
+ newt.commonChange("Spinner")
+ })
+
+ return &newt
+}
diff --git a/toolkit/andlabs-direct/structs.go b/toolkit/andlabs-direct/structs.go
new file mode 100644
index 0000000..9bba671
--- /dev/null
+++ b/toolkit/andlabs-direct/structs.go
@@ -0,0 +1,249 @@
+package toolkit
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "github.com/davecgh/go-spew/spew"
+
+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
+
+func setDefaultBehavior(s bool) {
+ defaultBehavior = s
+ if (defaultBehavior) {
+ if (DebugToolkit) {
+ log.Println("Setting this toolkit to use the default behavior.")
+ log.Println("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
+
+ DebugToolkit = false
+ } else {
+ log.Println("This toolkit is set to ignore the default behavior.")
+ }
+}
+
+func SetDebugToolkit (s bool) {
+ DebugToolkit = s
+}
+
+func GetDebugToolkit () bool {
+ return DebugToolkit
+}
+
+// stores the raw toolkit internals
+type Toolkit struct {
+ id string
+
+ Name string
+ Width int
+ Height int
+
+ OnChanged func(*Toolkit)
+ OnExit func(*Toolkit)
+
+ Custom func()
+
+ uiBox *ui.Box
+ uiBox2 *ui.Box // temporary hack while implementing tabs
+ uiButton *ui.Button
+ uiControl *ui.Control
+ uiCombobox *ui.Combobox
+ uiCheckbox *ui.Checkbox
+ uiEntry *ui.Entry
+ uiMultilineEntry *ui.MultilineEntry
+ uiGroup *ui.Group
+ uiLabel *ui.Label
+ uiSlider *ui.Slider
+ uiSpinbox *ui.Spinbox
+ uiTab *ui.Tab
+ uiText *ui.EditableCombobox
+ uiWindow *ui.Window
+ UiWindowBad *ui.Window
+
+ // 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
+ text string
+}
+
+func (t *Toolkit) String() string {
+ return t.GetText()
+}
+
+func forceDump(t *Toolkit) {
+ tmp := DebugToolkit
+ DebugToolkit = true
+ t.Dump()
+ DebugToolkit = tmp
+}
+
+func (t *Toolkit) GetText() string {
+ t.Dump()
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Text() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t.uiEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiEntry.Text())
+ }
+ return t.uiEntry.Text()
+ }
+ if (t.uiMultilineEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiMultilineEntry.Text())
+ }
+ text := t.uiMultilineEntry.Text()
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() text =", text)
+ }
+ t.text = text
+ return text
+ }
+ if (t.uiCombobox != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.GetText() =", t.text)
+ }
+ return t.text
+ }
+ return ""
+}
+
+func (t *Toolkit) SetText(s string) bool {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Text() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t.uiEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiEntry.Text)
+ }
+ t.uiEntry.SetText(s)
+ return true
+ }
+ if (t.uiMultilineEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiMultilineEntry.Text)
+ }
+ t.uiMultilineEntry.SetText(s)
+ return true
+ }
+ return false
+}
+
+func sanity(t *Toolkit) bool {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t.uiEntry == nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiEntry.Text)
+ }
+ return false
+ }
+ return true
+}
+
+func (t *Toolkit) SetValue(i int) bool {
+ log.Println("gui.Toolkit.SetValue() START")
+ if (sanity(t)) {
+ return false
+ }
+ t.Dump()
+ // panic("got to toolkit.SetValue")
+ return true
+}
+
+func (t *Toolkit) Value() int {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t == nil) {
+ log.Println("gui.Toolkit.Value() can not get value t == nil")
+ return 0
+ }
+ if (t.uiSlider != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiSlider.Value)
+ }
+ return t.uiSlider.Value()
+ }
+ if (t.uiSpinbox != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiSpinbox.Value)
+ }
+ return t.uiSpinbox.Value()
+ }
+ log.Println("gui.Toolkit.Value() Could not find a ui element to get a value from")
+ return 0
+}
+
+func (t *Toolkit) Dump() {
+ if ! DebugToolkit {
+ return
+ }
+ log.Println("gui.Toolkit.Dump() Name = ", t.Name, t.Width, t.Height)
+ if (t.uiBox != nil) {
+ log.Println("gui.Toolkit.Dump() uiBox =", t.uiBox)
+ }
+ if (t.uiButton != nil) {
+ log.Println("gui.Toolkit.Dump() uiButton =", t.uiButton)
+ }
+ if (t.uiCombobox != nil) {
+ log.Println("gui.Toolkit.Dump() uiCombobox =", t.uiCombobox)
+ }
+ if (t.uiWindow != nil) {
+ log.Println("gui.Toolkit.Dump() uiWindow =", t.uiWindow)
+ }
+ if (t.uiTab != nil) {
+ log.Println("gui.Toolkit.Dump() uiTab =", t.uiTab)
+ }
+ if (t.uiGroup != nil) {
+ log.Println("gui.Toolkit.Dump() uiGroup =", t.uiGroup)
+ }
+ if (t.uiEntry != nil) {
+ log.Println("gui.Toolkit.Dump() uiEntry =", t.uiEntry)
+ }
+ if (t.uiMultilineEntry != nil) {
+ log.Println("gui.Toolkit.Dump() uiMultilineEntry =", t.uiMultilineEntry)
+ }
+ if (t.uiSlider != nil) {
+ log.Println("gui.Toolkit.Dump() uiSlider =", t.uiSlider)
+ }
+ if (t.uiCheckbox != nil) {
+ log.Println("gui.Toolkit.Dump() uiCheckbox =", t.uiCheckbox)
+ }
+ if (t.OnExit != nil) {
+ log.Println("gui.Toolkit.Dump() OnExit =", t.OnExit)
+ }
+ if (t.Custom != nil) {
+ log.Println("gui.Toolkit.Dump() Custom =", t.Custom)
+ }
+ log.Println("gui.Toolkit.Dump() c =", t.c)
+ log.Println("gui.Toolkit.Dump() val =", t.val)
+ log.Println("gui.Toolkit.Dump() text =", t.text)
+}
diff --git a/toolkit/andlabs-direct/tab.go b/toolkit/andlabs-direct/tab.go
new file mode 100644
index 0000000..c641fc0
--- /dev/null
+++ b/toolkit/andlabs-direct/tab.go
@@ -0,0 +1,133 @@
+package toolkit
+
+import (
+ "log"
+ "time"
+
+ "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 (t *Toolkit) AddTab(name string) *Toolkit {
+ // var w *ui.Window
+ var newt *Toolkit
+
+ log.Println("gui.toolkit.AddTab() sleep 3")
+
+ if (t.uiWindow == nil) {
+ log.Println("gui.Toolkit.UiWindow == nil. I can't add a toolbar without window")
+ return nil
+ }
+
+ if (t.uiTab == nil) {
+ // this means you have to make a new tab
+ log.Println("gui.toolkit.NewTab() GOOD. This should be the first tab:", name)
+ newt = newTab(t.uiWindow, name)
+ t.uiTab = newt.uiTab
+ } else {
+ // this means you have to append a tab
+ log.Println("gui.toolkit.NewTab() GOOD. This should be an additional tab:", name)
+ newt = t.appendTab(name)
+ }
+
+ newt.Name = name
+
+ if (DebugToolkit) {
+ log.Println("t:")
+ t.Dump()
+ log.Println("newt:")
+ newt.Dump()
+ }
+
+ return newt
+}
+
+// This sets _all_ the tabs to Margin = true
+//
+// TODO: do proper tab tracking (will be complicated). low priority
+func tabSetMargined(tab *ui.Tab) {
+ c := tab.NumPages()
+ for i := 0; i < c; i++ {
+ if (DebugToolkit) {
+ log.Println("SetMargined", i, margin)
+ }
+ tab.SetMargined(i, margin)
+ }
+}
+
+func newTab(w *ui.Window, name string) *Toolkit {
+ var t Toolkit
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.NewTab() ADD", name)
+ }
+
+ if (w == nil) {
+ log.Println("gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window")
+ log.Println("gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window")
+ log.Println("gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window")
+ time.Sleep(1 * time.Second)
+ return nil
+ }
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.AddTab() START name =", name)
+ }
+ tab := ui.NewTab()
+ w.SetMargined(margin)
+
+ hbox := ui.NewHorizontalBox() // this makes everything go along the horizon
+ hbox.SetPadded(padded)
+ tab.Append(name, hbox)
+ tabSetMargined(tab) // TODO: run this in the right place(?)
+ w.SetChild(tab)
+
+ t.uiWindow = w
+ t.uiTab = tab
+ t.uiBox = hbox
+ return &t
+}
+
+func (t *Toolkit) appendTab(name string) *Toolkit {
+ var newT Toolkit
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.NewTab() ADD", name)
+ }
+
+ if (t.uiTab == nil) {
+ log.Println("gui.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")
+ }
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.AddTab() 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/toolkit/andlabs-direct/textbox.go b/toolkit/andlabs-direct/textbox.go
new file mode 100644
index 0000000..44946b8
--- /dev/null
+++ b/toolkit/andlabs-direct/textbox.go
@@ -0,0 +1,34 @@
+package toolkit
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t Toolkit) NewTextbox(name string) *Toolkit {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.NewTextbox()", name)
+ }
+ var newt Toolkit
+
+ if t.broken() {
+ return nil
+ }
+
+ c := ui.NewNonWrappingMultilineEntry()
+ newt.uiMultilineEntry = c
+
+ newt.uiBox = t.uiBox
+ newt.Name = name
+ if (defaultBehavior) {
+ t.uiBox.Append(c, true)
+ } else {
+ t.uiBox.Append(c, stretchy)
+ }
+
+ c.OnChanged(func(spin *ui.MultilineEntry) {
+ newt.commonChange("Textbox")
+ })
+
+ return &newt
+}
diff --git a/toolkit/andlabs-direct/window.go b/toolkit/andlabs-direct/window.go
new file mode 100644
index 0000000..efbd672
--- /dev/null
+++ b/toolkit/andlabs-direct/window.go
@@ -0,0 +1,66 @@
+package toolkit
+
+import (
+ "log"
+
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (t *Toolkit) MessageWindow(msg1 string, msg2 string) {
+ ui.MsgBox(t.uiWindow, msg1, msg2)
+}
+
+func (t *Toolkit) ErrorWindow(msg1 string, msg2 string) {
+ ui.MsgBoxError(t.uiWindow, msg1, msg2)
+}
+
+func NewWindow(title string, x int, y int) *Toolkit {
+ var t Toolkit
+ if (DebugToolkit) {
+ log.Println("toolkit NewWindow", title, x, y)
+ }
+ w := ui.NewWindow(title, x, y, menubar)
+ w.SetBorderless(canvas)
+ w.SetMargined(margin)
+ w.OnClosing(func(*ui.Window) bool {
+ if (DebugToolkit) {
+ log.Println("ui.Window().OnExit() SHOULD ATTEMPT CALLBACK here")
+ t.Dump()
+ }
+ if (t.OnExit != nil) {
+ if (DebugToolkit) {
+ log.Println("ui.Window().OnExit() ATTEMPTING toolkit.OnExit CALLBACK")
+ }
+ t.OnExit(&t)
+ }
+ if (t.Custom != nil) {
+ if (DebugToolkit) {
+ log.Println("ui.Window().Custom() ATTEMPTING toolkit.Custom CALLBACK")
+ }
+ t.Custom()
+ }
+ if (DebugToolkit) {
+ log.Println("ui.Window().OnExit() Toolkit.OnExit is nil")
+ }
+ return true
+ })
+ w.Show()
+ t.uiWindow = w
+ t.UiWindowBad = w // deprecate this as soon as possible
+ return &t
+}
+
+func (t *Toolkit) SetWindowTitle(title string) {
+ if (DebugToolkit) {
+ log.Println("toolkit NewWindow", t.Name, "title", title)
+ }
+ win := t.uiWindow
+ if (win != nil) {
+ win.SetTitle(title)
+ } else {
+ if (DebugToolkit) {
+ log.Println("Setting the window title", title)
+ }
+ }
+}