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

54
area.go
View File

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

203
box.go
View File

@ -1,7 +1,7 @@
package gui package gui
import "log" import "log"
// import "os" import "os"
// import "reflect" // import "reflect"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
@ -9,17 +9,190 @@ import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew" // 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 { func (n *Node) AddComboBox(title string, s ...string) *Node {
newNode := n.AddNode(title)
box := n.uiBox box := n.uiBox
if (box == nil) { if (box == nil) {
return n return n
} }
ecbox := ui.NewEditableCombobox() ecbox := ui.NewEditableCombobox()
newNode.uiText = ecbox
// newNode.Dump()
// log.Println("ecbox", ecbox)
for id, name := range s { for id, name := range s {
log.Println("Adding Combobox Entry:", id, name) 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) { ecbox.OnChanged(func(*ui.EditableCombobox) {
test := ecbox.Text() test := ecbox.Text()
log.Println("node.Name = '" + newNode.Name + "' text for '" + title + "' is now: '" + test + "'") log.Println("node.Name = '" + n.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()
}
}) })
box.Append(ecbox, Config.Stretchy) box.Append(ecbox, false)
newNode := n.AddNode(title)
newNode.uiText = ecbox
return newNode return newNode
} }
func (n *Node) GetText() string { func (n *Node) OnChanged(f func()) {
if (n.uiMultilineEntry != nil) { f()
return n.uiMultilineEntry.Text()
} }
func (n *Node) GetText() string {
if (n.uiText == nil) { if (n.uiText == nil) {
return "" return ""
} }

153
button.go
View File

@ -2,14 +2,11 @@ package gui
import "log" import "log"
import "reflect" import "reflect"
// import "image/color"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew" // import "github.com/davecgh/go-spew/spew"
// TODO: bring this generic mouse click function back
//
// This is the default mouse click handler // This is the default mouse click handler
// Every mouse click that hasn't been assigned to // Every mouse click that hasn't been assigned to
// something specific will fall into this routine // 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 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 // 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 { func (n *Node) AddButton(name string, custom func(*Node)) *Node {
if (n.uiBox == nil) { if (n.uiBox == nil) {
@ -27,12 +58,9 @@ func (n *Node) AddButton(name string, custom func(*Node)) *Node {
return n return n
} }
button := ui.NewButton(name) button := ui.NewButton(name)
if (Config.Debug) {
log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox)) log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox))
log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button)) log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button))
} n.uiBox.Append(button, false)
// true == expand, false == make normal size button
n.uiBox.Append(button, Config.Stretchy)
n.uiButton = button n.uiButton = button
newNode := n.makeNode(name, 888, 888 + Config.counter) 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()") log.Println("gui.AppendButton() Button Clicked. Running custom()")
custom(newNode) custom(newNode)
}) })
// panic("AppendButton")
// time.Sleep(3 * time.Second)
return newNode return newNode
} }
func (n *Node) CreateFontButton(action string) *Node { func (n *Node) CreateButton(custom func(*GuiButton), name string, values interface {}) *Node {
n.uiFontButton = ui.NewFontButton() 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) { var newB *GuiButton
log.Println("FontButton.OnChanged() START") newB = new(GuiButton)
n.Dump() newB.B = newUiB
}) if (box.UiBox == nil) {
n.uiBox.Append(n.uiFontButton, Config.Stretchy) 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 Data.AllButtons = append(Data.AllButtons, newB)
n.uiGrid = ui.NewGrid()
return n box.Append(newB.B, false)
return newNode
} }
func (n *Node) CreateColorButton(custom func(*Node), name string, values interface {}) *Node { func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton {
newUiB := ui.NewButton(name)
newUiB.OnClicked(defaultButtonClick)
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 // create a 'fake' button entry for the mouse clicks
n.uiColorButton = ui.NewColorButton() var newGB GuiButton
n.custom = custom newGB.Name = "FONT"
n.values = values newGB.FB = ui.NewFontButton()
newGB.Box = box
Data.AllButtons = append(Data.AllButtons, &newGB)
n.uiColorButton.OnChanged(func (*ui.ColorButton) { newGB.FB.OnChanged(func (*ui.FontButton) {
log.Println("ColorButton.OnChanged() START Color Button Click") log.Println("FontButton.OnChanged() START mouseClick(&newBM)", newGB)
rgba := n.Color if (Data.MouseClick != nil) {
r, g, b, a := rgba.R, rgba.G, rgba.B, rgba.A Data.MouseClick(&newGB)
log.Println("ColorButton.OnChanged() Color() =", r, g, b, a)
if (n.custom != nil) {
n.custom(n)
} else if (Data.MouseClick != nil) {
Data.MouseClick(n)
} }
}) })
n.uiBox.Append(n.uiColorButton, Config.Stretchy) return &newGB
return n }
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") groupNode1 := newNode.AddGroup("group 1")
cbNode := groupNode1.AddComboBox("username", "root", "jcarr", "hugo") cbNode := groupNode1.AddComboBox("username", "root", "jcarr", "hugo")
cbNode.OnChanged = func () { cbNode.OnChanged(func () {
username = cbNode.GetText() username = cbNode.GetText()
} })
groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff") groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff")
groupNode1.Dump() groupNode1.Dump()

