Try renaming 'Node' to 'Box'

This commit is contained in:
Jeff Carr 2022-10-08 23:51:48 -05:00
parent 917527d4dc
commit f68428d13b
18 changed files with 1083 additions and 331 deletions

58
area.go
View File

@ -7,14 +7,28 @@ import _ "github.com/andlabs/ui/winmanifest"
import "github.com/davecgh/go-spew/spew"
// make this button just to get the default font (but don't display the button)
// There should be another way to do this (?)
func (n *Node) makeGenericArea(newText *ui.AttributedString, custom func(*Node)) {
newNode := n.CreateFontButton("AREA")
newNode.custom = custom
area := new(GuiArea)
newNode.uiArea = ui.NewArea(area)
newNode.uiAttrstr = newText
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) {
@ -38,7 +52,7 @@ func appendWithAttributes(newText *ui.AttributedString, what string, attrs ...ui
func (ah GuiArea) Draw(a *ui.Area, p *ui.AreaDrawParams) {
tl := ui.DrawNewTextLayout(&ui.DrawTextLayoutParams{
String: ah.UiAttrstr,
DefaultFont: ah.N.uiFontButton.Font(),
DefaultFont: ah.Button.FB.Font(),
Width: p.AreaWidth,
Align: ui.DrawTextAlign(1),
})
@ -47,7 +61,6 @@ func (ah GuiArea) Draw(a *ui.Area, p *ui.AreaDrawParams) {
}
func (ah GuiArea) MouseEvent(a *ui.Area, me *ui.AreaMouseEvent) {
/*
if (Config.Debug) {
log.Println("GOT MouseEvent() ah.Button =", ah.Button)
spew.Dump(me)
@ -67,7 +80,6 @@ func (ah GuiArea) MouseEvent(a *ui.Area, me *ui.AreaMouseEvent) {
Data.MouseClick(ah.Button)
}
}
*/
}
func (ah GuiArea) MouseCrossed(a *ui.Area, left bool) {
@ -95,14 +107,30 @@ func (ah GuiArea) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) {
return false
}
func (n *Node) ShowTextBox(newText *ui.AttributedString, custom func(*Node), name string) {
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
n.uiBox.SetPadded(true)
b.UiBox.SetPadded(true)
// add(gw.BoxMap["MAINBOX"], newbox)
n.makeGenericArea(newText, custom)
n.uiBox.Append(n.area.UiArea, true)
makeGenericArea(b, newText, custom)
b.UiBox.Append(b.Window.Area.UiArea, true)
}

203
box.go
View File

@ -1,7 +1,7 @@
package gui
import "log"
// import "os"
import "os"
// import "reflect"
import "github.com/andlabs/ui"
@ -9,17 +9,190 @@ import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew"
// add(nil, newbox, "") // use this when the Window is created. Always called 'MAINBOX'
// add(gw.BoxMap["MAINBOX"], newbox, name) // use this to add a box off the main box
// add(gw.BoxMap["BUTTONBOX"], newbox, name) // use this to add something to the box called 'BUTTONBOX'
// add(box, newbox, name) // add 'newbox' to 'box' and call it 'name'
func add(box *GuiBox, newbox *GuiBox) {
log.Println("gui.add() START box =", box)
log.Println("gui.add() START newbox =", newbox)
if (box == nil) {
log.Println("\tgui.add() add to Window as MAINBOX")
if (newbox.Window.UiTab != nil) {
// create a new tab here
// add the box to it as MAINBOX
log.Println("\tgui.add() add to Window as a UiTab")
// TODO: allow passing where to append
// newbox.Window.UiTab.InsertAt(newbox.Name, 0, newbox.UiBox)
newbox.Window.UiTab.Append(newbox.Name, newbox.UiBox)
// newbox.Window.UiTab.SetMargined(0, true)
// TODO: figure out how to make a new Tab/Window/Box here
// window := InitGuiWindow(Data.Config, newbox.Name, gw.MakeWindow, gw.UiWindow, gw.UiTab)
// window.UiTab.Delete(0)
// window.MakeWindow(window)
// newbox.Window = window
newbox.Window.BoxMap["MAINBOX"] = newbox
log.Println("gui.add() END")
panic("gui.add() MAINBOX gui.add() END")
return
} else {
log.Println("\tgui.add() ERROR DONT KNOW HOW TO ADD TO A RAW WINDOW YET")
// add this to the window
}
log.Println("\tgui.add() ERROR DON'T KNOW HOW TO add to Window as MAINBOX DONE")
log.Println("gui.add() END")
panic("gui.add() gui.add() END")
return
}
log.Println("\tgui.add() adding", newbox.Name, "to", box.Name)
// copy the box settings over
newbox.Window = box.Window
if (box.node == nil) {
box.Dump()
panic("gui.add() ERROR box.node == nil")
}
if (newbox.UiBox == nil) {
panic("gui.add() ERROR newbox.UiBox == nil")
}
if (box.UiBox == nil) {
box.Dump()
// panic("gui.add() ERROR box.UiBox == nil")
return
// TODO: fix this whole add() function // Oct 9
}
box.UiBox.Append(newbox.UiBox, false)
box.Dump()
panic("gui.add()")
// add the newbox to the Window.BoxMap[]
box.Window.BoxMap[newbox.Name] = newbox
log.Println("gui.add() END")
}
func (n *Node) AddBox(axis int, name string) *Node {
newBox := new(GuiBox)
newBox.Window = n.window
newBox.Name = name
if (n.box == nil) {
n.box = newBox
}
// make a new box & a new node
newNode := n.makeNode(name, 111, 100 + Config.counter)
newNode.box = newBox
Config.counter += 1
var uiBox *ui.Box
if (axis == Xaxis) {
uiBox = ui.NewHorizontalBox()
} else {
uiBox = ui.NewVerticalBox()
}
uiBox.SetPadded(true)
newBox.UiBox = uiBox
newNode.uiBox = uiBox
n.Append(newNode)
// add(n.box, newBox)
return newNode
}
func (b *GuiBox) NewBox(axis int, name string) *GuiBox {
log.Println("gui.NewBox() START")
n := b.FindNode()
if (n == nil) {
log.Println("gui.NewBox() SERIOUS ERROR. CAN NOT FIND NODE")
os.Exit(0)
} else {
log.Println("gui.NewBox() node =", n.Name)
}
var newbox *GuiBox
newbox = new(GuiBox)
newbox.Window = b.Window
newbox.Name = name
var uiBox *ui.Box
if (axis == Xaxis) {
uiBox = ui.NewHorizontalBox()
} else {
uiBox = ui.NewVerticalBox()
}
uiBox.SetPadded(true)
newbox.UiBox = uiBox
add(b, newbox)
// panic("gui.NewBox")
return newbox
}
func HardBox(gw *GuiWindow, axis int, name string) *GuiBox {
log.Println("HardBox() START axis =", axis)
if (gw.node == nil) {
gw.Dump()
panic("gui.HardBox() gw.node == nil")
}
// add a Vertical Seperator if there is already a box
// Is this right?
box := gw.BoxMap["MAINBOX"]
if (box != nil) {
if (axis == Xaxis) {
VerticalBreak(box)
} else {
HorizontalBreak(box)
}
}
// make the new vbox
var uiBox *ui.Box
if (axis == Xaxis) {
uiBox = ui.NewHorizontalBox()
} else {
uiBox = ui.NewVerticalBox()
}
uiBox.SetPadded(true)
// Init a new GuiBox
newbox := new(GuiBox)
newbox.Window = gw
newbox.UiBox = uiBox
newbox.Name = name
add(gw.BoxMap["MAINBOX"], newbox)
log.Println("HardBox END")
return newbox
}
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)
}
func (n *Node) AddComboBox(title string, s ...string) *Node {
newNode := n.AddNode(title)
box := n.uiBox
if (box == nil) {
return n
}
ecbox := ui.NewEditableCombobox()
newNode.uiText = ecbox
// newNode.Dump()
// log.Println("ecbox", ecbox)
for id, name := range s {
log.Println("Adding Combobox Entry:", id, name)
@ -28,23 +201,21 @@ func (n *Node) AddComboBox(title string, s ...string) *Node {
ecbox.OnChanged(func(*ui.EditableCombobox) {
test := ecbox.Text()
log.Println("node.Name = '" + newNode.Name + "' text for '" + title + "' is now: '" + test + "'")
if (newNode.OnChanged == nil) {
log.Println("Not doing custom OnChanged since OnChanged == nil")
newNode.Dump()
} else {
newNode.OnChanged()
}
log.Println("node.Name = '" + n.Name + "' text for '" + title + "' is now: '" + test + "'")
})
box.Append(ecbox, Config.Stretchy)
box.Append(ecbox, false)
newNode := n.AddNode(title)
newNode.uiText = ecbox
return newNode
}
func (n *Node) OnChanged(f func()) {
f()
}
func (n *Node) GetText() string {
if (n.uiMultilineEntry != nil) {
return n.uiMultilineEntry.Text()
}
if (n.uiText == nil) {
return ""
}

159
button.go
View File

@ -2,14 +2,11 @@ package gui
import "log"
import "reflect"
// import "image/color"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew"
// TODO: bring this generic mouse click function back
//
// This is the default mouse click handler
// Every mouse click that hasn't been assigned to
// something specific will fall into this routine
@ -19,7 +16,41 @@ import _ "github.com/andlabs/ui/winmanifest"
// This routine MUST be here as this is how the andlabs/ui works
// This is the raw routine passed to every button in andlabs libui / ui
//
// There is a []GuiButton which has all the buttons. We search
// for the button and then call the function below
//
func defaultButtonClick(button *ui.Button) {
log.Println("gui.defaultButtonClick() LOOK FOR BUTTON button =", button)
for key, foo := range Data.AllButtons {
if (Config.Debug) {
log.Println("gui.defaultButtonClick() Data.AllButtons =", key, foo)
// spew.Dump(foo)
}
if Data.AllButtons[key].B == button {
log.Println("\tgui.defaultButtonClick() BUTTON MATCHED")
guiButtonClick(Data.AllButtons[key])
return
}
}
log.Println("\tgui.defaultButtonClick() ERROR: BUTTON NOT FOUND")
if (Config.Debug) {
panic("gui.defaultButtonClick() ERROR: UNMAPPED ui.Button")
}
}
func guiButtonClick(button *GuiButton) {
log.Println("\tgui.guiButtonClick() button.Name =", button.Name)
if button.Custom != nil {
log.Println("\tgui.guiButtonClick() DOING CUSTOM FUNCTION")
button.Custom(button)
return
}
if (Data.MouseClick != nil) {
Data.MouseClick(button)
} else {
log.Println("\tgui.guiButtonClick() IGNORING BUTTON. MouseClick() is nil")
}
}
func (n *Node) AddButton(name string, custom func(*Node)) *Node {
if (n.uiBox == nil) {
@ -27,12 +58,9 @@ func (n *Node) AddButton(name string, custom func(*Node)) *Node {
return n
}
button := ui.NewButton(name)
if (Config.Debug) {
log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox))
log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button))
}
// true == expand, false == make normal size button
n.uiBox.Append(button, Config.Stretchy)
log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox))
log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button))
n.uiBox.Append(button, false)
n.uiButton = button
newNode := n.makeNode(name, 888, 888 + Config.counter)
@ -43,40 +71,101 @@ func (n *Node) AddButton(name string, custom func(*Node)) *Node {
log.Println("gui.AppendButton() Button Clicked. Running custom()")
custom(newNode)
})
// panic("AppendButton")
// time.Sleep(3 * time.Second)
return newNode
}
func (n *Node) CreateFontButton(action string) *Node {
n.uiFontButton = ui.NewFontButton()
func (n *Node) CreateButton(custom func(*GuiButton), name string, values interface {}) *Node {
newNode := n.AddBox(Xaxis, "test CreateButton")
box := newNode.FindBox()
if (box == nil) {
panic("node.CreateButton().FindBox() == nil")
}
newUiB := ui.NewButton(name)
newUiB.OnClicked(defaultButtonClick)
n.uiFontButton.OnChanged(func (*ui.FontButton) {
log.Println("FontButton.OnChanged() START")
n.Dump()
})
n.uiBox.Append(n.uiFontButton, Config.Stretchy)
var newB *GuiButton
newB = new(GuiButton)
newB.B = newUiB
if (box.UiBox == nil) {
log.Println("CreateButton() box.Window == nil")
// ErrorWindow(box.Window, "Login Failed", msg) // can't even do this
panic("maybe print an error and return nil? or make a fake button?")
} else {
// uibox := box.UiBox
// uibox.Append(newUiB, true)
}
newB.Box = box
newB.Custom = custom
newB.Values = values
// TODO: implement Grid
n.uiGrid = ui.NewGrid()
return n
Data.AllButtons = append(Data.AllButtons, newB)
box.Append(newB.B, false)
return newNode
}
func (n *Node) CreateColorButton(custom func(*Node), name string, values interface {}) *Node {
// create a 'fake' button entry for the mouse clicks
n.uiColorButton = ui.NewColorButton()
n.custom = custom
n.values = values
func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton {
newUiB := ui.NewButton(name)
newUiB.OnClicked(defaultButtonClick)
n.uiColorButton.OnChanged(func (*ui.ColorButton) {
log.Println("ColorButton.OnChanged() START Color Button Click")
rgba := n.Color
r, g, b, a := rgba.R, rgba.G, rgba.B, rgba.A
log.Println("ColorButton.OnChanged() Color() =", r, g, b, a)
if (n.custom != nil) {
n.custom(n)
} else if (Data.MouseClick != nil) {
Data.MouseClick(n)
var newB *GuiButton
newB = new(GuiButton)
newB.B = newUiB
if (box.Window == nil) {
log.Println("CreateButton() box.Window == nil")
// ErrorWindow(box.Window, "Login Failed", msg) // can't even do this
panic("maybe print an error and return nil? or make a fake button?")
}
newB.Box = box
newB.Custom = custom
newB.Values = values
Data.AllButtons = append(Data.AllButtons, newB)
box.Append(newB.B, false)
return newB
}
func CreateFontButton(box *GuiBox, action string) *GuiButton {
// create a 'fake' button entry for the mouse clicks
var newGB GuiButton
newGB.Name = "FONT"
newGB.FB = ui.NewFontButton()
newGB.Box = box
Data.AllButtons = append(Data.AllButtons, &newGB)
newGB.FB.OnChanged(func (*ui.FontButton) {
log.Println("FontButton.OnChanged() START mouseClick(&newBM)", newGB)
if (Data.MouseClick != nil) {
Data.MouseClick(&newGB)
}
})
n.uiBox.Append(n.uiColorButton, Config.Stretchy)
return n
return &newGB
}
func CreateColorButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton {
// create a 'fake' button entry for the mouse clicks
var newCB GuiButton
newCB.Name = name
newCB.CB = ui.NewColorButton()
newCB.Box = box
newCB.Custom = custom
newCB.Values = values
Data.AllButtons = append(Data.AllButtons, &newCB)
newCB.CB.OnChanged(func (*ui.ColorButton) {
log.Println("ColorButton.OnChanged() START Color Button Click")
r, g, b, a := newCB.CB.Color()
log.Println("ColorButton.OnChanged() Color() =", r, g, b, a)
if (newCB.Custom != nil) {
newCB.Custom(&newCB)
} else if (Data.MouseClick != nil) {
Data.MouseClick(&newCB)
}
})
box.Append(newCB.CB, false)
return &newCB
}

View File

@ -33,9 +33,9 @@ func addDemoTab(n *gui.Node, title string) {
groupNode1 := newNode.AddGroup("group 1")
cbNode := groupNode1.AddComboBox("username", "root", "jcarr", "hugo")
cbNode.OnChanged = func () {
cbNode.OnChanged(func () {
username = cbNode.GetText()
}
})
groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff")
groupNode1.Dump()

View File

@ -7,7 +7,7 @@ import (
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
// "github.com/davecgh/go-spew/spew"
"github.com/davecgh/go-spew/spew"
)
var names = make([]string, 100)
@ -33,6 +33,126 @@ func makeWindowDebug() *ui.Box {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
/////////////////////////////////////////////////////
vbox := addGroup(hbox, "range Data.WindowMap")
cbox := ui.NewCombobox()
for name, _ := range Data.WindowMap {
if (Config.Debug) {
log.Println("range Data.WindowMap() name =", name)
}
addName(cbox, name)
}
cbox.SetSelected(0)
vbox.Append(cbox, false)
cbox.OnSelected(func(*ui.Combobox) {
x := cbox.Selected()
log.Println("x =", x)
log.Println("names[x] =", names[x])
dumpBox(names[x])
})
/////////////////////////////////////////////////////
vbox = addGroup(hbox, "Debug Window")
b1 := addButton(vbox, "dumpBox(window)")
b1.OnClicked(func(*ui.Button) {
x := cbox.Selected()
log.Println("x =", x)
log.Println("names[x] =", names[x])
dumpBox(names[x])
})
b2 := addButton(vbox, "SetMargined(tab)")
b2.OnClicked(func(*ui.Button) {
x := cbox.Selected()
log.Println("x =", x)
log.Println("FindWindow; names[x] =", names[x])
gw := FindWindow(names[x])
if gw == nil {
return
}
if gw.UiTab == nil {
return
}
if gw.TabNumber == nil {
return
}
scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(gw)
log.Println("gui.DumpBoxes()\tWindow.UiTab =", gw.UiTab)
log.Println("gui.DumpBoxes()\tWindow.TabNumber =", *gw.TabNumber)
gw.UiTab.SetMargined(*gw.TabNumber, true)
})
b3 := addButton(vbox, "Hide(tab)")
b3.OnClicked(func(*ui.Button) {
x := cbox.Selected()
log.Println("x =", x)
log.Println("FindWindow; names[x] =", names[x])
gw := FindWindow(names[x])
if gw == nil {
return
}
if gw.UiTab == nil {
return
}
gw.UiTab.Hide()
})
b4 := addButton(vbox, "Show(tab)")
b4.OnClicked(func(*ui.Button) {
x := cbox.Selected()
log.Println("x =", x)
log.Println("FindWindow; names[x] =", names[x])
gw := FindWindow(names[x])
if gw == nil {
return
}
if gw.UiTab == nil {
return
}
gw.UiTab.Show()
})
b5 := addButton(vbox, "Delete(tab)")
b5.OnClicked(func(*ui.Button) {
x := cbox.Selected()
log.Println("x =", x)
log.Println("FindWindow; names[x] =", names[x])
gw := FindWindow(names[x])
if gw == nil {
return
}
if gw.UiTab == nil {
return
}
if gw.TabNumber == nil {
return
}
gw.UiTab.Delete(*gw.TabNumber)
})
/////////////////////////////////////////////////////
vbox = addGroup(hbox, "Global Debug")
dump3 := addButton(vbox, "Dump Windows")
dump3.OnClicked(func(*ui.Button) {
DumpWindows()
})
dump2 := addButton(vbox, "Dump Boxes")
dump2.OnClicked(func(*ui.Button) {
DumpBoxes()
})
dump1 := addButton(vbox, "Dump MAP")
dump1.OnClicked(func(*ui.Button) {
DumpMap()
})
/////////////////////////////////////////////////////
nodeBox := addGroup(hbox, "Windows:")
nodeCombo := ui.NewCombobox()
@ -46,7 +166,7 @@ func makeWindowDebug() *ui.Box {
}
nodeCombo.SetSelected(0)
nodeBox.Append(nodeCombo, Config.Stretchy)
nodeBox.Append(nodeCombo, false)
nodeCombo.OnSelected(func(*ui.Combobox) {
y := nodeCombo.Selected()
@ -59,7 +179,7 @@ func makeWindowDebug() *ui.Box {
})
/////////////////////////////////////////////////////
vbox := addGroup(hbox, "Node Debug")
vbox = addGroup(hbox, "Node Debug")
n1 := addButton(vbox, "Data.DumpNodeMap()")
n1.OnClicked(func(*ui.Button) {
@ -148,7 +268,7 @@ func addName(c *ui.Combobox, s string) {
func addGroup(b *ui.Box, name string) *ui.Box {
group := ui.NewGroup(name)
group.SetMargined(true)
b.Append(group, Config.Stretchy)
b.Append(group, true)
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
@ -157,6 +277,48 @@ func addGroup(b *ui.Box, name string) *ui.Box {
return vbox
}
func dumpBox(s string) {
var name string
var window *GuiWindow
for name, window = range Data.WindowMap {
if name != s {
continue
}
log.Println("gui.DumpBoxes() MAP: ", name)
if window.TabNumber == nil {
log.Println("gui.DumpBoxes() \tWindows.TabNumber = nil")
} else {
log.Println("gui.DumpBoxes() \tWindows.TabNumber =", *window.TabNumber)
}
log.Println("gui.DumpBoxes()\tWindow.name =", window.Name)
// log.Println("gui.DumpBoxes()\tWindow.UiWindow type =", reflect.TypeOf(window.UiWindow))
log.Println("gui.DumpBoxes()\tWindow.UiWindow =", window.UiWindow)
log.Println("gui.DumpBoxes()\tWindow.UiTab =", window.UiTab)
log.Println("gui.dumpBox() BoxMap START")
for name, abox := range window.BoxMap {
log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
abox.Dump()
if name == "MAINBOX" {
if Config.Debug {
scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(abox.UiBox)
}
}
}
log.Println("gui.dumpBox() BoxMap END")
if window.UiTab != nil {
pages := window.UiTab.NumPages()
log.Println("gui.DumpBoxes()\tWindow.UiTab.NumPages() =", pages)
tabSetMargined(window.UiTab)
if Config.Debug {
scs := spew.ConfigState{MaxDepth: 2}
scs.Dump(window.UiTab)
}
}
}
}
func addButton(box *ui.Box, name string) *ui.Button {
button := ui.NewButton(name)
@ -164,7 +326,7 @@ func addButton(box *ui.Box, name string) *ui.Button {
log.Println("Should do something here")
})
box.Append(button, Config.Stretchy)
box.Append(button, false)
return button
}

View File

@ -5,7 +5,7 @@ import (
"log"
"time"
// "github.com/davecgh/go-spew/spew"
"github.com/davecgh/go-spew/spew"
)
// WatchGUI() opens a goroutine
@ -22,7 +22,7 @@ func WatchGUI() {
if count > 20 {
log.Println("Sleep() in watchGUI()")
if Config.Debug {
// DumpBoxes()
DumpBoxes()
}
count = 0
}
@ -31,6 +31,71 @@ func WatchGUI() {
}
}
func DumpWindows() {
for name, _ := range Data.WindowMap {
log.Println("gui.DumpWindows() window =", name)
}
}
func DumpMap() {
for name, window := range Data.WindowMap {
log.Println("gui.DumpBoxes() MAP: ", name)
log.Println("gui.DumpBoxes() BOXES:", name)
for name, abox := range window.BoxMap {
log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
}
}
}
func DumpBoxes() {
for name, window := range Data.WindowMap {
log.Println("gui.DumpBoxes() MAP: ", name)
if window.TabNumber == nil {
log.Println("gui.DumpBoxes() \tWindows.TabNumber = nil")
} else {
log.Println("gui.DumpBoxes() \tWindows.TabNumber =", *window.TabNumber)
}
log.Println("gui.DumpBoxes()\tWindow.name =", window.Name)
// log.Println("gui.DumpBoxes()\tWindow.UiWindow type =", reflect.TypeOf(window.UiWindow))
log.Println("gui.DumpBoxes()\tWindow.UiWindow =", window.UiWindow)
log.Println("gui.DumpBoxes()\tWindow.UiTab =", window.UiTab)
for name, abox := range window.BoxMap {
log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
if name == "MAINBOX" {
if Config.Debug {
scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(abox.UiBox)
}
}
}
if window.UiTab != nil {
// log.Println("gui.DumpBoxes()\tWindow.UiTab type =", reflect.TypeOf(window.UiTab))
// log.Println("gui.DumpBoxes()\tWindow.UiTab =", window.UiTab)
pages := window.UiTab.NumPages()
log.Println("gui.DumpBoxes()\tWindow.UiTab.NumPages() =", pages)
// for i := 0; i < pages; i++ {
// log.Println("gui.DumpBoxes()\t\tWindow.UiTab.Margined(", i, ") =", window.UiTab.Margined(i))
// }
// tmp := spew.NewDefaultConfig()
// tmp.MaxDepth = 2
// tmp.Dump(window.UiTab)
if Config.Debug {
scs := spew.ConfigState{MaxDepth: 2}
scs.Dump(window.UiTab)
}
}
}
/*
for i, window := range Data.Windows {
if (window.TabNumber == nil) {
log.Println("gui.DumpBoxes() Data.Windows", i, "Name =", window.Name, "TabNumber = nil")
} else {
log.Println("gui.DumpBoxes() Data.Windows", i, "Name =", window.Name, "TabNumber =", *window.TabNumber)
}
}
*/
}
func addTableTab() {
var parts []TableColumnData
@ -61,6 +126,24 @@ func (dn *GuiData) DumpNodeMap() {
}
}
/*
func DebugDataNodeChildren() {
if Data.NodeMap == nil {
log.Println("DebugDataNodeChildren() NodeMap == nil")
return
}
log.Println("DebugDataNodeChildren():")
for name, node := range Data.NodeMap {
log.Println("\tNode name =", node.Width, node.Height, name)
if (node.children == nil) {
log.Println("\t\tNo children")
break
}
log.Println("\t\tHas children:", node.children)
}
}
*/
func (dn *GuiData) ListChildren(dump bool) {
if Data.NodeMap == nil {
log.Println("gui.Data.ListChildren() Data.NodeMap == nil")
@ -68,9 +151,8 @@ func (dn *GuiData) ListChildren(dump bool) {
}
log.Println("gui.Data.ListChildren() Data.NodeMap:")
for name, node := range Data.NodeMap {
listChildrenDepth = 0
log.Println("\tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name)
if (dump == true) {
log.Println("tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name)
node.Dump()
}
node.ListChildren(dump)

View File

@ -1,6 +1,6 @@
package gui
import "log"
// import "log"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
@ -16,7 +16,7 @@ func (n *Node) AddGroup(title string) *Node {
}
group := ui.NewGroup(title)
group.SetMargined(true)
hbox.Append(group, Config.Stretchy)
hbox.Append(group, true)
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
@ -26,67 +26,3 @@ func (n *Node) AddGroup(title string) *Node {
newNode.uiBox = vbox
return newNode
}
func (n *Node) MakeBasicControlsPage(title string) *Node {
if (n == nil) {
return nil
}
origbox := n.uiBox
if (origbox == nil) {
return n
}
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
vbox.Append(hbox, false)
hbox.Append(ui.NewButton("Button"), false)
hbox.Append(ui.NewCheckbox("Checkbox"), false)
vbox.Append(ui.NewLabel("This is a label. Right now, labels can only span one line."), false)
vbox.Append(ui.NewHorizontalSeparator(), false)
group := ui.NewGroup("Entries")
group.SetMargined(true)
vbox.Append(group, true)
group.SetChild(ui.NewNonWrappingMultilineEntry())
entryForm := ui.NewForm()
entryForm.SetPadded(true)
group.SetChild(entryForm)
entryForm.Append("Entry", ui.NewEntry(), false)
entryForm.Append("Password Entry", ui.NewPasswordEntry(), false)
entryForm.Append("Search Entry", ui.NewSearchEntry(), false)
entryForm.Append("Multiline Entry", ui.NewMultilineEntry(), true)
entryForm.Append("Multiline Entry No Wrap", ui.NewNonWrappingMultilineEntry(), true)
origbox.Append(vbox, false)
newNode := n.AddNode(title)
newNode.uiBox = vbox
return newNode
}
func (n *Node) MakeGroupEdit(title string) *Node {
n.Dump()
group := ui.NewGroup(title)
group.SetMargined(true)
n.uiBox.Append(group, Config.Stretchy)
entrybox := ui.NewNonWrappingMultilineEntry()
group.SetChild(entrybox)
log.Println("entrybox =", entrybox)
n.uiMultilineEntry = entrybox
newNode := n.AddNode(title)
newNode.uiMultilineEntry = entrybox
newNode.uiGroup = group
return newNode
}

5
doc.go
View File

@ -64,6 +64,9 @@ GUI Usage
Errors
Not sure about errors yet. To early to document them. This is a work in progress.
Since it is possible for custom Stringer/error interfaces to panic, spew
detects them and handles them internally by printing the panic information
inline with the output. Since spew is intended to provide deep pretty printing
capabilities on structures, it intentionally does not return any errors.
*/
package gui

104
entry.go
View File

@ -1,25 +1,45 @@
package gui
import "log"
import "errors"
// import "fmt"
import "fmt"
import "github.com/andlabs/ui"
// import ui "git.wit.org/interesting/andlabs-ui"
import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew"
import "github.com/davecgh/go-spew/spew"
// functions for handling text entry boxes
func NewLabel(box *GuiBox, text string) {
box.Append(ui.NewLabel(text), false)
}
func (n *Node) NewLabel(text string) *Node {
// make new node here
newNode := n.makeNode(text, 333, 334)
// n.Append(ui.NewLabel(text), false)
newNode := makeNode(n, text, 333, 334)
newNode.Dump()
// panic("node.NewLabel()")
n.Append(newNode)
return newNode
}
func (b *GuiBox) GetText(name string) string {
if (b.Window.EntryMap == nil) {
log.Println("gui.GetText() ERROR b.Box.Window.EntryMap == nil")
return ""
}
spew.Dump(b.Window.EntryMap)
if (b.Window.EntryMap[name] == nil) {
log.Println("gui.GetText() ERROR box.Window.EntryMap[", name, "] == nil ")
return ""
}
e := b.Window.EntryMap[name]
log.Println("gui.GetText() box.Window.EntryMap[", name, "] = ", e.UiEntry.Text())
log.Println("gui.GetText() END")
return e.UiEntry.Text()
}
func (n *Node) SetText(value string) error {
log.Println("gui.SetText() value =", value)
if (n.uiText != nil) {
@ -30,20 +50,72 @@ func (n *Node) SetText(value string) error {
n.uiButton.SetText(value)
return nil
}
if (n.uiMultilineEntry != nil) {
n.uiMultilineEntry.SetText(value)
return nil
}
n.Dump()
return errors.New("couldn't find something to set the text to")
return nil
}
func (n *Node) SetMargined(x bool) {
if (n.uiGroup != nil) {
n.uiGroup.SetMargined(x)
return
func SetText(box *GuiBox, name string, value string) error {
if (box == nil) {
return fmt.Errorf("gui.SetText() ERROR box == nil")
}
log.Println("Couldn't find something that has a Margin setting")
if (box.Window.EntryMap == nil) {
return fmt.Errorf("gui.SetText() ERROR b.Box.Window.EntryMap == nil")
}
spew.Dump(box.Window.EntryMap)
if (box.Window.EntryMap[name] == nil) {
return fmt.Errorf("gui.SetText() ERROR box.Window.EntryMap[" + name + "] == nil ")
}
e := box.Window.EntryMap[name]
log.Println("gui.SetText() box.Window.EntryMap[", name, "] = ", e.UiEntry.Text())
e.UiEntry.SetText(value)
log.Println("gui.SetText() box.Window.EntryMap[", name, "] = ", e.UiEntry.Text())
log.Println("gui.SetText() END")
return nil
}
// makeEntryBox(box, "hostname:", "blah.foo.org") {
func MakeEntryVbox(box *GuiBox, a string, startValue string, edit bool, action string) *GuiEntry {
// Start 'Nickname' vertical box
vboxN := ui.NewVerticalBox()
vboxN.SetPadded(true)
vboxN.Append(ui.NewLabel(a), false)
e := defaultMakeEntry(startValue, edit, action)
vboxN.Append(e.UiEntry, false)
box.UiBox.Append(vboxN, false)
// End 'Nickname' vertical box
return e
}
func MakeEntryHbox(box *GuiBox, a string, startValue string, edit bool, action string) *GuiEntry {
hboxN := ui.NewHorizontalBox()
hboxN.SetPadded(true)
hboxN.Append(ui.NewLabel(a), false)
e := defaultMakeEntry(startValue, edit, action)
hboxN.Append(e.UiEntry, true)
box.UiBox.Append(hboxN, true)
return e
}
func AddEntry(box *GuiBox, name string) *GuiEntry {
var ge *GuiEntry
ge = new(GuiEntry)
ue := ui.NewEntry()
ue.SetReadOnly(false)
ue.OnChanged(func(*ui.Entry) {
log.Println("gui.AddEntry() OK. ue.Text() =", ue.Text())
})
box.UiBox.Append(ue, false)
ge.UiEntry = ue
box.Window.EntryMap[name] = ge
return ge
}
func defaultEntryChange(e *ui.Entry) {

59
find.go
View File

@ -17,6 +17,65 @@ func (n *Node) FindControl() *ui.Control {
return n.uiControl
}
func (n *Node) FindBox() *GuiBox {
if (n.box != nil) {
return n.box
}
if (n.parent != nil) {
p := n.parent
return p.box
}
return n.box
}
func (n *Node) FindWindowBox() *GuiBox {
if (n.box == nil) {
panic("SERIOUS ERROR n.box == nil in FindWindowBox()")
}
return n.box
}
func (w *GuiWindow) FindNode() *Node {
return w.node
}
func (b *GuiBox) FindNode() *Node {
log.Println("gui.FindNode() on GuiBox")
if b.node != nil {
return b.node
}
Data.ListChildren(true)
b.Dump()
log.Println("gui.FindNode() on GuiBox is nil")
os.Exit(-1)
return nil
}
func FindWindow(s string) *GuiWindow {
for name, window := range Data.WindowMap {
if name == s {
return window
}
}
log.Printf("COULD NOT FIND WINDOW " + s)
return nil
}
func FindBox(s string) *GuiBox {
for name, window := range Data.WindowMap {
if name != s {
continue
}
for name, abox := range window.BoxMap {
log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
return abox
}
log.Println("gui.FindBox() NEED TO INIT WINDOW name =", name)
}
log.Println("gui.FindBox() COULD NOT FIND BOX", s)
return nil
}
func FindNode(name string) *Node {
if Data.NodeMap == nil {
log.Println("gui.FindNode() gui.Data.NodeMap == nil")

9
go.mod
View File

@ -1,10 +1,9 @@
module git.wit.org/wit/gui
go 1.19
go 1.17
require (
git.wit.org/interesting/andlabs-ui v0.0.0-20200610043537-70a69d6ae31e // indirect
github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e
github.com/davecgh/go-spew v1.1.1
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
)

8
go.sum
View File

@ -1,10 +1,8 @@
git.wit.org/interesting/andlabs-ui v0.0.0-20200610043537-70a69d6ae31e h1:CTg83RH/Poy/HCBbBkRFIqKsdBSsHkLeED6XbMmzZzk=
git.wit.org/interesting/andlabs-ui v0.0.0-20200610043537-70a69d6ae31e/go.mod h1:UuaKXIGj4crFE8XDWljgHTyKi8j4pSd9Vvn+zeHNjkQ=
github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e h1:wSQCJiig/QkoUnpvelSPbLiZNWvh2yMqQTQvIQqSUkU=
github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e/go.mod h1:5G2EjwzgZUPnnReoKvPWVneT8APYbyKkihDVAHUi0II=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

6
gui.go
View File

@ -14,16 +14,18 @@ const Xaxis = 0 // box that is horizontal
const Yaxis = 1 // box that is vertical
func init() {
log.Println("gui.init() REMOVE THIS init()")
log.Println("gui.init() has been run")
Data.buttonMap = make(map[*ui.Button]*GuiButton)
Data.WindowMap = make(map[string]*GuiWindow)
Data.NodeMap = make(map[string]*Node)
Data.NodeSlice = make([]*Node, 0)
Config.counter = 0
Config.prefix = "wit"
Config.DebugNode = false
Config.DebugTabs = false
Config.Stretchy = true
}
func GuiInit() {

View File

@ -3,7 +3,6 @@ package gui
import (
"log"
"fmt"
"image/color"
// "reflect"
// "github.com/davecgh/go-spew/spew"
@ -45,29 +44,20 @@ type Node struct {
Name string
Width int
Height int
OnChanged func ()
Color color.RGBA
parent *Node
children []*Node
area *GuiArea
window *GuiWindow
box *GuiBox
custom func(*Node)
values interface {}
uiControl *ui.Control
uiButton *ui.Button
uiFontButton *ui.FontButton
uiColorButton *ui.ColorButton
uiWindow *ui.Window
uiAttrstr *ui.AttributedString
uiTab *ui.Tab
uiBox *ui.Box
uiArea *ui.Area
uiText *ui.EditableCombobox
uiMultilineEntry *ui.MultilineEntry
uiGroup *ui.Group
uiGrid *ui.Grid
uiTab *ui.Tab
uiBox *ui.Box
uiText *ui.EditableCombobox
}
func (n *Node) Parent() *Node {
@ -83,7 +73,6 @@ func (n *Node) Dump() {
log.Println("gui.Node.Dump() Name = ", n.Name)
log.Println("gui.Node.Dump() Width = ", n.Width)
log.Println("gui.Node.Dump() Height = ", n.Height)
log.Println("gui.Node.Dump() OnChanged = ", n.OnChanged)
if (n.parent == nil) {
log.Println("gui.Node.Dump() parent = nil")
@ -92,20 +81,24 @@ func (n *Node) Dump() {
}
log.Println("gui.Node.Dump() children = ", n.children)
// log.Println("gui.Node.Dump() window = ", n.window)
// log.Println("gui.Node.Dump() box = ", n.box)
log.Println("gui.Node.Dump() window = ", n.window)
log.Println("gui.Node.Dump() box = ", n.box)
log.Println("gui.Node.Dump() uiWindow = ", n.uiWindow)
log.Println("gui.Node.Dump() uiTab = ", n.uiTab)
log.Println("gui.Node.Dump() uiBox = ", n.uiBox)
log.Println("gui.Node.Dump() uiControl = ", n.uiControl)
log.Println("gui.Node.Dump() uiButton = ", n.uiButton)
log.Println("gui.Node.Dump() uiText = ", n.uiText)
if (n.id == "") {
log.Println("THIS SHOULD NOT HAPPEN: gui.Node.Dump() id == nil")
panic("gui.Node.Dump() id == nil")
}
}
func (n *Node) SetBox(box *GuiBox) {
n.box = box
}
func (n *Node) SetName(name string) {
// n.uiType.SetName(name)
if (n.uiWindow != nil) {
@ -138,22 +131,19 @@ func (n *Node) List() {
var listChildrenParent *Node
var listChildrenDepth int = 0
// var indent string = "\t"
var indent string = " "
func indentPrintln(depth int, format string, a ...interface{}) {
var space string
var tabs string
for i := 0; i < depth; i++ {
space = space + indent
tabs = tabs + "\t"
}
// newFormat := tabs + strconv.Itoa(depth) + " " + format
newFormat := space + format
newFormat := tabs + format
log.Println(newFormat, a)
}
func (n *Node) ListChildren(dump bool) {
indentPrintln(listChildrenDepth, "", n.id, n.Width, n.Height, n.Name)
indentPrintln(listChildrenDepth, "\t", n.id, n.Width, n.Height, n.Name)
if (dump == true) {
n.Dump()
@ -212,13 +202,13 @@ func (n *Node) ListChildren(dump bool) {
//
// This function should make a new node with the parent and
// the 'stuff' Node as a child
func (n *Node) AddTabNode(title string) *Node {
func (n *Node) AddTabNode(title string, b *GuiBox) *Node {
var newNode *Node
parent := n
newNode = parent.makeNode(title, 444, 400 + Config.counter)
newNode.uiTab = parent.uiTab
// newNode.box = b
newNode.box = b
if (Config.DebugNode) {
fmt.Println("")
@ -230,62 +220,16 @@ func (n *Node) AddTabNode(title string) *Node {
newNode.Dump()
}
if (newNode.uiTab != nil) {
log.Println("ERROR: wit/gui/ AddTabNode() Something went wrong tab == nil")
if (newNode.uiTab == nil) {
log.Println("wit/gui/ AddTabNode() Something went wrong tab == nil")
// TODO: try to find the tab or window and make them if need be
// newNode.uiTab.Append(title, b.UiBox)
return newNode
}
newNode.uiTab.Append(title, b.UiBox)
return newNode
}
func (n *Node) AddHorizontalBreak() *Node {
log.Println("AddHorizontalBreak added to node =", n.Name)
if (n.uiBox != nil) {
tmp := ui.NewHorizontalSeparator()
n.uiBox.Append(tmp, Config.Stretchy)
} else {
n.Dump()
return nil
}
return n
}
func (n *Node) AddVerticalBreak() *Node {
log.Println("AddVerticalBreak added to node =", n.Name)
if (n.uiBox != nil) {
tmp := ui.NewVerticalSeparator()
n.uiBox.Append(tmp, Config.Stretchy)
} else {
n.Dump()
return nil
}
return n
}
func (n *Node) AddHorizontalBox(title string) *Node {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
if (n.uiBox != nil) {
log.Println("add new hbox to uiBox =", n.uiBox)
n.uiBox.Append(hbox, Config.Stretchy)
newNode := n.makeNode(title, 333, 333 + Config.counter)
newNode.parent = n
newNode.uiBox = hbox
// newNode.uiControl = hbox
return newNode
}
if (n.uiTab != nil) {
log.Println("add new hbox to uiTab =", n.uiTab)
n.uiTab.Append(title, hbox)
newNode := n.makeNode(title, 333, 333 + Config.counter)
newNode.parent = n
newNode.uiBox = hbox
// newNode.uiControl = hbox
return newNode
}
return n
}
func (n *Node) AddTab(title string, uiC *ui.Box) *Node {
parent := n
log.Println("gui.Node.AddTab() START name =", title)
@ -294,12 +238,20 @@ func (n *Node) AddTab(title string, uiC *ui.Box) *Node {
log.Println("gui.Node.AddTab() ERROR ui.Window == nil")
return nil
}
if parent.box == nil {
parent.Dump()
panic("gui.AddTab() ERROR box == nil")
}
if parent.uiTab == nil {
inittab := ui.NewTab() // no, not that 'inittab'
parent.uiWindow.SetChild(inittab)
parent.uiWindow.SetMargined(true)
parent.uiTab = inittab
// parent.Dump()
// panic("gui.AddTab() ERROR uiTab == nil")
}
tab := parent.uiTab
parent.uiWindow.SetMargined(true)
@ -313,6 +265,7 @@ func (n *Node) AddTab(title string, uiC *ui.Box) *Node {
newNode := parent.makeNode(title, 555, 600 + Config.counter)
newNode.uiTab = tab
newNode.uiBox = uiC
// panic("gui.AddTab() after makeNode()")
tabSetMargined(newNode.uiTab)
return newNode
}

View File

@ -2,7 +2,7 @@ package gui
import (
"image/color"
// "log"
"log"
"github.com/andlabs/ui"
"golang.org/x/image/font"
@ -22,8 +22,6 @@ type GuiConfig struct {
Title string
Width int
Height int
Stretchy bool
Menu bool
Exit func(*Node)
Debug bool
@ -40,15 +38,162 @@ type GuiConfig struct {
type GuiData struct {
// a fallback default function to handle mouse events
// if nothing else is defined to handle them
MouseClick func(*Node)
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
Area *GuiArea
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) Dump() {
log.Println("gui.GuiBox.Dump() Name = ", b.Name)
log.Println("gui.GuiBox.Dump() Axis = ", b.Axis)
log.Println("gui.GuiBox.Dump() GuiWindow = ", b.Window)
log.Println("gui.GuiBox.Dump() node = ", b.node)
log.Println("gui.GuiBox.Dump() UiBox = ", b.UiBox)
}
func (b *GuiBox) SetTitle(title string) {
log.Println("DID IT!", title)
if b.Window == nil {
return
}
if b.Window.UiWindow == nil {
return
}
b.Window.UiWindow.SetTitle(title)
return
}
func (w *GuiWindow) SetNode(n *Node) {
if (w.node != nil) {
w.Dump()
panic("gui.SetNode() Error not nil")
}
w.node = n
if (w.node == nil) {
w.Dump()
panic("gui.SetNode() node == nil")
}
}
func (b *GuiBox) SetNode(n *Node) {
if (b.node != nil) {
b.Dump()
panic("gui.SetNode() Error not nil")
}
b.node = n
if (b.node == nil) {
b.Dump()
panic("gui.SetNode() node == nil")
}
}
func (b *GuiBox) Append(child ui.Control, x bool) {
if b.UiBox == nil {
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
}
// text entry fields
@ -58,14 +203,21 @@ type GuiEntry struct {
Last string // the last value
Normalize func(string) string // function to 'normalize' the data
N *Node
B *GuiButton
Box *GuiBox
// andlabs/ui abstraction mapping
UiEntry *ui.Entry
}
//
// AREA STRUCTURES START
// AREA STRUCTURES START
// AREA STRUCTURES START
//
type GuiArea struct {
N *Node // what node to pass mouse events
Button *GuiButton // what button handles mouse events
Box *GuiBox
UiAttrstr *ui.AttributedString
UiArea *ui.Area
@ -79,6 +231,14 @@ type FontString struct {
}
//
// AREA STRUCTURES END
// AREA STRUCTURES END
// AREA STRUCTURES END
//
//
// TABLE DATA STRUCTURES START
// TABLE DATA STRUCTURES START
// TABLE DATA STRUCTURES START
//
@ -95,7 +255,7 @@ type TableData struct {
Cells [20]CellData
Human [20]HumanMap
n *Node
Box *GuiBox
lastRow int
lastColumn int
@ -122,7 +282,7 @@ type HumanCellData struct {
TextID int
Color color.RGBA
ColorID int
N *Node
Button *GuiButton
}
type HumanMap struct {

View File

@ -97,12 +97,13 @@ func InitColumns(mh *TableData, parts []TableColumnData) {
}
}
func AddTableTab(name string, rowcount int, parts []TableColumnData) *TableData {
n := NewWindow()
return n.AddTableBox(name, rowcount, parts)
func AddTableTab(gw *GuiWindow, name string, rowcount int, parts []TableColumnData) *TableData {
node := NewWindow()
b := node.box
return b.AddTableBox(name, rowcount, parts)
}
func (n *Node) AddTableBox(name string, rowcount int, parts []TableColumnData) *TableData {
func (b *GuiBox) AddTableBox(name string, rowcount int, parts []TableColumnData) *TableData {
mh := new(TableData)
mh.RowCount = rowcount
@ -141,10 +142,9 @@ func (n *Node) AddTableBox(name string, rowcount int, parts []TableColumnData) *
// is this needed?
// gw.BoxMap[name] = box
// mh.Box = b
mh.n = n
mh.Box = b
n.uiBox.Append(table, true)
b.UiBox.Append(table, true)
return mh
}

View File

@ -95,12 +95,9 @@ func defaultSetCellValue(mh *TableData, row int, column int) {
humanID := mh.Cells[column].HumanID
log.Println("defaultSetCellValue() FOUND THE TABLE BUTTON ", row, humanID)
n := mh.Rows[row].HumanData[humanID].N
if (n != nil) {
// TODO: fixme. removed on Oct 31 2021
if (n.OnChanged != nil) {
n.OnChanged()
}
button := mh.Rows[row].HumanData[humanID].Button
if (button != nil) {
guiButtonClick(button)
return
}
log.Println("defaultSetCellValue() ERROR: UNKNOWN BUTTON IN TABLE")

159
window.go
View File

@ -2,36 +2,57 @@ package gui
import (
"log"
// "fmt"
"fmt"
"strconv"
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
)
func findUiWindow() *ui.Window {
for _, node := range Data.NodeMap {
if (node.uiWindow != nil) {
return node.uiWindow
func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) {
ui.MsgBox(gw.UiWindow, msg1, msg2)
}
func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) {
ui.MsgBoxError(gw.UiWindow, msg1, msg2)
}
func DeleteWindow(name string) {
log.Println("gui.DeleteWindow() START name =", name)
window := Data.WindowMap[name]
if window == nil {
log.Println("gui.DeleteWindow() NO WINDOW WITH name =", name)
return
}
log.Println("gui.DumpBoxes() MAP: ", name)
log.Println("gui.DumpBoxes()\tWindow.name =", window.Name)
if window.TabNumber == nil {
log.Println("gui.DumpBoxes() \tWindows.TabNumber = nil")
}
tab := *window.TabNumber
log.Println("gui.DumpBoxes() \tWindows.TabNumber =", tab)
log.Println("gui.DumpBoxes() \tSHOULD DELETE TAB", tab, "HERE")
window.UiTab.Delete(tab)
delete(Data.WindowMap, name)
// renumber tabs here
for name, window := range Data.WindowMap {
log.Println("gui.DumpBoxes() MAP: ", name)
if window.TabNumber == nil {
log.Println("gui.DumpBoxes() \tWindows.TabNumber = nil")
} else {
log.Println("gui.DumpBoxes() \tWindows.TabNumber =", *window.TabNumber)
if tab < *window.TabNumber {
log.Println("gui.DumpBoxes() \tSubtracting 1 from TabNumber")
*window.TabNumber -= 1
log.Println("gui.DumpBoxes() \tWindows.TabNumber is now =", *window.TabNumber)
}
}
}
return nil
}
func MessageWindow(msg1 string, msg2 string) (*Node) {
uiW := findUiWindow()
ui.MsgBox(uiW, msg1, msg2)
// TODO: make new node
return nil
}
func ErrorWindow(msg1 string, msg2 string) (*Node) {
uiW := findUiWindow()
ui.MsgBoxError(uiW, msg1, msg2)
return nil
}
func initNode(title string, x int, y int) *Node {
func makeNode(parent *Node, title string, x int, y int) *Node {
var node Node
node.Name = title
node.Width = x
@ -41,17 +62,26 @@ func initNode(title string, x int, y int) *Node {
Config.counter += 1
node.id = id
if (Data.NodeMap[title] != nil) {
log.Println("ERROR: Duplicate window name =", title)
// TODO: just change the 'title' to something unique
return Data.NodeMap[title]
// panic("gui.makeNode() START")
if (parent == nil) {
if (Data.NodeMap[title] != nil) {
log.Println("Duplicate window name =", title)
// TODO: just change the 'title' to something unique
panic(fmt.Sprintf("Duplicate window name = %s\n", title))
return nil
}
// panic("gui.makeNode() before NodeMap()")
Data.NodeMap[title] = &node
Data.NodeArray = append(Data.NodeArray, &node)
Data.NodeSlice = append(Data.NodeSlice, &node)
// panic("gui.makeNode() after NodeMap()")
return &node
} else {
// panic("gui.makeNode() before Append()")
parent.Append(&node)
// panic("gui.makeNode() after Append()")
}
Data.NodeMap[title] = &node
Data.NodeArray = append(Data.NodeArray, &node)
Data.NodeSlice = append(Data.NodeSlice, &node)
return &node
// parent.Append(&node)
//node.parent = parent
node.parent = parent
return &node
}
@ -86,19 +116,15 @@ func (n *Node) AddNode(title string) *Node {
}
func (n *Node) uiNewWindow(title string, x int, y int) {
w := ui.NewWindow(title, x, y, Config.Menu)
w := ui.NewWindow(title, x, y, false)
w.SetBorderless(false)
f := Config.Exit
w.OnClosing(func(*ui.Window) bool {
log.Println("RUNNING the ui.Window().OnClosing() function")
if (Config.Debug) {
log.Println("ui.Window().OnClosing()")
}
if (f != nil) {
f(n)
} else {
n.Dump()
log.Println("gui.uiWindow().OnClosing() NOT SURE WHAT TO DO HERE")
// TODO: always do this here? // by default delete the node?
name := n.Name
delete(Data.NodeMap, name)
}
return true
})
@ -109,16 +135,43 @@ func (n *Node) uiNewWindow(title string, x int, y int) {
return
}
/*
func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Node {
log.Println("gui.WindowMap START title =", title)
if Data.WindowMap[title] != nil {
log.Println("Data.WindowMap[title] already exists title =", title)
title = title + Config.prefix + strconv.Itoa(Config.counter)
Config.counter += 1
}
if Data.WindowMap[title] != nil {
log.Println("Data.WindowMap[title] already exists title =", title)
panic("Data.WindowMap[newGuiWindow.Name] already exists")
return nil
}
var newGuiWindow GuiWindow
newGuiWindow.Width = x
newGuiWindow.Height = y
newGuiWindow.Name = title
newGuiWindow.UiWindow = window
newGuiWindow.BoxMap = make(map[string]*GuiBox)
newGuiWindow.EntryMap = make(map[string]*GuiEntry)
Data.WindowMap[newGuiWindow.Name] = &newGuiWindow
var box GuiBox
box.Window = &newGuiWindow
box.Name = title
node := makeNode(parent, title, x, y)
node.box = &box
node.uiWindow = window
box.node = node
newGuiWindow.BoxMap["jcarrInitTest"] = &box
return node
}
*/
// This routine creates a blank window with a Title and size (W x H)
//
@ -126,29 +179,17 @@ func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Nod
// it can be passed via the 'andlabs/ui' queue which, because it is
// cross platform, must pass UI changes into the OS threads (that is
// my guess).
//
// There is probably some way to pass arguements here that I'm can't think of right now
//
func NewWindow() *Node {
title := Config.Title
w := Config.Width
h := Config.Height
if (Data.NodeMap[title] != nil) {
log.Println("Duplicate window name =", title)
Data.NodeMap[title].Dump()
Data.NodeMap[title].ListChildren(false)
uiW := Data.NodeMap[title].uiWindow
if (uiW != nil) {
uiW.Show()
}
log.Println("PROBABLY BAD ERROR: check here to see if window is really alive")
return Data.NodeMap[title]
}
var n *Node
n = initNode(title, w, h)
n.uiNewWindow(title, w, h)
n = mapWindow(nil, nil, title, w, h)
box := n.box
log.Println("gui.NewWindow() title = box.Name =", box.Name)
n.uiNewWindow(box.Name, w, h)
window := n.uiWindow
f := Config.Exit
@ -160,9 +201,9 @@ func NewWindow() *Node {
return true
})
n.uiWindow = window
box.Window.UiWindow = window
if(n.uiWindow == nil) {
log.Println("ERROR: node.uiWindow == nil. This should never happen")
panic("node.uiWindow == nil. This should never happen")
}
return n
}