diff options
Diffstat (limited to 'toolkit/andlabs-direct')
| -rw-r--r-- | toolkit/andlabs-direct/box.go | 66 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/button.go | 79 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/checkbox.go | 34 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/common.go | 61 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/demo.go | 92 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/dropdown.go | 55 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/group.go | 42 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/label.go | 21 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/main.go | 31 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/old/area.go | 136 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/old/color.go | 31 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/old/seperator.go | 25 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/old/structs.go | 273 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/old/table.go | 150 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/old/tableCallbacks.go | 108 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/slider.go | 31 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/spinner.go | 30 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/structs.go | 249 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/tab.go | 133 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/textbox.go | 34 | ||||
| -rw-r--r-- | toolkit/andlabs-direct/window.go | 66 |
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) + } + } +} |