View File

@ -7,7 +7,7 @@ import (
"github.com/andlabs/ui" "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
// "github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
) )
var names = make([]string, 100) var names = make([]string, 100)
@ -33,6 +33,126 @@ func makeWindowDebug() *ui.Box {
hbox := ui.NewHorizontalBox() hbox := ui.NewHorizontalBox()
hbox.SetPadded(true) 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:") nodeBox := addGroup(hbox, "Windows:")
nodeCombo := ui.NewCombobox() nodeCombo := ui.NewCombobox()
@ -46,7 +166,7 @@ func makeWindowDebug() *ui.Box {
} }
nodeCombo.SetSelected(0) nodeCombo.SetSelected(0)
nodeBox.Append(nodeCombo, Config.Stretchy) nodeBox.Append(nodeCombo, false)
nodeCombo.OnSelected(func(*ui.Combobox) { nodeCombo.OnSelected(func(*ui.Combobox) {
y := nodeCombo.Selected() 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 := addButton(vbox, "Data.DumpNodeMap()")
n1.OnClicked(func(*ui.Button) { 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 { func addGroup(b *ui.Box, name string) *ui.Box {
group := ui.NewGroup(name) group := ui.NewGroup(name)
group.SetMargined(true) group.SetMargined(true)
b.Append(group, Config.Stretchy) b.Append(group, true)
vbox := ui.NewVerticalBox() vbox := ui.NewVerticalBox()
vbox.SetPadded(true) vbox.SetPadded(true)
@ -157,6 +277,48 @@ func addGroup(b *ui.Box, name string) *ui.Box {
return vbox 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 { func addButton(box *ui.Box, name string) *ui.Button {
button := ui.NewButton(name) button := ui.NewButton(name)
@ -164,7 +326,7 @@ func addButton(box *ui.Box, name string) *ui.Button {
log.Println("Should do something here") log.Println("Should do something here")
}) })
box.Append(button, Config.Stretchy) box.Append(button, false)
return button return button
} }

View File

@ -5,7 +5,7 @@ import (
"log" "log"
"time" "time"
// "github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
) )
// WatchGUI() opens a goroutine // WatchGUI() opens a goroutine
@ -22,7 +22,7 @@ func WatchGUI() {
if count > 20 { if count > 20 {
log.Println("Sleep() in watchGUI()") log.Println("Sleep() in watchGUI()")
if Config.Debug { if Config.Debug {
// DumpBoxes() DumpBoxes()
} }
count = 0 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() { func addTableTab() {
var parts []TableColumnData 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) { func (dn *GuiData) ListChildren(dump bool) {
if Data.NodeMap == nil { if Data.NodeMap == nil {
log.Println("gui.Data.ListChildren() 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:") log.Println("gui.Data.ListChildren() Data.NodeMap:")
for name, node := range 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) { if (dump == true) {
log.Println("tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name)
node.Dump() node.Dump()
} }
node.ListChildren(dump) node.ListChildren(dump)

View File

@ -1,6 +1,6 @@
package gui package gui
import "log" // import "log"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
@ -16,7 +16,7 @@ func (n *Node) AddGroup(title string) *Node {
} }
group := ui.NewGroup(title) group := ui.NewGroup(title)
group.SetMargined(true) group.SetMargined(true)
hbox.Append(group, Config.Stretchy) hbox.Append(group, true)
vbox := ui.NewVerticalBox() vbox := ui.NewVerticalBox()
vbox.SetPadded(true) vbox.SetPadded(true)
@ -26,67 +26,3 @@ func (n *Node) AddGroup(title string) *Node {
newNode.uiBox = vbox newNode.uiBox = vbox
return newNode 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 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 package gui

100
entry.go
View File

@ -1,25 +1,45 @@
package gui package gui
import "log" import "log"
import "errors" import "fmt"
// import "fmt"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
// import ui "git.wit.org/interesting/andlabs-ui"
import _ "github.com/andlabs/ui/winmanifest" 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 // 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 { func (n *Node) NewLabel(text string) *Node {
// make new node here // make new node here
newNode := n.makeNode(text, 333, 334) // n.Append(ui.NewLabel(text), false)
newNode := makeNode(n, text, 333, 334)
newNode.Dump() newNode.Dump()
// panic("node.NewLabel()")
n.Append(newNode) n.Append(newNode)
return 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 { func (n *Node) SetText(value string) error {
log.Println("gui.SetText() value =", value) log.Println("gui.SetText() value =", value)
if (n.uiText != nil) { if (n.uiText != nil) {
@ -30,20 +50,72 @@ func (n *Node) SetText(value string) error {
n.uiButton.SetText(value) n.uiButton.SetText(value)
return nil return nil
} }
if (n.uiMultilineEntry != nil) {
n.uiMultilineEntry.SetText(value)
return nil return nil
} }
n.Dump()
return errors.New("couldn't find something to set the text to") func SetText(box *GuiBox, name string, value string) error {
if (box == nil) {
return fmt.Errorf("gui.SetText() ERROR box == nil")
}
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
} }
func (n *Node) SetMargined(x bool) { // makeEntryBox(box, "hostname:", "blah.foo.org") {
if (n.uiGroup != nil) { func MakeEntryVbox(box *GuiBox, a string, startValue string, edit bool, action string) *GuiEntry {
n.uiGroup.SetMargined(x) // Start 'Nickname' vertical box
return 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
} }
log.Println("Couldn't find something that has a Margin setting")
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) { func defaultEntryChange(e *ui.Entry) {

59
find.go
View File

@ -17,6 +17,65 @@ func (n *Node) FindControl() *ui.Control {
return n.uiControl 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 { func FindNode(name string) *Node {
if Data.NodeMap == nil { if Data.NodeMap == nil {
log.Println("gui.FindNode() gui.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 module git.wit.org/wit/gui
go 1.19 go 1.17
require ( require (
git.wit.org/interesting/andlabs-ui v0.0.0-20200610043537-70a69d6ae31e // indirect github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e
github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e // indirect github.com/davecgh/go-spew v1.1.1
github.com/davecgh/go-spew v1.1.1 // indirect golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
) )

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 h1:wSQCJiig/QkoUnpvelSPbLiZNWvh2yMqQTQvIQqSUkU=
github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e/go.mod h1:5G2EjwzgZUPnnReoKvPWVneT8APYbyKkihDVAHUi0II= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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= 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 const Yaxis = 1 // box that is vertical
func init() { 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.NodeMap = make(map[string]*Node)
Data.NodeSlice = make([]*Node, 0) Data.NodeSlice = make([]*Node, 0)
Config.counter = 0 Config.counter = 0
Config.prefix = "wit" Config.prefix = "wit"
Config.DebugNode = false Config.DebugNode = false
Config.DebugTabs = false Config.DebugTabs = false
Config.Stretchy = true
} }
func GuiInit() { func GuiInit() {

View File

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

View File

@ -2,7 +2,7 @@ package gui
import ( import (
"image/color" "image/color"
// "log" "log"
"github.com/andlabs/ui" "github.com/andlabs/ui"
"golang.org/x/image/font" "golang.org/x/image/font"
@ -22,8 +22,6 @@ type GuiConfig struct {
Title string Title string
Width int Width int
Height int Height int
Stretchy bool
Menu bool
Exit func(*Node) Exit func(*Node)
Debug bool Debug bool
@ -40,15 +38,162 @@ type GuiConfig struct {
type GuiData struct { type GuiData struct {
// a fallback default function to handle mouse events // a fallback default function to handle mouse events
// if nothing else is defined to handle them // if nothing else is defined to handle them
MouseClick func(*Node) MouseClick func(*GuiButton)
// A map of all the entry boxes // A map of all the entry boxes
AllEntries []*GuiEntry AllEntries []*GuiEntry
WindowMap map[string]*GuiWindow
// Store access to everything via binary tree's // Store access to everything via binary tree's
NodeMap map[string]*Node NodeMap map[string]*Node
NodeArray []*Node NodeArray []*Node
NodeSlice []*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 // text entry fields
@ -58,14 +203,21 @@ type GuiEntry struct {
Last string // the last value Last string // the last value
Normalize func(string) string // function to 'normalize' the data Normalize func(string) string // function to 'normalize' the data
N *Node B *GuiButton
Box *GuiBox
// andlabs/ui abstraction mapping // andlabs/ui abstraction mapping
UiEntry *ui.Entry UiEntry *ui.Entry
} }
//
// AREA STRUCTURES START
// AREA STRUCTURES START
// AREA STRUCTURES START
//
type GuiArea struct { type GuiArea struct {
N *Node // what node to pass mouse events Button *GuiButton // what button handles mouse events
Box *GuiBox
UiAttrstr *ui.AttributedString UiAttrstr *ui.AttributedString
UiArea *ui.Area 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 // TABLE DATA STRUCTURES START
// //
@ -95,7 +255,7 @@ type TableData struct {
Cells [20]CellData Cells [20]CellData
Human [20]HumanMap Human [20]HumanMap
n *Node Box *GuiBox
lastRow int lastRow int
lastColumn int lastColumn int
@ -122,7 +282,7 @@ type HumanCellData struct {
TextID int TextID int
Color color.RGBA Color color.RGBA
ColorID int ColorID int
N *Node Button *GuiButton
} }
type HumanMap struct { type HumanMap struct {

View File

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

View File

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

143
window.go
View File

@ -2,36 +2,57 @@ package gui
import ( import (
"log" "log"
// "fmt" "fmt"
"strconv" "strconv"
"github.com/andlabs/ui" "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
) )
func findUiWindow() *ui.Window { func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) {
for _, node := range Data.NodeMap { ui.MsgBox(gw.UiWindow, msg1, msg2)
if (node.uiWindow != nil) {
return node.uiWindow
}
}
return nil
} }
func MessageWindow(msg1 string, msg2 string) (*Node) { func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) {
uiW := findUiWindow() ui.MsgBoxError(gw.UiWindow, msg1, msg2)
ui.MsgBox(uiW, msg1, msg2)
// TODO: make new node
return nil
} }
func ErrorWindow(msg1 string, msg2 string) (*Node) { func DeleteWindow(name string) {
uiW := findUiWindow() log.Println("gui.DeleteWindow() START name =", name)
ui.MsgBoxError(uiW, msg1, msg2) window := Data.WindowMap[name]
return nil if window == nil {
log.Println("gui.DeleteWindow() NO WINDOW WITH name =", name)
return
} }
func initNode(title string, x int, y int) *Node { 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)
}
}
}
}
func makeNode(parent *Node, title string, x int, y int) *Node {
var node Node var node Node
node.Name = title node.Name = title
node.Width = x node.Width = x
@ -41,17 +62,26 @@ func initNode(title string, x int, y int) *Node {
Config.counter += 1 Config.counter += 1
node.id = id node.id = id
// panic("gui.makeNode() START")
if (parent == nil) {
if (Data.NodeMap[title] != nil) { if (Data.NodeMap[title] != nil) {
log.Println("ERROR: Duplicate window name =", title) log.Println("Duplicate window name =", title)
// TODO: just change the 'title' to something unique // TODO: just change the 'title' to something unique
return Data.NodeMap[title] panic(fmt.Sprintf("Duplicate window name = %s\n", title))
return nil
} }
// panic("gui.makeNode() before NodeMap()")
Data.NodeMap[title] = &node Data.NodeMap[title] = &node
Data.NodeArray = append(Data.NodeArray, &node) Data.NodeArray = append(Data.NodeArray, &node)
Data.NodeSlice = append(Data.NodeSlice, &node) Data.NodeSlice = append(Data.NodeSlice, &node)
// panic("gui.makeNode() after NodeMap()")
return &node return &node
// parent.Append(&node) } else {
//node.parent = parent // panic("gui.makeNode() before Append()")
parent.Append(&node)
// panic("gui.makeNode() after Append()")
}
node.parent = parent
return &node return &node
} }
@ -86,19 +116,15 @@ func (n *Node) AddNode(title string) *Node {
} }
func (n *Node) uiNewWindow(title string, x int, y int) { 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) w.SetBorderless(false)
f := Config.Exit f := Config.Exit
w.OnClosing(func(*ui.Window) bool { 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) { if (f != nil) {
f(n) 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 return true
}) })
@ -109,16 +135,43 @@ func (n *Node) uiNewWindow(title string, x int, y int) {
return return
} }
/*
func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Node { func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Node {
log.Println("gui.WindowMap START title =", title) 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 := makeNode(parent, title, x, y)
node.box = &box
node.uiWindow = window node.uiWindow = window
box.node = node
newGuiWindow.BoxMap["jcarrInitTest"] = &box
return node return node
} }
*/
// This routine creates a blank window with a Title and size (W x H) // 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 // 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 // cross platform, must pass UI changes into the OS threads (that is
// my guess). // my guess).
//
// There is probably some way to pass arguements here that I'm can't think of right now
//
func NewWindow() *Node { func NewWindow() *Node {
title := Config.Title title := Config.Title
w := Config.Width w := Config.Width
h := Config.Height 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 var n *Node
n = initNode(title, w, h) n = mapWindow(nil, nil, title, w, h)
n.uiNewWindow(title, w, h) box := n.box
log.Println("gui.NewWindow() title = box.Name =", box.Name)
n.uiNewWindow(box.Name, w, h)
window := n.uiWindow window := n.uiWindow
f := Config.Exit f := Config.Exit
@ -160,9 +201,9 @@ func NewWindow() *Node {
return true return true
}) })
n.uiWindow = window box.Window.UiWindow = window
if(n.uiWindow == nil) { if(n.uiWindow == nil) {
log.Println("ERROR: node.uiWindow == nil. This should never happen") panic("node.uiWindow == nil. This should never happen")
} }
return n return n
} }