From b036f9fccbf6b20ec510a54c892c3ee2a166b6f1 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Tue, 5 Oct 2021 07:13:24 -0500 Subject: DEBUG: added button to SetMargin() by name Signed-off-by: Jeff Carr --- debug.go | 1 + 1 file changed, 1 insertion(+) (limited to 'debug.go') diff --git a/debug.go b/debug.go index ec60df2..4253306 100644 --- a/debug.go +++ b/debug.go @@ -41,6 +41,7 @@ func DumpBoxes() { 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") { -- cgit v1.2.3 From ff2d50354b7846c11227752d555e86f14bf3fc47 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Tue, 5 Oct 2021 10:37:53 -0500 Subject: DEBUG: add DumpMap() Signed-off-by: Jeff Carr --- button.go | 4 ++-- debug.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'debug.go') diff --git a/button.go b/button.go index 24dcd49..825b79b 100644 --- a/button.go +++ b/button.go @@ -68,7 +68,7 @@ func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values inte Data.AllButtons = append(Data.AllButtons, newB) - box.UiBox.Append(newB.B, false) + box.Append(newB.B, false) return newB } @@ -110,6 +110,6 @@ func CreateColorButton(box *GuiBox, custom func(*GuiButton), name string, values Data.MouseClick(&newCB) } }) - box.UiBox.Append(newCB.CB, false) + box.Append(newCB.CB, false) return &newCB } diff --git a/debug.go b/debug.go index 4253306..75f5424 100644 --- a/debug.go +++ b/debug.go @@ -30,6 +30,12 @@ func WatchGUI() { } } +func DumpMap() { + for name, _ := range Data.WindowMap { + log.Println("gui.DumpBoxes() MAP: ", name) + } +} + func DumpBoxes() { for name, window := range Data.WindowMap { log.Println("gui.DumpBoxes() MAP: ", name) -- cgit v1.2.3 From 84d67feb2c8d8cea48bc6d4a362a70dab65a67c5 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Wed, 6 Oct 2021 11:50:35 -0500 Subject: FORMAT: I think somehow I formatted this --- debug.go | 44 +++++++++++++++++++++++--------------------- gui.go | 19 +++++++++++-------- window-debug.go | 1 + 3 files changed, 35 insertions(+), 29 deletions(-) (limited to 'debug.go') diff --git a/debug.go b/debug.go index 75f5424..c0ae5dd 100644 --- a/debug.go +++ b/debug.go @@ -1,26 +1,28 @@ package gui -import "log" -import "time" -import "fmt" +import ( + "fmt" + "log" + "time" + + "github.com/davecgh/go-spew/spew" +) + // import "reflect" // import "github.com/andlabs/ui" // import _ "github.com/andlabs/ui/winmanifest" -import "github.com/davecgh/go-spew/spew" -// import pb "git.wit.com/wit/witProtobuf" // -// this watches the GUI primarily to process protobuf's -// this is pointless or wrong but I use it for debugging +// Dump out debugging information every 4 seconds // func WatchGUI() { count := 0 for { - if (count > 20) { + if count > 20 { log.Println("Sleep() in watchGUI()") - if (Config.Debug) { + if Config.Debug { DumpBoxes() } count = 0 @@ -39,7 +41,7 @@ func DumpMap() { func DumpBoxes() { for name, window := range Data.WindowMap { log.Println("gui.DumpBoxes() MAP: ", name) - if (window.TabNumber == nil) { + if window.TabNumber == nil { log.Println("gui.DumpBoxes() \tWindows.TabNumber = nil") } else { log.Println("gui.DumpBoxes() \tWindows.TabNumber =", *window.TabNumber) @@ -50,14 +52,14 @@ func DumpBoxes() { 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) { + if name == "MAINBOX" { + if Config.Debug { scs := spew.ConfigState{MaxDepth: 1} scs.Dump(abox.UiBox) } } } - if (window.UiTab != nil) { + 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() @@ -68,20 +70,20 @@ func DumpBoxes() { // tmp := spew.NewDefaultConfig() // tmp.MaxDepth = 2 // tmp.Dump(window.UiTab) - if (Config.Debug) { + 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) + 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) + } } - } */ } @@ -93,7 +95,7 @@ func addTableTab() { var b TableColumnData b.CellType = foo - b.Heading = fmt.Sprintf("heading%d", key) + b.Heading = fmt.Sprintf("heading%d", key) parts = append(parts, b) } diff --git a/gui.go b/gui.go index 3bdd32e..97e3c24 100644 --- a/gui.go +++ b/gui.go @@ -1,11 +1,14 @@ package gui -import "log" -// import "time" -import "regexp" +import ( + "github.com/andlabs/ui" // import "time" + "log" + "regexp" -import "github.com/andlabs/ui" -import _ "github.com/andlabs/ui/winmanifest" // the _ means we only need this for the init() + _ "github.com/andlabs/ui/winmanifest" +) + +// the _ means we only need this for the init() const Xaxis = 0 // box that is horizontal const Yaxis = 1 // box that is vertical @@ -13,13 +16,13 @@ const Yaxis = 1 // box that is vertical func init() { log.Println("gui.init() has been run") - Data.buttonMap = make(map[*ui.Button]*GuiButton) - Data.WindowMap = make(map[string]*GuiWindow) + Data.buttonMap = make(map[*ui.Button]*GuiButton) + Data.WindowMap = make(map[string]*GuiWindow) } func GuiInit() { ui.OnShouldQuit(func() bool { - ui.Quit() + ui.Quit() return true }) } diff --git a/window-debug.go b/window-debug.go index bf93a9b..77a7e5e 100644 --- a/window-debug.go +++ b/window-debug.go @@ -27,6 +27,7 @@ func makeWindowDebug() ui.Control { log.Println("range Data.WindowMap() name =", name) addName(cbox, name) } + cbox.SetSelected(0) vbox.Append(cbox, false) -- cgit v1.2.3 From 7c6fae3efea5e96ae8aad2a3171f42ab4e69b3b1 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Wed, 6 Oct 2021 13:23:00 -0500 Subject: TAB: correctly lookup and add tabs to blank windows Signed-off-by: Jeff Carr --- debug.go | 6 +- structs.go | 226 ++++++++++++++++++++++++++++++-------------------------- window-debug.go | 77 +++++++++++-------- window.go | 2 + 4 files changed, 177 insertions(+), 134 deletions(-) (limited to 'debug.go') diff --git a/debug.go b/debug.go index c0ae5dd..8c1e947 100644 --- a/debug.go +++ b/debug.go @@ -33,8 +33,12 @@ func WatchGUI() { } func DumpMap() { - for name, _ := range Data.WindowMap { + 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) + } } } diff --git a/structs.go b/structs.go index 6387b45..71921bd 100644 --- a/structs.go +++ b/structs.go @@ -1,36 +1,39 @@ package gui -import "log" -import "image/color" -import "golang.org/x/image/font" +import ( + "image/color" + "log" -import "github.com/andlabs/ui" -import _ "github.com/andlabs/ui/winmanifest" + "github.com/andlabs/ui" + "golang.org/x/image/font" + + _ "github.com/andlabs/ui/winmanifest" +) // // All GUI Data Structures and functions that are external // If you need cross platform support, these might only // be the safe way to interact with the GUI // -var Data GuiData -var Config GuiConfig +var Data GuiData +var Config GuiConfig type GuiConfig struct { - Width int - Height int - Debug bool - DebugTable bool - Exit func(*GuiWindow) + Width int + Height int + Debug bool + DebugTable bool + Exit func(*GuiWindow) } 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 - MouseClick func(*GuiButton) + MouseClick func(*GuiButton) // A map of all the entry boxes - AllEntries []*GuiEntry - WindowMap map[string]*GuiWindow + AllEntries []*GuiEntry + WindowMap map[string]*GuiWindow // Windows []*GuiWindow @@ -40,15 +43,15 @@ type GuiData struct { // // This has to work this way because of how // andlabs/ui & andlabs/libui work - AllButtons []*GuiButton - buttonMap map[*ui.Button]*GuiButton - Nodes *Node + AllButtons []*GuiButton + buttonMap map[*ui.Button]*GuiButton + Nodes *Node } type GuiTab struct { - Name string // field for human readable name - Number int // the andlabs/ui tab index - Window *GuiWindow // the parent Window + Name string // field for human readable name + Number int // the andlabs/ui tab index + Window *GuiWindow // the parent Window } // @@ -70,42 +73,42 @@ type GuiTab struct { // 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 + 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 + BoxMap map[string]*GuiBox + EntryMap map[string]*GuiEntry + Area *GuiArea // andlabs/ui abstraction mapping - UiWindow *ui.Window - UiTab *ui.Tab // if this != nil, the window is 'tabbed' + UiWindow *ui.Window + UiTab *ui.Tab // if this != nil, the window is 'tabbed' } // 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 + Name string // field for human readable name + Axis int // does it add items to the X or Y axis + Window *GuiWindow // the parent Window // andlabs/ui abstraction mapping - UiBox *ui.Box + UiBox *ui.Box } func (s GuiBox) SetTitle(title string) { log.Println("DID IT!", title) - if (s.Window == nil) { + if s.Window == nil { return } - if (s.Window.UiWindow == nil) { + if s.Window.UiWindow == nil { return } s.Window.UiWindow.SetTitle(title) @@ -113,17 +116,33 @@ func (s GuiBox) SetTitle(title string) { } func (s GuiBox) Append(child ui.Control, x bool) { - if (s.UiBox == nil) { + if s.UiBox == nil { return } s.UiBox.Append(child, x) } +func (w GuiWindow) InitBox(title string) *GuiBox { + if w.UiWindow == nil { + log.Println("gui.InitBox() THIS SHOULD NEVER HAPPEN. Window doesn't exist", w) + return nil + } + tab := ui.NewTab() + w.UiWindow.SetChild(tab) + w.UiWindow.SetMargined(true) + + tab.Append(title, initBlankWindow()) + tab.SetMargined(0, true) + + w.UiTab = tab + return nil +} + func (s GuiBox) InitTab(title string) *ui.Tab { - if (s.Window == nil) { + if s.Window == nil { return nil } - if (s.Window.UiWindow == nil) { + if s.Window.UiWindow == nil { return nil } @@ -141,10 +160,10 @@ func (s GuiBox) InitTab(title string) *ui.Tab { } func (s GuiBox) AddTab(title string, custom ui.Control) *ui.Tab { - if (s.Window == nil) { + if s.Window == nil { return nil } - if (s.Window.UiTab == nil) { + if s.Window.UiTab == nil { return nil } @@ -155,10 +174,10 @@ func (s GuiBox) AddTab(title string, custom ui.Control) *ui.Tab { } func (s GuiBox) AddTab2(title string, custom ui.Control) *ui.Tab { - if (s.Window == nil) { + if s.Window == nil { return nil } - if (s.Window.UiTab == nil) { + if s.Window.UiTab == nil { return nil } @@ -200,32 +219,32 @@ func tabSetMargined(tab *ui.Tab) { // 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 + 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 + Custom func(*GuiButton) + Values interface{} + Color color.RGBA // andlabs/ui abstraction mapping - B *ui.Button - FB *ui.FontButton - CB *ui.ColorButton + B *ui.Button + FB *ui.FontButton + CB *ui.ColorButton } // text entry fields type GuiEntry struct { - Name string // field for human readable name - Edit bool - Last string // the last value - Normalize func (string) string // function to 'normalize' the data + Name string // field for human readable name + Edit bool + Last string // the last value + Normalize func(string) string // function to 'normalize' the data - B *GuiButton - Box *GuiBox + B *GuiButton + Box *GuiBox // andlabs/ui abstraction mapping - UiEntry *ui.Entry + UiEntry *ui.Entry } // @@ -233,20 +252,21 @@ type GuiEntry struct { // AREA STRUCTURES START // AREA STRUCTURES START // -type GuiArea struct{ - Button *GuiButton // what button handles mouse events - Box *GuiBox +type GuiArea struct { + Button *GuiButton // what button handles mouse events + Box *GuiBox - UiAttrstr *ui.AttributedString - UiArea *ui.Area + UiAttrstr *ui.AttributedString + UiArea *ui.Area } type FontString struct { - S string - Size int - F font.Face - W font.Weight + S string + Size int + F font.Face + W font.Weight } + // // AREA STRUCTURES END // AREA STRUCTURES END @@ -264,18 +284,18 @@ type FontString struct { // to the GUI. This is the "authoritative" data. // type TableData struct { - RowCount int // This is the number of 'rows' which really means data elements not what the human sees - RowWidth int // This is how wide each row is - Rows []RowData // This is all the table data by row - generatedColumnTypes []ui.TableValue // generate this dynamically + RowCount int // This is the number of 'rows' which really means data elements not what the human sees + RowWidth int // This is how wide each row is + Rows []RowData // This is all the table data by row + generatedColumnTypes []ui.TableValue // generate this dynamically - Cells [20]CellData - Human [20]HumanMap + Cells [20]CellData + Human [20]HumanMap - Box *GuiBox + Box *GuiBox - lastRow int - lastColumn int + lastRow int + lastColumn int } // @@ -294,44 +314,44 @@ type TableData struct { // TODO: re-add images and the progress bar (works in andlabs/ui) // type HumanCellData struct { - Name string // what kind of row is this? - Text string - TextID int - Color color.RGBA - ColorID int - Button *GuiButton + Name string // what kind of row is this? + Text string + TextID int + Color color.RGBA + ColorID int + Button *GuiButton } type HumanMap struct { - Name string // what kind of row is this? - TextID int - ColorID int + Name string // what kind of row is this? + TextID int + ColorID int } type TableColumnData struct { - Index int - CellType string - Heading string - Color string + Index int + CellType string + Heading string + Color string } type CellData struct { - Index int - HumanID int - Name string // what type of cell is this? + Index int + HumanID int + Name string // what type of cell is this? } // hmm. will this stand the test of time? type RowData struct { - Name string // what kind of row is this? - Status string // status of the row? -/* - // TODO: These may or may not be implementable - // depending on if it's possible to detect the bgcolor or what row is selected - click func() // what function to call if the user clicks on it - doubleclick func() // what function to call if the user double clicks on it -*/ - HumanData [20]HumanCellData + Name string // what kind of row is this? + Status string // status of the row? + /* + // TODO: These may or may not be implementable + // depending on if it's possible to detect the bgcolor or what row is selected + click func() // what function to call if the user clicks on it + doubleclick func() // what function to call if the user double clicks on it + */ + HumanData [20]HumanCellData } // diff --git a/window-debug.go b/window-debug.go index 77a7e5e..704ef7b 100644 --- a/window-debug.go +++ b/window-debug.go @@ -20,7 +20,7 @@ func makeWindowDebug() ui.Control { vbox.Append(pbar, false) ///////////////////////////////////////////////////// - vbox = addGroup(hbox, "WindowMap 2") + vbox = addGroup(hbox, "Window") cbox := ui.NewCombobox() for name, _ := range Data.WindowMap { @@ -39,9 +39,9 @@ func makeWindowDebug() ui.Control { }) ///////////////////////////////////////////////////// - vbox = addGroup(hbox, "Buttons") + vbox = addGroup(hbox, "Debug Window") - b1 := addButton(vbox, "dumpBox(name)") + b1 := addButton(vbox, "dumpBox(window)") b1.OnClicked(func(*ui.Button) { x := cbox.Selected() log.Println("x =", x) @@ -49,23 +49,12 @@ func makeWindowDebug() ui.Control { dumpBox(names[x]) }) - dump2 := addButton(vbox, "Dump Boxes") - dump2.OnClicked(func(*ui.Button) { - DumpBoxes() - }) - - dump1 := addButton(vbox, "Dump MAP") - dump1.OnClicked(func(*ui.Button) { - DumpMap() - }) - - b2 := addButton(vbox, "SetMargined()") + b2 := addButton(vbox, "SetMargined(tab)") b2.OnClicked(func(*ui.Button) { x := cbox.Selected() log.Println("x =", x) - log.Println("findBox; names[x] =", names[x]) - findBox(names[x]) - gw := findBox(names[x]) + log.Println("FindWindow; names[x] =", names[x]) + gw := FindWindow(names[x]) if gw == nil { return } @@ -82,13 +71,12 @@ func makeWindowDebug() ui.Control { gw.UiTab.SetMargined(*gw.TabNumber, true) }) - b3 := addButton(vbox, "Hide()") + b3 := addButton(vbox, "Hide(tab)") b3.OnClicked(func(*ui.Button) { x := cbox.Selected() log.Println("x =", x) - log.Println("findBox; names[x] =", names[x]) - findBox(names[x]) - gw := findBox(names[x]) + log.Println("FindWindow; names[x] =", names[x]) + gw := FindWindow(names[x]) if gw == nil { return } @@ -98,13 +86,12 @@ func makeWindowDebug() ui.Control { gw.UiTab.Hide() }) - b4 := addButton(vbox, "Show()") + b4 := addButton(vbox, "Show(tab)") b4.OnClicked(func(*ui.Button) { x := cbox.Selected() log.Println("x =", x) - log.Println("findBox; names[x] =", names[x]) - findBox(names[x]) - gw := findBox(names[x]) + log.Println("FindWindow; names[x] =", names[x]) + gw := FindWindow(names[x]) if gw == nil { return } @@ -114,13 +101,12 @@ func makeWindowDebug() ui.Control { gw.UiTab.Show() }) - b5 := addButton(vbox, "Delete()") + b5 := addButton(vbox, "Delete(tab)") b5.OnClicked(func(*ui.Button) { x := cbox.Selected() log.Println("x =", x) - log.Println("findBox; names[x] =", names[x]) - findBox(names[x]) - gw := findBox(names[x]) + log.Println("FindWindow; names[x] =", names[x]) + gw := FindWindow(names[x]) if gw == nil { return } @@ -133,6 +119,19 @@ func makeWindowDebug() ui.Control { gw.UiTab.Delete(*gw.TabNumber) }) + ///////////////////////////////////////////////////// + vbox = addGroup(hbox, "Global Debug") + + dump2 := addButton(vbox, "Dump Boxes") + dump2.OnClicked(func(*ui.Button) { + DumpBoxes() + }) + + dump1 := addButton(vbox, "Dump MAP") + dump1.OnClicked(func(*ui.Button) { + DumpMap() + }) + return hbox } @@ -156,12 +155,28 @@ func addGroup(b *ui.Box, name string) *ui.Box { return vbox } -func findBox(s string) *GuiWindow { +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 } @@ -180,6 +195,7 @@ func dumpBox(s string) { // 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) if name == "MAINBOX" { @@ -189,6 +205,7 @@ func dumpBox(s string) { } } } + log.Println("gui.dumpBox() BoxMap END") if window.UiTab != nil { pages := window.UiTab.NumPages() log.Println("gui.DumpBoxes()\tWindow.UiTab.NumPages() =", pages) diff --git a/window.go b/window.go index 1dfe05a..24bd879 100644 --- a/window.go +++ b/window.go @@ -210,6 +210,8 @@ func mapWindow(window *ui.Window, title string, x int, y int) *GuiBox { box.Window = &newGuiWindow box.Name = title + newGuiWindow.BoxMap["jcarrInitTest"] = &box + return &box } -- cgit v1.2.3 From 213c7d153b06d3e1211d1cdeae1e4f7833cb89f7 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sun, 31 Oct 2021 14:21:36 -0500 Subject: REFACTOR: refactor everything to gui.Node struct Signed-off-by: Jeff Carr --- .gitignore | 3 +- area.go | 10 +- box.go | 110 +++++++++++-- button.go | 56 +++++++ cmds/gui-demo/Makefile | 5 + cmds/gui-demo/demo-window.go | 33 ++++ cmds/gui-demo/main.go | 68 ++++++++ cmds/gui-example/Makefile | 5 + cmds/gui-example/demo-window.go | 105 ++++++++++++ cmds/gui-example/main.go | 68 ++++++++ cmds/gui-example/os.go | 99 +++++++++++ debug-window.go | 355 ++++++++++++++++++++++++++++++++++++++++ debug.go | 66 +++++++- demo-window-andlabs-ui.go | 84 ++++++++++ demo-window.go | 28 ++++ doc.go | 72 ++++++++ entry.go | 40 +++-- example_test.go | 45 +++++ find.go | 156 ++++++++++++++++++ gui-example/Makefile | 5 - gui-example/main.go | 43 ----- gui.go | 8 + main.go | 28 +--- new-structs.go | 249 ++++++++++++++++++++++++++-- structs.go | 159 +++++++----------- table.go | 12 +- tableCallbacks.go | 3 +- window-debug.go | 230 -------------------------- window-template.go | 72 -------- window.go | 250 +++++++++++++--------------- 30 files changed, 1803 insertions(+), 664 deletions(-) create mode 100644 cmds/gui-demo/Makefile create mode 100644 cmds/gui-demo/demo-window.go create mode 100644 cmds/gui-demo/main.go create mode 100644 cmds/gui-example/Makefile create mode 100644 cmds/gui-example/demo-window.go create mode 100644 cmds/gui-example/main.go create mode 100644 cmds/gui-example/os.go create mode 100644 debug-window.go create mode 100644 demo-window-andlabs-ui.go create mode 100644 demo-window.go create mode 100644 doc.go create mode 100644 example_test.go create mode 100644 find.go delete mode 100644 gui-example/Makefile delete mode 100644 gui-example/main.go delete mode 100644 window-debug.go delete mode 100644 window-template.go (limited to 'debug.go') diff --git a/.gitignore b/.gitignore index bb1e72d..1445c95 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp -gui-example/gui-example +cmds/gui-example/gui-example +cmds/gui-demo/gui-demo diff --git a/area.go b/area.go index 0cc7531..7c42c6c 100644 --- a/area.go +++ b/area.go @@ -107,10 +107,10 @@ func (ah GuiArea) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) { return false } -func ShowTextBox(box *GuiBox, newText *ui.AttributedString, custom func(*GuiButton), name string) { +func (b *GuiBox) ShowTextBox(newText *ui.AttributedString, custom func(*GuiButton), name string) { log.Println("ShowTextBox() START") - gw := box.Window + gw := b.Window if (gw == nil) { log.Println("ShowTextBox() ERROR gw = nil") return @@ -127,10 +127,10 @@ func ShowTextBox(box *GuiBox, newText *ui.AttributedString, custom func(*GuiButt */ // TODO: allow padded & axis here - box.UiBox.SetPadded(true) + b.UiBox.SetPadded(true) // add(gw.BoxMap["MAINBOX"], newbox) - makeGenericArea(box, newText, custom) - box.UiBox.Append(box.Window.Area.UiArea, true) + makeGenericArea(b, newText, custom) + b.UiBox.Append(b.Window.Area.UiArea, true) } diff --git a/box.go b/box.go index 2640742..7a61f55 100644 --- a/box.go +++ b/box.go @@ -1,6 +1,7 @@ package gui import "log" +import "os" // import "reflect" import "github.com/andlabs/ui" @@ -34,6 +35,7 @@ func add(box *GuiBox, newbox *GuiBox) { 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") @@ -41,33 +43,77 @@ func add(box *GuiBox, newbox *GuiBox) { } 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.UiBox == nil) { - log.Println("\tgui.add() ERROR box.UiBox == nil") - panic("crap") + if (box.node == nil) { + box.Dump() + panic("gui.add() ERROR box.node == nil") } + if (newbox.UiBox == nil) { - log.Println("\tgui.add() ERROR newbox.UiBox == nil") - panic("crap") + 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 } - // log.Println("\tgui.add() newbox.UiBox == ", newbox.UiBox.GetParent()) - // spew.Dump(newbox.UiBox) 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 NewBox(box *GuiBox, axis int, name string) *GuiBox { - log.Println("VerticalBox START") +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 = box.Window + newbox.Window = b.Window newbox.Name = name var uiBox *ui.Box @@ -78,13 +124,18 @@ func NewBox(box *GuiBox, axis int, name string) *GuiBox { } uiBox.SetPadded(true) newbox.UiBox = uiBox - add(box, newbox) + 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"] @@ -134,3 +185,40 @@ func VerticalBreak(box *GuiBox) { tmp := ui.NewVerticalSeparator() box.UiBox.Append(tmp, false) } + +func (n *Node) AddComboBox(title string, s ...string) *Node { + box := n.uiBox + if (box == nil) { + return n + } + + ecbox := ui.NewEditableCombobox() + + for id, name := range s { + log.Println("Adding Combobox Entry:", id, name) + ecbox.Append(name) + } + + ecbox.OnChanged(func(*ui.EditableCombobox) { + test := ecbox.Text() + log.Println("node.Name = '" + n.Name + "' text for '" + title + "' is now: '" + test + "'") + }) + + 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.uiText == nil) { + return "" + } + ecbox := n.uiText + return ecbox.Text() +} diff --git a/button.go b/button.go index 825b79b..8ad0a3b 100644 --- a/button.go +++ b/button.go @@ -1,10 +1,12 @@ package gui import "log" +import "reflect" import "github.com/andlabs/ui" import _ "github.com/andlabs/ui/winmanifest" // import "github.com/davecgh/go-spew/spew" + // This is the default mouse click handler // Every mouse click that hasn't been assigned to // something specific will fall into this routine @@ -50,6 +52,60 @@ func guiButtonClick(button *GuiButton) { } } +func (n *Node) AddButton(name string, custom func(*Node)) *Node { + if (n.uiBox == nil) { + log.Println("gui.Node.AppendButton() filed node.UiBox == nil") + return n + } + button := ui.NewButton(name) + 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) + newNode.uiButton = button + newNode.custom = custom + + button.OnClicked(func(*ui.Button) { + log.Println("gui.AppendButton() Button Clicked. Running custom()") + custom(newNode) + }) + // panic("AppendButton") + // time.Sleep(3 * time.Second) + return newNode +} + +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) + + 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 + + Data.AllButtons = append(Data.AllButtons, newB) + + box.Append(newB.B, false) + return newNode +} + func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton { newUiB := ui.NewButton(name) newUiB.OnClicked(defaultButtonClick) diff --git a/cmds/gui-demo/Makefile b/cmds/gui-demo/Makefile new file mode 100644 index 0000000..2dbc808 --- /dev/null +++ b/cmds/gui-demo/Makefile @@ -0,0 +1,5 @@ +run: build + ./gui-demo + +build: + GO111MODULE="off" go build diff --git a/cmds/gui-demo/demo-window.go b/cmds/gui-demo/demo-window.go new file mode 100644 index 0000000..fd8e8f4 --- /dev/null +++ b/cmds/gui-demo/demo-window.go @@ -0,0 +1,33 @@ +package main + +import "log" + +import "git.wit.org/wit/gui" + +func demoClick (n *gui.Node) { + log.Println("demoClick() Dumping node:") + n.Dump() +} + +func addDemoTab(n *gui.Node, title string) { + newNode := n.AddTab(title, nil) + if (gui.Config.Debug) { + newNode.Dump() + } + newNode.ListChildren(false) + + groupNode1 := newNode.AddGroup("group 1") + groupNode1.AddComboBox("demoCombo1", "foo", "bar", "stuff") + groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff") + + groupNode1.Dump() + + butNode1 := groupNode1.AddButton("button1", demoClick) + butNode1.Dump() + + butNode2 := groupNode1.AddButton("button2", demoClick) + butNode2.Dump() + + groupNode2 := newNode.AddGroup("group 2") + groupNode2.AddComboBox("demoCombo2", "more 1", "more 2", "more 3") +} diff --git a/cmds/gui-demo/main.go b/cmds/gui-demo/main.go new file mode 100644 index 0000000..8eae878 --- /dev/null +++ b/cmds/gui-demo/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "log" + "os" + "time" + + "git.wit.org/wit/gui" +) + +// This initializes the first window +// +// Then starts a goroutine to demonstrate how to +// inject things into the GUI +func main() { + log.Println("Starting my Control Panel") + + go gui.Main(initGUI) + + watchGUI() +} + +// This initializes the first window +func initGUI() { + gui.Config.Title = "WIT GUI Window Demo 1" + gui.Config.Width = 640 + gui.Config.Height = 480 + gui.Config.Exit = myExit + node1 := gui.NewWindow() + addDemoTab(node1, "A Simple Tab Demo") + + gui.Config.Title = "WIT GUI Window Demo 2" + gui.Config.Width = 640 + gui.Config.Height = 240 + gui.Config.Exit = myExit + node2 := gui.NewWindow() + node2.DemoAndlabsUiTab("A Simple andlabs/ui Tab Demo") +} + +// This demonstrates how to properly interact with the GUI +// You can not involke the GUI from external goroutines in most cases. +func watchGUI() { + var i = 1 + for { + log.Println("Waiting", i, "seconds") + i += 1 + time.Sleep(1 * time.Second) + if i == 4 { + log.Println("Opening a Debug Window via the gui.Queue()") + gui.Config.Width = 800 + gui.Config.Height = 300 + gui.Config.Exit = myDebugExit + gui.Queue(gui.DebugWindow) + } + } +} + +func myExit(n *gui.Node) { + log.Println() + log.Println("Entered myExit() on node.Name =", n.Name) + log.Println() + os.Exit(0) +} + +func myDebugExit(n *gui.Node) { + log.Println("Entered myDebugExit() on node.Name =", n.Name) + log.Println("Don't actually os.Exit()") +} diff --git a/cmds/gui-example/Makefile b/cmds/gui-example/Makefile new file mode 100644 index 0000000..5028ebd --- /dev/null +++ b/cmds/gui-example/Makefile @@ -0,0 +1,5 @@ +run: build + ./gui-example + +build: + GO111MODULE="off" go build diff --git a/cmds/gui-example/demo-window.go b/cmds/gui-example/demo-window.go new file mode 100644 index 0000000..993900d --- /dev/null +++ b/cmds/gui-example/demo-window.go @@ -0,0 +1,105 @@ +package main + +import "log" +import "reflect" + +import "git.wit.org/wit/gui" + +import "github.com/davecgh/go-spew/spew" + +func demoClick (n *gui.Node) { + log.Println("demoClick() Dumping node:") + n.Dump() +} + +var username = "jcarr" +var hostname = "fire" + +func newClick (n *gui.Node) { + var tmp []string + junk := "ssh -v " + username + "@" + hostname + log.Println("junk = " , junk) + xterm(junk) + log.Println("tmp = " , reflect.ValueOf(tmp).Kind()) + // spew.Dump(tmp) +} + +func addDemoTab(n *gui.Node, title string) { + newNode := n.AddTab(title, nil) + if (gui.Config.Debug) { + newNode.Dump() + } + newNode.ListChildren(false) + + groupNode1 := newNode.AddGroup("group 1") + cbNode := groupNode1.AddComboBox("username", "root", "jcarr", "hugo") + cbNode.OnChanged(func () { + username = cbNode.GetText() + }) + groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff") + + groupNode1.Dump() + + butNode1 := groupNode1.AddButton("button1", demoClick) + butNode1.Dump() + + butNode2 := groupNode1.AddButton("button2", newClick) + butNode2.Dump() + + groupNode2 := newNode.AddGroup("group 2") + groupNode2.AddComboBox("demoCombo2", "more 1", "more 2", "more 3") + + gNode := newNode.AddGroup("domU") + makeSSHbutton(gNode, "hugo@www", "www.wit.org") + makeSSHbutton(gNode, "check.lab", "check.lab.wit.org") + makeSSHbutton(gNode, "gobuild.lab", "gobuild.lab.wit.org") + makeSSHbutton(gNode, "gobuild2.lab", "gobuild2.lab.wit.org") + +/////////////////////////////// Column DNS //////////////////////////////// + gNode = newNode.AddGroup("dns") + makeSSHbutton(gNode, "bind.wit.org", "bind.wit.org") + makeSSHbutton(gNode, "ns1.wit.com", "ns1.wit.com") + makeSSHbutton(gNode, "ns2.wit.com", "ns2.wit.com") + makeSSHbutton(gNode, "coredns", "coredns.lab.wit.org") + +/////////////////////////////// PHYS 530 ////////////////////////////////// + gNode = newNode.AddGroup("phys 530") + // makeXtermButton(gNode, "openwrt", "SUBDOMAIN", "ssh -4 -v root@openwrt") + gNode.AddButton("openwrt", func (*gui.Node) { + stuff := "ssh -4 -v root@openwrt" + xterm(stuff) + }) + makeSSHbutton (gNode, "mirrors", "mirrors.wit.org") + makeSSHbutton (gNode, "node004", "node004.lab.wit.org") + makeSSHbutton (gNode, "lenovo-z70", "lenovo-z70.lab.wit.org") + +/////////////////////////////// PHYS 522 ////////////////////////////////// + gNode = newNode.AddGroup("phys 522") + // makeXtermButton(gNode, "openwrt2", "SUBDOMAIN", "ssh -4 -v root@openwrt2") + gNode.AddButton("openwrt2", func (*gui.Node) { + stuff := "ssh -4 -v root@openwrt2" + xterm(stuff) + }) + makeSSHbutton (gNode, "fire.lab", "fire.lab.wit.org") + makeSSHbutton (gNode, "predator", "predator.lab.wit.org") + +/////////////////////////////// FLOAT ///////////////////////////////////// + gNode = newNode.AddGroup("float") + makeSSHbutton(gNode, "root@asus-n501vw", "asus-n501vw.lab.wit.org") +} + +func makeSSHbutton (n *gui.Node, name string, hostname string) { + bNode := n.AddButton(name, func (*gui.Node) { + var tmp []string + if (username == "") { + username = "root" + } + junk := "ssh -v " + username + "@" + hostname + log.Println("junk = " , junk) + log.Println("username = '" + username + "'") + xterm(junk) + log.Println("tmp = " , reflect.ValueOf(tmp).Kind()) + spew.Dump(tmp) + }) + bNode.Dump() +} diff --git a/cmds/gui-example/main.go b/cmds/gui-example/main.go new file mode 100644 index 0000000..8eae878 --- /dev/null +++ b/cmds/gui-example/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "log" + "os" + "time" + + "git.wit.org/wit/gui" +) + +// This initializes the first window +// +// Then starts a goroutine to demonstrate how to +// inject things into the GUI +func main() { + log.Println("Starting my Control Panel") + + go gui.Main(initGUI) + + watchGUI() +} + +// This initializes the first window +func initGUI() { + gui.Config.Title = "WIT GUI Window Demo 1" + gui.Config.Width = 640 + gui.Config.Height = 480 + gui.Config.Exit = myExit + node1 := gui.NewWindow() + addDemoTab(node1, "A Simple Tab Demo") + + gui.Config.Title = "WIT GUI Window Demo 2" + gui.Config.Width = 640 + gui.Config.Height = 240 + gui.Config.Exit = myExit + node2 := gui.NewWindow() + node2.DemoAndlabsUiTab("A Simple andlabs/ui Tab Demo") +} + +// This demonstrates how to properly interact with the GUI +// You can not involke the GUI from external goroutines in most cases. +func watchGUI() { + var i = 1 + for { + log.Println("Waiting", i, "seconds") + i += 1 + time.Sleep(1 * time.Second) + if i == 4 { + log.Println("Opening a Debug Window via the gui.Queue()") + gui.Config.Width = 800 + gui.Config.Height = 300 + gui.Config.Exit = myDebugExit + gui.Queue(gui.DebugWindow) + } + } +} + +func myExit(n *gui.Node) { + log.Println() + log.Println("Entered myExit() on node.Name =", n.Name) + log.Println() + os.Exit(0) +} + +func myDebugExit(n *gui.Node) { + log.Println("Entered myDebugExit() on node.Name =", n.Name) + log.Println("Don't actually os.Exit()") +} diff --git a/cmds/gui-example/os.go b/cmds/gui-example/os.go new file mode 100644 index 0000000..ce5db8d --- /dev/null +++ b/cmds/gui-example/os.go @@ -0,0 +1,99 @@ +package main + +import "log" +import "strings" +import "os" +import "os/exec" +import "io/ioutil" +import "errors" +// import "bufio" + +// import "github.com/davecgh/go-spew/spew" + +/* +import "time" +import "runtime" +import "runtime/debug" +import "runtime/pprof" + +import "git.wit.org/wit/gui" +import "git.wit.org/wit/shell" +import "github.com/gobuffalo/packr" +*/ + +func runSimpleCommand(s string) { + cmd := strings.TrimSpace(s) // this is like 'chomp' in perl + cmd = strings.TrimSuffix(cmd, "\n") // this is like 'chomp' in perl + cmdArgs := strings.Fields(cmd) + runLinuxCommand(cmdArgs) +} + +var geom string = "120x30+500+500" + +func xterm(cmd string) { + var tmp []string + var argsXterm = []string{"nohup", "xterm", "-geometry", geom} + tmp = append(argsXterm, "-hold", "-e", cmd) + log.Println("xterm cmd=", cmd) + go runCommand(tmp) +} + +func runCommand(cmdArgs []string) { + log.Println("runCommand() START", cmdArgs) + process := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...) + // process := exec.Command("xterm", "-e", "ping localhost") + log.Println("runCommand() process.Start()") + process.Start() + log.Println("runCommand() process.Wait()") + err := process.Wait() + lookupError(err) + log.Println("runCommand() NEED TO CHECK THE TIME HERE TO SEE IF THIS WORKED") + log.Println("runCommand() OTHERWISE INFORM THE USER") + log.Println("runCommand() END", cmdArgs) +} + +func lookupError(err error) { + var ( + ee *exec.ExitError + pe *os.PathError + ) + + if errors.As(err, &ee) { + log.Println("ran, but non-zero exit code =", ee.ExitCode()) // ran, but non-zero exit code + } else if errors.As(err, &pe) { + log.Printf("os.PathError = %v", pe) // "no such file ...", "permission denied" etc. + } else if err != nil { + log.Printf("something really bad happened general err = %v", err) // something really bad happened! + if exitError, ok := err.(*exec.ExitError); ok { + log.Printf("exitError.ExitCode() is %d\n", exitError.ExitCode()) + } + } else { + log.Println("success! // ran without error (exit code zero)") + } +} + +func runLinuxCommand(cmdArgs []string) (string, error) { + process := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...) + + process.Stdin = os.Stdin + process.Stderr = os.Stderr + + stdOut, err := process.StdoutPipe() + if err != nil { + return "", err + } + + if err := process.Start(); err != nil { + return "", err + } + + bytes, err := ioutil.ReadAll(stdOut) + if err != nil { + return "", err + } + err = process.Wait() + lookupError(err) + + log.Println(string(bytes)) + return string(bytes), err +} diff --git a/debug-window.go b/debug-window.go new file mode 100644 index 0000000..19f276d --- /dev/null +++ b/debug-window.go @@ -0,0 +1,355 @@ +package gui + +import ( + "log" + // "fmt" + "strconv" + + "github.com/andlabs/ui" + _ "github.com/andlabs/ui/winmanifest" + "github.com/davecgh/go-spew/spew" +) + +var names = make([]string, 100) +var nodeNames = make([]string, 100) + +func DebugWindow() { + Config.Title = "DebugWindow()" + node := NewWindow() + node.DebugTab("WIT GUI Debug Tab") +} + +// TODO: remove this crap +// What does this actually do? +// It populates the nodeNames in a map. No, not a map, an array. +// What is the difference again? (other than one being in order and a predefined length) +func addNodeName(c *ui.Combobox, s string, id string) { + c.Append(s) + nodeNames[y] = id + y = y + 1 +} + +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() + + for name, node := range Data.NodeMap { + if (Config.Debug) { + log.Println("range Data.NodeMap() name =", name) + } + tmp := node.id + " (" + name + ")" + addNodeName(nodeCombo, tmp, node.id) + } + nodeCombo.SetSelected(0) + + nodeBox.Append(nodeCombo, false) + + nodeCombo.OnSelected(func(*ui.Combobox) { + y := nodeCombo.Selected() + log.Println("y =", y) + log.Println("nodeNames[y] =", nodeNames[y]) + node := Data.findId(nodeNames[y]) + if (node != nil) { + node.Dump() + } + }) + + ///////////////////////////////////////////////////// + vbox = addGroup(hbox, "Node Debug") + + n1 := addButton(vbox, "Data.DumpNodeMap()") + n1.OnClicked(func(*ui.Button) { + Data.DumpNodeMap() + }) + + n1 = addButton(vbox, "Data.ListChildren(false)") + n1.OnClicked(func(*ui.Button) { + Data.ListChildren(false) + }) + + n1 = addButton(vbox, "Data.ListChildren(true)") + n1.OnClicked(func(*ui.Button) { + Data.ListChildren(true) + }) + + n1 = addButton(vbox, "Node.Dump()") + n1.OnClicked(func(*ui.Button) { + y := nodeCombo.Selected() + log.Println("y =", y) + log.Println("nodeNames[y] =", nodeNames[y]) + node := Data.findId(nodeNames[y]) + if (node != nil) { + node.Dump() + } + }) + + n1 = addButton(vbox, "Node.ListChildren(false)") + n1.OnClicked(func(*ui.Button) { + y := nodeCombo.Selected() + log.Println("y =", y) + log.Println("nodeNames[y] =", nodeNames[y]) + node := Data.findId(nodeNames[y]) + if (node != nil) { + node.ListChildren(false) + } + }) + + n1 = addButton(vbox, "Node.ListChildren(true)") + n1.OnClicked(func(*ui.Button) { + y := nodeCombo.Selected() + log.Println("y =", y) + log.Println("nodeNames[y] =", nodeNames[y]) + node := Data.findId(nodeNames[y]) + if (node != nil) { + node.ListChildren(true) + } + }) + + n1 = addButton(vbox, "Node.AddDebugTab") + n1.OnClicked(func(*ui.Button) { + y := nodeCombo.Selected() + log.Println("y =", y) + log.Println("nodeNames[y] =", nodeNames[y]) + node := Data.findId(nodeNames[y]) + if (node != nil) { + node.DebugTab("added this DebugTab") + } + }) + + n1 = addButton(vbox, "Node.DemoAndlabsUiTab") + n1.OnClicked(func(*ui.Button) { + y := nodeCombo.Selected() + log.Println("y =", y) + log.Println("nodeNames[y] =", nodeNames[y]) + node := Data.findId(nodeNames[y]) + if (node != nil) { + node.DemoAndlabsUiTab("ran gui.AddDemoAndlabsUiTab() " + strconv.Itoa(Config.counter)) + } + }) + + return hbox +} + +// TODO: remove this crap +var x int = 0 +var y int = 0 + +// TODO: remove this crap +func addName(c *ui.Combobox, s string) { + c.Append(s) + names[x] = s + x = x + 1 +} + +func addGroup(b *ui.Box, name string) *ui.Box { + group := ui.NewGroup(name) + group.SetMargined(true) + b.Append(group, true) + + vbox := ui.NewVerticalBox() + vbox.SetPadded(true) + group.SetChild(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 { + button := ui.NewButton(name) + + button.OnClicked(func(*ui.Button) { + log.Println("Should do something here") + }) + + box.Append(button, false) + return button +} + +func (n *Node) DebugTab(title string) { + newNode := n.AddTab(title, makeWindowDebug()) + if (Config.DebugNode) { + newNode.Dump() + } + tabSetMargined(newNode.uiTab) +} + +// This sets _all_ the tabs to Margin = true +// +// TODO: do proper tab tracking (will be complicated). low priority +func tabSetMargined(tab *ui.Tab) { + if (Config.DebugTabs) { + log.Println("tabSetMargined() IGNORE THIS") + } + c := tab.NumPages() + for i := 0; i < c; i++ { + if (Config.DebugTabs) { + log.Println("tabSetMargined() i =", i) + } + tab.SetMargined(i, true) + } +} diff --git a/debug.go b/debug.go index 8c1e947..0b0baa4 100644 --- a/debug.go +++ b/debug.go @@ -8,14 +8,13 @@ import ( "github.com/davecgh/go-spew/spew" ) -// import "reflect" - -// import "github.com/andlabs/ui" -// import _ "github.com/andlabs/ui/winmanifest" - -// -// Dump out debugging information every 4 seconds +// WatchGUI() opens a goroutine // +// From that goroutine, it dumps out debugging information every 4 seconds +/* + TODO: add configuration triggers on what to dump out + TODO: allow this to be sent to /var/log, syslogd, systemd's journalctl, etc +*/ func WatchGUI() { count := 0 @@ -32,6 +31,12 @@ 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) @@ -106,3 +111,50 @@ func addTableTab() { log.Println("Sleep for 1 second, then try to add new tabs") time.Sleep(1 * time.Second) } + +func (dn *GuiData) DumpNodeMap() { + log.Println("DebugDataNodeMap():") + for name, node := range dn.NodeMap { + log.Println("\tNode =", node.id, node.Width, node.Height, name) + if (node.children == nil) { + log.Println("\t\tNo children") + } else { + log.Println("\t\tHas children:", node.children) + } + // node.SetName("yahoo") + // log.Println("\tData.NodeMap node =", node) + } +} + +/* +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") + return + } + log.Println("gui.Data.ListChildren() Data.NodeMap:") + for name, node := range Data.NodeMap { + log.Println("\tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name) + if (dump == true) { + node.Dump() + } + node.ListChildren(dump) + } +} diff --git a/demo-window-andlabs-ui.go b/demo-window-andlabs-ui.go new file mode 100644 index 0000000..e11ffe9 --- /dev/null +++ b/demo-window-andlabs-ui.go @@ -0,0 +1,84 @@ +package gui + +import "log" +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +// This will create a tab in a window using direct +// calls to andlabs/ui. This can be used to bypass +// the obvuscation added in this package if it is desired +// or needed. +func (n *Node) DemoAndlabsUiTab(title string) { + newNode := n.AddTab(title, makeAndlabsUiTab()) + if (Config.DebugNode) { + newNode.Dump() + } + tabSetMargined(newNode.uiTab) +} + +func makeAndlabsUiTab() *ui.Box { + hbox := ui.NewHorizontalBox() + hbox.SetPadded(true) + + group := ui.NewGroup("Numbers") + group.SetMargined(true) + hbox.Append(group, true) + + vbox := ui.NewVerticalBox() + vbox.SetPadded(true) + group.SetChild(vbox) + + spinbox := ui.NewSpinbox(47, 100) + slider := ui.NewSlider(21, 100) + pbar := ui.NewProgressBar() + + spinbox.OnChanged(func(*ui.Spinbox) { + slider.SetValue(spinbox.Value()) + pbar.SetValue(spinbox.Value()) + }) + slider.OnChanged(func(*ui.Slider) { + spinbox.SetValue(slider.Value()) + pbar.SetValue(slider.Value()) + }) + vbox.Append(spinbox, false) + vbox.Append(slider, false) + vbox.Append(pbar, false) + + ip := ui.NewProgressBar() + ip.SetValue(-1) + vbox.Append(ip, false) + + group = ui.NewGroup("Lists") + group.SetMargined(true) + hbox.Append(group, true) + + vbox = ui.NewVerticalBox() + vbox.SetPadded(true) + group.SetChild(vbox) + + cbox := ui.NewCombobox() + cbox.Append("Combobox Item 1") + cbox.Append("Combobox Item 2") + cbox.Append("Combobox Item 3") + vbox.Append(cbox, false) + + ecbox := ui.NewEditableCombobox() + ecbox.Append("Editable Item 1") + ecbox.Append("Editable Item 2") + ecbox.Append("Editable Item 3") + vbox.Append(ecbox, false) + + ecbox.OnChanged(func(*ui.EditableCombobox) { + log.Println("test") + test := ecbox.Text() + log.Println("test=", test) + }) + + rb := ui.NewRadioButtons() + rb.Append("Radio Button 1") + rb.Append("Radio Button 2") + rb.Append("Radio Button 3") + vbox.Append(rb, false) + + return hbox +} diff --git a/demo-window.go b/demo-window.go new file mode 100644 index 0000000..16566c4 --- /dev/null +++ b/demo-window.go @@ -0,0 +1,28 @@ +package gui + +// import "log" +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +var mybox *ui.Box + +func (n *Node) AddGroup(title string) *Node { + if (n == nil) { + return nil + } + hbox := n.uiBox + if (hbox == nil) { + return n + } + group := ui.NewGroup(title) + group.SetMargined(true) + hbox.Append(group, true) + + vbox := ui.NewVerticalBox() + vbox.SetPadded(true) + group.SetChild(vbox) + + newNode := n.AddNode(title) + newNode.uiBox = vbox + return newNode +} diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..2b324c9 --- /dev/null +++ b/doc.go @@ -0,0 +1,72 @@ +/* +Package wit/gui implements a abstraction layer for Go visual elements in +a cross platform way. Right now, this abstraction is built on top of +the GUI toolkit 'andlabs/ui' which does the cross platform support. + +A quick overview of the features, some general design guidelines +and principles for how this package should generally work: + + * GUI elements are stored in a tree of nodes + * When in doubt, it's ok to guess. We will return something close. + * It tries to make your code simple + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + + package main + + import ( + "git.wit.org/wit/gui" + ) + + func main() { + gui.Main(initGUI) + } + + // This initializes the first window + func initGUI() { + gui.Config.Title = "WIT GUI Window 1" + gui.Config.Width = 640 + gui.Config.Height = 480 + node1 := gui.NewWindow() + addDemoTab(node1, "A Simple Tab Demo") + } + + func addDemoTab(n *gui.Node, title string) { + newNode := n.AddTab(title, nil) + + groupNode1 := newNode.AddGroup("group 1") + groupNode1.AddComboBox("demoCombo2", "more 1", "more 2", "more 3") + } + +Configuration Options + +Configuration of the GUI is handled by fields in the ConfigType type. For +convenience, all of the top-level functions use a global state available +via the gui.Config global. + +The following configuration options are available: + * Width + When creating a new window, this is the width + + * Height + When creating a new window, this is the height + + * Debug + When 'true' log more output + +GUI Usage + +Errors + +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 diff --git a/entry.go b/entry.go index d7f31c9..c10b7d0 100644 --- a/entry.go +++ b/entry.go @@ -13,26 +13,46 @@ func NewLabel(box *GuiBox, text string) { box.Append(ui.NewLabel(text), false) } -func GetText(box *GuiBox, name string) string { - if (box == nil) { - log.Println("gui.GetText() ERROR box == nil") - return "" - } - if (box.Window.EntryMap == nil) { +func (n *Node) NewLabel(text string) *Node { + // make new node here + // 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(box.Window.EntryMap) - if (box.Window.EntryMap[name] == nil) { + spew.Dump(b.Window.EntryMap) + if (b.Window.EntryMap[name] == nil) { log.Println("gui.GetText() ERROR box.Window.EntryMap[", name, "] == nil ") return "" } - e := box.Window.EntryMap[name] + 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) { + n.uiText.SetText(value) + return nil + } + if (n.uiButton != nil) { + n.uiButton.SetText(value) + return nil + } + return nil +} + func SetText(box *GuiBox, name string, value string) error { if (box == nil) { return fmt.Errorf("gui.SetText() ERROR box == nil") @@ -42,7 +62,7 @@ func SetText(box *GuiBox, name string, value string) error { } spew.Dump(box.Window.EntryMap) if (box.Window.EntryMap[name] == nil) { - return fmt.Errorf("gui.SetText() ERROR 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()) diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..f65cad1 --- /dev/null +++ b/example_test.go @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gui_test + +import ( + "git.wit.org/wit/gui" +) + +// This example demonstrates how to create a NewWindow() +// +// Interacting with a GUI in a cross platform fashion adds some +// unusual problems. To obvuscate those, andlabs/ui starts a +// goroutine that interacts with the native gui toolkits +// on the Linux, MacOS, Windows, etc. +// +// Because of this oddity, to initialize a new window, the +// function is not passed any arguements and instead passes +// the information via the Config type. +// +func ExampleNewWindow() { + // Define the name and size + gui.Config.Title = "WIT GUI Window 1" + gui.Config.Width = 640 + gui.Config.Height = 480 + + // Create the Window + gui.NewWindow() + + // Output: + // You get a window +} diff --git a/find.go b/find.go new file mode 100644 index 0000000..e046161 --- /dev/null +++ b/find.go @@ -0,0 +1,156 @@ +package gui + +import ( + "log" + "os" + + "github.com/andlabs/ui" + _ "github.com/andlabs/ui/winmanifest" +// "github.com/davecgh/go-spew/spew" +) + +func (n *Node) FindTab() *ui.Tab { + return n.uiTab +} + +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") + return nil + } + log.Println("gui.FindNode() searching Data.NodeMap:") + for id, node := range Data.NodeMap { + log.Println("\tData.NodeMap name =", node.Width, node.Height, id) + node.Dump() + if (name == node.Name) { + return node + } + newNode := findByName(node, name) + if (newNode != nil) { + return newNode + } + log.Println("gui.FindNode() could not find node name =", name) + os.Exit(-1) + } + log.Println("gui.FindNode() could not find node name =", name) + return nil +} + +func (dn *GuiData) findId(id string) *Node { + if Data.NodeMap == nil { + log.Println("gui.Data.findId() map == nil") + return nil + } + // log.Println("Dumping Data.NodeMap:") + for name, node := range Data.NodeMap { + // log.Println("\tData.NodeMap name =", node.id, node.Width, node.Height, name) + if (id == node.id) { + log.Println("\tgui.Data.findId() found node =", node.id, node.Width, node.Height, name) + return node + } + // TODO: fix // Oct 9 + // node.findId(id) + } + return nil +} + +func findByIdDFS(node *Node, id string) *Node { + log.Println("findByIdDFS()", id, node) + node.Dump() + if node.id == id { + log.Println("Found node id =", id, node) + return node + } + + if len(node.children) > 0 { + for _, child := range node.children { + newNode := findByIdDFS(child, id) + if (newNode != nil) { + return newNode + } + } + } + return nil +} + +func findByName(node *Node, name string) *Node { + log.Println("findByName()", name, node) + node.Dump() + if node.Name == name { + log.Println("findByName() Found node name =", name, node) + return node + } + + if len(node.children) > 0 { + for _, child := range node.children { + newNode := findByName(child, name) + if (newNode != nil) { + return newNode + } + } + } + return nil +} diff --git a/gui-example/Makefile b/gui-example/Makefile deleted file mode 100644 index 5028ebd..0000000 --- a/gui-example/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -run: build - ./gui-example - -build: - GO111MODULE="off" go build diff --git a/gui-example/main.go b/gui-example/main.go deleted file mode 100644 index 1ff286d..0000000 --- a/gui-example/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "log" - "os" - "time" - - "git.wit.org/wit/gui" -) - -func customExit(gw *gui.GuiWindow) { - log.Println("Should Exit Here") - os.Exit(0) -} - -func main() { - log.Println("starting my Control Panel") - - gui.Config.Width = 800 - gui.Config.Height = 300 - gui.Config.Exit = customExit - - go gui.Main(initGUI) - - watchGUI() -} - -func initGUI() { - gui.NewWindow("jcarr start", 640, 480) -} - -func watchGUI() { - var i = 1 - for { - log.Println("Waiting for customExit()", i) - i += 1 - time.Sleep(time.Second) - if i == 3 { - log.Println("Sending ExampleWindow to gui.Queue()") - gui.Queue(gui.DebugWindow) - } - } -} diff --git a/gui.go b/gui.go index 97e3c24..4174133 100644 --- a/gui.go +++ b/gui.go @@ -18,6 +18,14 @@ func init() { 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 } func GuiInit() { diff --git a/main.go b/main.go index 09d105f..70e0e65 100644 --- a/main.go +++ b/main.go @@ -12,7 +12,7 @@ func Main(f func()) { ui.Main(f) } -// Other goroutines must use this +// Other goroutines must use this to access the GUI // // You can not acess / process the GUI thread directly from // other goroutines. This is due to the nature of how @@ -23,28 +23,12 @@ func Queue(f func()) { ui.QueueMain(f) } +/* func ExampleWindow() { log.Println("START gui.ExampleWindow()") - title := "Test Window" - box := InitWindow(nil, title, 0) - window := box.Window - log.Println("box =", box) - log.Println("window =", window) - box.AddDebugTab("jcarr Debug") - - window.UiWindow.Show() -} - -func DebugWindow() { - log.Println("START gui.ExampleWindow()") - - title := "Debug Window" - box := InitWindow(nil, title, 0) - window := box.Window - log.Println("box =", box) - log.Println("window =", window) - box.AddDebugTab("jcarr Debug") - - window.UiWindow.Show() + Config.Title = "ExampleWindow" + node := NewWindow() + node.AddDebugTab("jcarr Debug") } +*/ diff --git a/new-structs.go b/new-structs.go index 0fa326a..4f9989e 100644 --- a/new-structs.go +++ b/new-structs.go @@ -2,12 +2,42 @@ package gui import ( "log" + "fmt" +// "reflect" + + // "github.com/davecgh/go-spew/spew" "github.com/andlabs/ui" _ "github.com/andlabs/ui/winmanifest" ) +type Element int + // https://ieftimov.com/post/golang-datastructures-trees/ +const ( + Unknown Element = iota + Window + Tab + Box + Label + Combo +) + +func (s Element) String() string { + switch s { + case Window: + return "window" + case Tab: + return "tab" + case Box: + return "box" + case Label: + return "label" + case Combo: + return "combo" + } + return "unknown" +} type Node struct { id string @@ -15,32 +45,227 @@ type Node struct { Width int Height int - uiType *ui.Control + parent *Node children []*Node + + window *GuiWindow + box *GuiBox + custom func(*Node) + + uiControl *ui.Control + uiButton *ui.Button + uiWindow *ui.Window + uiTab *ui.Tab + uiBox *ui.Box + uiText *ui.EditableCombobox +} + +func (n *Node) Parent() *Node { + return n.parent +} + +func (n *Node) Window() *Node { + return n.parent +} + +func (n *Node) Dump() { + log.Println("gui.Node.Dump() id = ", n.id) + log.Println("gui.Node.Dump() Name = ", n.Name) + log.Println("gui.Node.Dump() Width = ", n.Width) + log.Println("gui.Node.Dump() Height = ", n.Height) + + if (n.parent == nil) { + log.Println("gui.Node.Dump() parent = nil") + } else { + log.Println("gui.Node.Dump() parent = ", n.parent.id) + } + 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() 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) + if (n.id == "") { + 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) - log.Println("n.uiType =", n.uiType) + if (n.uiWindow != nil) { + log.Println("node is a window. setting title =", name) + n.uiWindow.SetTitle(name) + return + } + log.Println("*ui.Control =", n.uiControl) return } -func (n Node) Append(child Node) { +func (n *Node) Append(child *Node) { // if (n.UiBox == nil) { // return // } - // n.uiType.Append(child, x) + n.children = append(n.children, child) + if (Config.Debug) { + log.Println("child node:") + child.Dump() + log.Println("parent node:") + n.Dump() + } + // time.Sleep(3 * time.Second) } -func findByIdDFS(node *Node, id string) *Node { - if node.id == id { - return node +func (n *Node) List() { + findByIdDFS(n, "test") +} + +var listChildrenParent *Node +var listChildrenDepth int = 0 + +func indentPrintln(depth int, format string, a ...interface{}) { + var tabs string + for i := 0; i < depth; i++ { + tabs = tabs + "\t" } - if len(node.children) > 0 { - for _, child := range node.children { - findByIdDFS(child, id) + // newFormat := tabs + strconv.Itoa(depth) + " " + format + newFormat := tabs + format + log.Println(newFormat, a) +} + +func (n *Node) ListChildren(dump bool) { + indentPrintln(listChildrenDepth, "\t", n.id, n.Width, n.Height, n.Name) + + if (dump == true) { + n.Dump() + } + if len(n.children) == 0 { + if (n.parent == nil) { + } else { + if (Config.DebugNode) { + log.Println("\t\t\tparent =",n.parent.id) + } + if (listChildrenParent != nil) { + if (Config.DebugNode) { + log.Println("\t\t\tlistChildrenParent =",listChildrenParent.id) + } + if (listChildrenParent.id != n.parent.id) { + log.Println("parent.child does not match child.parent") + panic("parent.child does not match child.parent") + } + } + } + if (Config.DebugNode) { + log.Println("\t\t", n.id, "has no children") + } + return + } + for _, child := range n.children { + // log.Println("\t\t", child.id, child.Width, child.Height, child.Name) + if (child.parent != nil) { + if (Config.DebugNode) { + log.Println("\t\t\tparent =",child.parent.id) + } + } else { + log.Println("\t\t\tno parent") + panic("no parent") + } + if (dump == true) { + child.Dump() } + if (Config.DebugNode) { + if (child.children == nil) { + log.Println("\t\t", child.id, "has no children") + } else { + log.Println("\t\t\tHas children:", child.children) + } + } + listChildrenParent = n + listChildrenDepth += 1 + child.ListChildren(dump) + listChildrenDepth -= 1 + } + return +} + +// The parent Node needs to be the raw Window +// The 'stuff' Node needs to be the contents of the tab +// +// This function should make a new node with the parent and +// the 'stuff' Node as a child +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 + + if (Config.DebugNode) { + fmt.Println("") + log.Println("parent:") + parent.Dump() + + fmt.Println("") + log.Println("newNode:") + newNode.Dump() + } + + 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 + return newNode + } + newNode.uiTab.Append(title, b.UiBox) + + return newNode +} + +func (n *Node) AddTab(title string, uiC *ui.Box) *Node { + parent := n + log.Println("gui.Node.AddTab() START name =", title) + if parent.uiWindow == nil { + parent.Dump() + 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 { + 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) + + if (uiC == nil) { + hbox := ui.NewHorizontalBox() + hbox.SetPadded(true) + uiC = hbox + } + tab.Append(title, uiC) + + newNode := parent.makeNode(title, 555, 600 + Config.counter) + newNode.uiTab = tab + newNode.uiBox = uiC + // panic("gui.AddTab() after makeNode()") + tabSetMargined(newNode.uiTab) + return newNode } diff --git a/structs.go b/structs.go index ad3307b..c15f4b7 100644 --- a/structs.go +++ b/structs.go @@ -19,11 +19,20 @@ var Data GuiData var Config GuiConfig type GuiConfig struct { + Title string Width int Height int - Debug bool - DebugTable bool - Exit func(*GuiWindow) + Exit func(*Node) + + Debug bool + DebugNode bool + DebugTabs bool + DebugTable bool + DebugWindow bool + + depth int + counter int // used to make unique ID's + prefix string } type GuiData struct { @@ -35,7 +44,10 @@ type GuiData struct { AllEntries []*GuiEntry WindowMap map[string]*GuiWindow - // Windows []*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 @@ -45,7 +57,6 @@ type GuiData struct { // andlabs/ui & andlabs/libui work AllButtons []*GuiButton buttonMap map[*ui.Button]*GuiButton - Nodes *Node } type GuiTab struct { @@ -87,11 +98,20 @@ type GuiWindow struct { 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 { @@ -99,121 +119,62 @@ type GuiBox struct { 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 (s GuiBox) SetTitle(title string) { +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 s.Window == nil { + if b.Window == nil { return } - if s.Window.UiWindow == nil { + if b.Window.UiWindow == nil { return } - s.Window.UiWindow.SetTitle(title) + b.Window.UiWindow.SetTitle(title) return } -func (s GuiBox) Append(child ui.Control, x bool) { - if s.UiBox == nil { - return +func (w *GuiWindow) SetNode(n *Node) { + if (w.node != nil) { + w.Dump() + panic("gui.SetNode() Error not nil") } - s.UiBox.Append(child, x) -} - -/* -func (w GuiWindow) InitWindow(title string) *GuiBox { - if w.UiWindow == nil { - log.Println("gui.InitBox() THIS SHOULD NEVER HAPPEN. Window doesn't exist", w) - return nil + w.node = n + if (w.node == nil) { + w.Dump() + panic("gui.SetNode() node == nil") } - tab := ui.NewTab() - w.UiWindow.SetChild(tab) - w.UiWindow.SetMargined(true) - - tab.Append(title, InitBlankWindow()) - tab.SetMargined(0, true) - - w.UiTab = tab - return nil } -*/ -func (s GuiBox) InitTab(title string, custom func() ui.Control) *ui.Tab { - if s.Window == nil { - return nil +func (b *GuiBox) SetNode(n *Node) { + if (b.node != nil) { + b.Dump() + panic("gui.SetNode() Error not nil") } - if s.Window.UiWindow == nil { - return nil + b.node = n + if (b.node == nil) { + b.Dump() + panic("gui.SetNode() node == nil") } - - window := s.Window.UiWindow - tab := ui.NewTab() - window.SetChild(tab) - window.SetMargined(true) - - tab.Append(title, custom()) - tab.SetMargined(0, true) - // tab.SetMargined(1, true) - - s.Window.UiTab = tab - return tab } -func (s GuiBox) AddTab(title string, custom ui.Control) *ui.Tab { - if s.Window == nil { - return nil - } - if s.Window.UiTab == nil { - return nil - } - - tab := s.Window.UiTab - - tab.Append(title, custom) - return tab -} - -func (s GuiBox) AddTab2(title string, custom ui.Control) *ui.Tab { - if s.Window == nil { - return nil - } - if s.Window.UiTab == nil { - return nil - } - - tab := s.Window.UiTab - tab.Append(title, custom) - return tab -} - -func (s GuiBox) AddBoxTab(title string) *GuiBox { - uiTab := s.AddTab2(title, InitBlankWindow()) - tabSetMargined(uiTab) - - var box *GuiBox - box = HardBox(s.Window, Xaxis, "jcarrAddBoxTab") - box.Window.UiTab = uiTab - return box -} - -func (s GuiBox) AddDemoTab(title string) { - uiTab := s.AddTab(title, makeWindowTemplate()) - tabSetMargined(uiTab) -} - -func (s GuiBox) AddDebugTab(title string) { - uiTab := s.AddTab(title, makeWindowDebug()) - tabSetMargined(uiTab) -} - -func tabSetMargined(tab *ui.Tab) { - c := tab.NumPages() - for i := 0; i < c; i++ { - log.Println("tabSetMargined() i =", i) - // tab.SetMargined(i, true) +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 diff --git a/table.go b/table.go index 87e69b2..92ae871 100644 --- a/table.go +++ b/table.go @@ -98,12 +98,12 @@ func InitColumns(mh *TableData, parts []TableColumnData) { } func AddTableTab(gw *GuiWindow, name string, rowcount int, parts []TableColumnData) *TableData { - box := InitWindow(gw, name, Yaxis) - - return AddTableBox(box, name, rowcount, parts) + node := NewWindow() + b := node.box + return b.AddTableBox(name, rowcount, parts) } -func AddTableBox(box *GuiBox, name string, rowcount int, parts []TableColumnData) *TableData { +func (b *GuiBox) AddTableBox(name string, rowcount int, parts []TableColumnData) *TableData { mh := new(TableData) mh.RowCount = rowcount @@ -142,9 +142,9 @@ func AddTableBox(box *GuiBox, name string, rowcount int, parts []TableColumnData // is this needed? // gw.BoxMap[name] = box - mh.Box = box + mh.Box = b - box.UiBox.Append(table, true) + b.UiBox.Append(table, true) return mh } diff --git a/tableCallbacks.go b/tableCallbacks.go index 966f173..6eefd8d 100644 --- a/tableCallbacks.go +++ b/tableCallbacks.go @@ -30,7 +30,8 @@ func (mh *TableData) ColumnTypes(m *ui.TableModel) []ui.TableValue { } // TODO: Figure out why this is being called 1000 times a second (10 times for each row & column) -// Nevermind this TODO. Who gives a shit. This is a really smart way to treat the OS toolkits +// +// Nevermind that TODO. Who gives a shit. This is a really smart way to treat the OS toolkits func (mh *TableData) CellValue(m *ui.TableModel, row, column int) ui.TableValue { if (Config.DebugTable) { log.Println("CellValue() row, column =", row, column) diff --git a/window-debug.go b/window-debug.go deleted file mode 100644 index 704ef7b..0000000 --- a/window-debug.go +++ /dev/null @@ -1,230 +0,0 @@ -package gui - -import ( - "log" - - "github.com/andlabs/ui" - _ "github.com/andlabs/ui/winmanifest" - "github.com/davecgh/go-spew/spew" -) - -var names = make([]string, 100) - -func makeWindowDebug() ui.Control { - hbox := ui.NewHorizontalBox() - hbox.SetPadded(true) - - ///////////////////////////////////////////////////// - vbox := addGroup(hbox, "Numbers") - pbar := ui.NewProgressBar() - vbox.Append(pbar, false) - - ///////////////////////////////////////////////////// - vbox = addGroup(hbox, "Window") - cbox := ui.NewCombobox() - - for name, _ := range Data.WindowMap { - 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") - - dump2 := addButton(vbox, "Dump Boxes") - dump2.OnClicked(func(*ui.Button) { - DumpBoxes() - }) - - dump1 := addButton(vbox, "Dump MAP") - dump1.OnClicked(func(*ui.Button) { - DumpMap() - }) - - return hbox -} - -var x int = 0 - -func addName(c *ui.Combobox, s string) { - c.Append(s) - names[x] = s - x = x + 1 -} - -func addGroup(b *ui.Box, name string) *ui.Box { - group := ui.NewGroup(name) - group.SetMargined(true) - b.Append(group, true) - - vbox := ui.NewVerticalBox() - vbox.SetPadded(true) - group.SetChild(vbox) - - return vbox -} - -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 dumpBox(s string) { - 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) - 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) - - button.OnClicked(func(*ui.Button) { - log.Println("Should do something here") - }) - - box.Append(button, false) - return button -} diff --git a/window-template.go b/window-template.go deleted file mode 100644 index c3e30ef..0000000 --- a/window-template.go +++ /dev/null @@ -1,72 +0,0 @@ -package gui - -import "log" -import "github.com/andlabs/ui" -import _ "github.com/andlabs/ui/winmanifest" - -func makeWindowTemplate() ui.Control { - hbox := ui.NewHorizontalBox() - hbox.SetPadded(true) - - group := ui.NewGroup("Numbers") - group.SetMargined(true) - hbox.Append(group, true) - - vbox := ui.NewVerticalBox() - vbox.SetPadded(true) - group.SetChild(vbox) - - spinbox := ui.NewSpinbox(47, 100) - slider := ui.NewSlider(21, 100) - pbar := ui.NewProgressBar() - - spinbox.OnChanged(func(*ui.Spinbox) { - slider.SetValue(spinbox.Value()) - pbar.SetValue(spinbox.Value()) - }) - slider.OnChanged(func(*ui.Slider) { - spinbox.SetValue(slider.Value()) - pbar.SetValue(slider.Value()) - }) - vbox.Append(spinbox, false) - vbox.Append(slider, false) - vbox.Append(pbar, false) - - ip := ui.NewProgressBar() - ip.SetValue(-1) - vbox.Append(ip, false) - - group = ui.NewGroup("Lists") - group.SetMargined(true) - hbox.Append(group, true) - - vbox = ui.NewVerticalBox() - vbox.SetPadded(true) - group.SetChild(vbox) - - cbox := ui.NewCombobox() - cbox.Append("Combobox Item 1") - cbox.Append("Combobox Item 2") - cbox.Append("Combobox Item 3") - vbox.Append(cbox, false) - - ecbox := ui.NewEditableCombobox() - ecbox.Append("Editable Item 1") - ecbox.Append("Editable Item 2") - ecbox.Append("Editable Item 3") - vbox.Append(ecbox, false) - - ecbox.OnChanged(func(*ui.EditableCombobox) { - log.Println("test") - test := ecbox.Text() - log.Println("test=", test) - }) - - rb := ui.NewRadioButtons() - rb.Append("Radio Button 1") - rb.Append("Radio Button 2") - rb.Append("Radio Button 3") - vbox.Append(rb, false) - - return hbox -} diff --git a/window.go b/window.go index 2b615b5..403638e 100644 --- a/window.go +++ b/window.go @@ -2,40 +2,13 @@ package gui import ( "log" + "fmt" "strconv" - "time" "github.com/andlabs/ui" - - // import "regexp" - _ "github.com/andlabs/ui/winmanifest" ) -func initUI(name string, callback func(*GuiBox) *GuiBox) { - ui.Main(func() { - log.Println("gui.initUI() inside ui.Main()") - - box := InitWindow(nil, "StartNewWindow"+name, 0) - box = callback(box) - window := box.Window - log.Println("StartNewWindow() box =", box) - - window.UiWindow.Show() - }) -} - -func StartNewWindow(bg bool, name string, axis int, callback func(*GuiBox) *GuiBox) { - log.Println("StartNewWindow() ui.Main() Create a new window") - - if bg { - go initUI(name, callback) - time.Sleep(500 * time.Millisecond) // this might make it more stable on windows? - } else { - initUI(name, callback) - } -} - func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) { ui.MsgBox(gw.UiWindow, msg1, msg2) } @@ -44,71 +17,6 @@ func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) { ui.MsgBoxError(gw.UiWindow, msg1, msg2) } -// -// This creates a new 'window' (which is just a tab in the window) -// This is this way because on Linux you can have more than one -// actual window but that does not appear to work on the MacOS or Windows -// -func InitWindow(gw *GuiWindow, name string, axis int) *GuiBox { - log.Println("InitGuiWindow() START") - - var box *GuiBox - if gw == nil { - box = mapWindow(nil, name, Config.Height, Config.Width) - } else { - box = mapWindow(gw.UiWindow, name, Config.Height, Config.Width) - } - - // box.Window = &newGuiWindow - newGuiWindow := box.Window - - // This is the first window. One must create it here - if gw == nil { - log.Println("initWindow() ADDING ui.NewWindow()") - newGuiWindow.UiWindow = ui.NewWindow(name, int(newGuiWindow.Height), int(newGuiWindow.Width), true) - newGuiWindow.UiWindow.SetBorderless(false) - - // newGuiWindow.UiWindow.SetTitle("test") - newGuiWindow.UiWindow.OnClosing(func(*ui.Window) bool { - log.Println("initTabWindow() OnClosing() THIS WINDOW IS CLOSING newGuiWindow=", newGuiWindow) - // newGuiWindow.UiWindow.Destroy() - if Config.Exit == nil { - ui.Quit() - } else { - // allow a custom exit function - Config.Exit(newGuiWindow) - } - return true - }) - - newGuiWindow.UiTab = ui.NewTab() - newGuiWindow.UiWindow.SetChild(newGuiWindow.UiTab) - newGuiWindow.UiWindow.SetMargined(true) - tmp := 0 - newGuiWindow.TabNumber = &tmp - } else { - newGuiWindow.UiWindow = gw.UiWindow - newGuiWindow.UiTab = gw.UiTab - } - - newGuiWindow.BoxMap = make(map[string]*GuiBox) - newGuiWindow.EntryMap = make(map[string]*GuiEntry) - // Data.Windows = append(Data.Windows, &newGuiWindow) - - if newGuiWindow.UiTab == nil { - tabnum := 0 - newGuiWindow.TabNumber = &tabnum - } else { - tabnum := newGuiWindow.UiTab.NumPages() - newGuiWindow.TabNumber = &tabnum - } - - Data.WindowMap[newGuiWindow.Name] = newGuiWindow - - log.Println("InitGuiWindow() END *GuiWindow =", newGuiWindow) - return box -} - func DeleteWindow(name string) { log.Println("gui.DeleteWindow() START name =", name) window := Data.WindowMap[name] @@ -144,57 +52,102 @@ func DeleteWindow(name string) { } } -func CreateWindow(title string, tabname string, x int, y int, custom func() ui.Control) *GuiBox { - box := CreateBlankWindow(title, x, y) - box.InitTab(title, custom) - return box +func makeNode(parent *Node, title string, x int, y int) *Node { + var node Node + node.Name = title + node.Width = x + node.Height = y + + id := Config.prefix + strconv.Itoa(Config.counter) + Config.counter += 1 + node.id = id + + // 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()") + } + node.parent = parent + return &node } -func CreateBlankWindow(title string, x int, y int) *GuiBox { - box := mapWindow(nil, title, x, y) - log.Println("gui.CreateBlankWindow() title = box.Name =", box.Name) - - window := ui.NewWindow(box.Name, x, y, false) - window.SetBorderless(false) - window.OnClosing(func(*ui.Window) bool { - log.Println("createWindow().OnClosing()", box.Name) - return true - }) - ui.OnShouldQuit(func() bool { - log.Println("createWindow().Destroy()", box.Name) - window.Destroy() - return true - }) +func (parent *Node) makeNode(title string, x int, y int) *Node { + var node Node + node.Name = title + node.Width = x + node.Height = y - window.SetMargined(true) - window.Show() + id := Config.prefix + strconv.Itoa(Config.counter) + Config.counter += 1 + node.id = id - box.Window.UiWindow = window - return box + parent.Append(&node) + node.parent = parent + return &node } -func InitBlankWindow() ui.Control { - hbox := ui.NewHorizontalBox() - hbox.SetPadded(true) +func (n *Node) AddNode(title string) *Node { + var node Node + node.Name = title + node.Width = n.Width + node.Height = n.Height + + id := Config.prefix + strconv.Itoa(Config.counter) + Config.counter += 1 + node.id = id - return hbox + n.Append(&node) + node.parent = n + return &node } -var master = 0 +func (n *Node) uiNewWindow(title string, x int, y int) { + w := ui.NewWindow(title, x, y, false) + w.SetBorderless(false) + f := Config.Exit + w.OnClosing(func(*ui.Window) bool { + if (Config.Debug) { + log.Println("ui.Window().OnClosing()") + } + if (f != nil) { + f(n) + } + return true + }) + w.SetMargined(true) + w.Show() + n.uiWindow = w + // w.node = &node + return +} -func mapWindow(window *ui.Window, title string, x int, y int) *GuiBox { +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) - master = master + 1 - title = title + " jcarr " + strconv.Itoa(master) + 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 } - log.Println("gui.WindowMap START title =", title) + var newGuiWindow GuiWindow newGuiWindow.Width = x newGuiWindow.Height = y @@ -210,30 +163,47 @@ func mapWindow(window *ui.Window, title string, x int, y int) *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 &box + return node } -func NewWindow(title string, x int, y int) *GuiBox { - box := mapWindow(nil, title, x, y) +// This routine creates a blank window with a Title and size (W x H) +// +// This routine can not have any arguements due to the nature of how +// 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). +func NewWindow() *Node { + title := Config.Title + w := Config.Width + h := Config.Height + + var n *Node + n = mapWindow(nil, nil, title, w, h) + box := n.box log.Println("gui.NewWindow() title = box.Name =", box.Name) - window := ui.NewWindow(box.Name, x, y, false) - window.SetBorderless(false) - window.OnClosing(func(*ui.Window) bool { - log.Println("createWindow().OnClosing()", box.Name) - return true - }) + n.uiNewWindow(box.Name, w, h) + window := n.uiWindow + + f := Config.Exit ui.OnShouldQuit(func() bool { - log.Println("createWindow().Destroy()", box.Name) - window.Destroy() + log.Println("createWindow().Destroy() on node.Name =", n.Name) + if (f != nil) { + f(n) + } return true }) - window.SetMargined(true) - window.Show() - box.Window.UiWindow = window - return box + if(n.uiWindow == nil) { + panic("node.uiWindow == nil. This should never happen") + } + return n } -- cgit v1.2.3 From c95392d4609f06eb0b86fc6a25b93613ee3770fb Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sun, 31 Oct 2021 21:07:36 -0500 Subject: BOX: kill GuiBox Signed-off-by: Jeff Carr --- button.go | 6 +++--- debug-window.go | 2 ++ debug.go | 6 +++++- new-structs.go | 5 +++-- structs.go | 16 +++++++++++----- window.go | 11 ----------- 6 files changed, 24 insertions(+), 22 deletions(-) (limited to 'debug.go') diff --git a/button.go b/button.go index 8135962..5017f7a 100644 --- a/button.go +++ b/button.go @@ -50,7 +50,7 @@ func CreateFontButton(n *Node, action string) *GuiButton { var newGB GuiButton newGB.Name = "FONT" newGB.FB = ui.NewFontButton() - newGB.Box = n.box + // newGB.Box = n.box Data.AllButtons = append(Data.AllButtons, &newGB) newGB.FB.OnChanged(func (*ui.FontButton) { @@ -67,7 +67,7 @@ func CreateColorButton(n *Node, custom func(*GuiButton), name string, values int var newCB GuiButton newCB.Name = name newCB.CB = ui.NewColorButton() - newCB.Box = n.box + // newCB.Box = n.box newCB.Custom = custom newCB.Values = values @@ -83,6 +83,6 @@ func CreateColorButton(n *Node, custom func(*GuiButton), name string, values int Data.MouseClick(&newCB) } }) - n.box.Append(newCB.CB, false) + n.uiBox.Append(newCB.CB, false) return &newCB } diff --git a/debug-window.go b/debug-window.go index 19f276d..f058a1e 100644 --- a/debug-window.go +++ b/debug-window.go @@ -295,6 +295,7 @@ func dumpBox(s string) { // 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) @@ -307,6 +308,7 @@ func dumpBox(s string) { } } log.Println("gui.dumpBox() BoxMap END") + */ if window.UiTab != nil { pages := window.UiTab.NumPages() log.Println("gui.DumpBoxes()\tWindow.UiTab.NumPages() =", pages) diff --git a/debug.go b/debug.go index 0b0baa4..d0e814f 100644 --- a/debug.go +++ b/debug.go @@ -40,10 +40,12 @@ func DumpWindows() { func DumpMap() { for name, window := range Data.WindowMap { log.Println("gui.DumpBoxes() MAP: ", name) - log.Println("gui.DumpBoxes() BOXES:", name) + log.Println("gui.DumpBoxes() window:", window) + /* for name, abox := range window.BoxMap { log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name) } + */ } } @@ -59,6 +61,7 @@ func DumpBoxes() { // 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" { @@ -68,6 +71,7 @@ func DumpBoxes() { } } } + */ if window.UiTab != nil { // log.Println("gui.DumpBoxes()\tWindow.UiTab type =", reflect.TypeOf(window.UiTab)) // log.Println("gui.DumpBoxes()\tWindow.UiTab =", window.UiTab) diff --git a/new-structs.go b/new-structs.go index d821a3f..bba6347 100644 --- a/new-structs.go +++ b/new-structs.go @@ -50,7 +50,6 @@ type Node struct { children []*Node window *GuiWindow - box *GuiBox area *GuiArea custom func(*Node) @@ -85,7 +84,7 @@ 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() box = ", n.box) log.Println("gui.Node.Dump() uiWindow = ", n.uiWindow) log.Println("gui.Node.Dump() uiTab = ", n.uiTab) @@ -237,10 +236,12 @@ 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) diff --git a/structs.go b/structs.go index b298f43..c31b021 100644 --- a/structs.go +++ b/structs.go @@ -94,7 +94,7 @@ type GuiWindow struct { // MakeWindow func(*GuiBox) *GuiBox // the components of the window - BoxMap map[string]*GuiBox + // BoxMap map[string]*GuiBox EntryMap map[string]*GuiEntry Area *GuiArea @@ -112,6 +112,7 @@ func (w *GuiWindow) Dump() { 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 { @@ -124,7 +125,9 @@ type GuiBox struct { // 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) @@ -144,6 +147,7 @@ func (b *GuiBox) SetTitle(title string) { b.Window.UiWindow.SetTitle(title) return } +*/ func (w *GuiWindow) SetNode(n *Node) { if (w.node != nil) { @@ -157,6 +161,7 @@ func (w *GuiWindow) SetNode(n *Node) { } } +/* func (b *GuiBox) SetNode(n *Node) { if (b.node != nil) { b.Dump() @@ -176,6 +181,7 @@ func (b *GuiBox) Append(child ui.Control, x bool) { } b.UiBox.Append(child, x) } +*/ // Note: every mouse click is handled // as a 'Button' regardless of where @@ -183,7 +189,7 @@ func (b *GuiBox) Append(child ui.Control, x bool) { // call this 'GuiMouseClick' type GuiButton struct { Name string // field for human readable name - Box *GuiBox // what box the button click was in + // box2 *GuiBox // what box the button click was in // a callback function for the main application Custom func(*GuiButton) @@ -204,7 +210,7 @@ type GuiEntry struct { Normalize func(string) string // function to 'normalize' the data B *GuiButton - Box *GuiBox + // Box *GuiBox // andlabs/ui abstraction mapping UiEntry *ui.Entry @@ -217,7 +223,7 @@ type GuiEntry struct { // type GuiArea struct { Button *GuiButton // what button handles mouse events - Box *GuiBox + // Box *GuiBox UiAttrstr *ui.AttributedString UiArea *ui.Area @@ -255,7 +261,7 @@ type TableData struct { Cells [20]CellData Human [20]HumanMap - Box *GuiBox + // Box *GuiBox n *Node lastRow int diff --git a/window.go b/window.go index 8b5f9a5..6b2a114 100644 --- a/window.go +++ b/window.go @@ -154,23 +154,12 @@ func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Nod 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.uiWindow = window - // node.box = &box - // box.node = node - - // newGuiWindow.BoxMap["jcarrInitTest"] = &box return node } -- cgit v1.2.3 From 59d15f3fcf9799e00566aad7678f29add4e19dd4 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sun, 31 Oct 2021 21:46:30 -0500 Subject: REFACTOR: remove GuiWindow & GuiBox Signed-off-by: Jeff Carr --- area.go | 14 +++++---- debug-window.go | 93 ++++----------------------------------------------------- debug.go | 12 +++----- find.go | 12 ++------ gui.go | 2 +- new-structs.go | 12 ++++---- structs.go | 75 ++++------------------------------------------ table.go | 2 +- window.go | 34 +++++++-------------- 9 files changed, 45 insertions(+), 211 deletions(-) (limited to 'debug.go') diff --git a/area.go b/area.go index 2cf3d18..4fb05ec 100644 --- a/area.go +++ b/area.go @@ -12,22 +12,24 @@ func makeGenericArea(n *Node, newText *ui.AttributedString, custom func(*GuiButt // There should be another way to do this (?) var newB *GuiButton newB = CreateFontButton(n, "AREA") - // newB.Box = gb newB.Custom = custom +/* gw := n.window // initialize the GuiArea{} - gw.Area = new(GuiArea) gw.Area.Button = newB +*/ + area := new(GuiArea) + // gw.Area.Box = gb - gw.Area.UiAttrstr = newText - gw.Area.UiArea = ui.NewArea(gw.Area) + n.uiAttrstr = newText + n.uiArea = ui.NewArea(area) if (Config.Debug) { - spew.Dump(gw.Area.UiArea) + spew.Dump(n.uiArea) log.Println("DEBUGGING", Config.Debug) } else { - log.Println("NOT DEBUGGING AREA mhAH.Button =", gw.Area.Button) + log.Println("NOT DEBUGGING AREA mhAH.Button =", n.uiButton) } } diff --git a/debug-window.go b/debug-window.go index f058a1e..0849f71 100644 --- a/debug-window.go +++ b/debug-window.go @@ -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,7 @@ func makeWindowDebug() *ui.Box { hbox := ui.NewHorizontalBox() hbox.SetPadded(true) +/* ///////////////////////////////////////////////////// vbox := addGroup(hbox, "range Data.WindowMap") cbox := ui.NewCombobox() @@ -44,7 +45,6 @@ func makeWindowDebug() *ui.Box { addName(cbox, name) } cbox.SetSelected(0) - vbox.Append(cbox, false) cbox.OnSelected(func(*ui.Combobox) { @@ -65,76 +65,6 @@ func makeWindowDebug() *ui.Box { 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") @@ -152,6 +82,7 @@ func makeWindowDebug() *ui.Box { dump1.OnClicked(func(*ui.Button) { DumpMap() }) +*/ ///////////////////////////////////////////////////// nodeBox := addGroup(hbox, "Windows:") @@ -179,7 +110,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) { @@ -277,6 +208,7 @@ func addGroup(b *ui.Box, name string) *ui.Box { return vbox } +/* func dumpBox(s string) { var name string var window *GuiWindow @@ -295,20 +227,6 @@ func dumpBox(s string) { // 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) @@ -320,6 +238,7 @@ func dumpBox(s string) { } } } +*/ func addButton(box *ui.Box, name string) *ui.Button { button := ui.NewButton(name) diff --git a/debug.go b/debug.go index d0e814f..2caf6d0 100644 --- a/debug.go +++ b/debug.go @@ -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,7 @@ func WatchGUI() { } } +/* func DumpWindows() { for name, _ := range Data.WindowMap { log.Println("gui.DumpWindows() window =", name) @@ -41,11 +42,9 @@ func DumpMap() { for name, window := range Data.WindowMap { log.Println("gui.DumpBoxes() MAP: ", name) log.Println("gui.DumpBoxes() window:", window) - /* for name, abox := range window.BoxMap { log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name) } - */ } } @@ -61,7 +60,6 @@ func DumpBoxes() { // 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" { @@ -71,7 +69,6 @@ func DumpBoxes() { } } } - */ if window.UiTab != nil { // log.Println("gui.DumpBoxes()\tWindow.UiTab type =", reflect.TypeOf(window.UiTab)) // log.Println("gui.DumpBoxes()\tWindow.UiTab =", window.UiTab) @@ -89,7 +86,6 @@ func DumpBoxes() { } } } - /* for i, window := range Data.Windows { if (window.TabNumber == nil) { log.Println("gui.DumpBoxes() Data.Windows", i, "Name =", window.Name, "TabNumber = nil") @@ -97,8 +93,8 @@ func DumpBoxes() { log.Println("gui.DumpBoxes() Data.Windows", i, "Name =", window.Name, "TabNumber =", *window.TabNumber) } } - */ } +*/ func addTableTab() { var parts []TableColumnData diff --git a/find.go b/find.go index 619ba36..5eb0854 100644 --- a/find.go +++ b/find.go @@ -17,19 +17,11 @@ func (n *Node) FindControl() *ui.Control { return n.uiControl } +/* func (w *GuiWindow) FindNode() *Node { return w.node } - -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 FindNode(name string) *Node { if Data.NodeMap == nil { diff --git a/gui.go b/gui.go index 4174133..bb7e0e5 100644 --- a/gui.go +++ b/gui.go @@ -17,7 +17,7 @@ func init() { log.Println("gui.init() has been run") Data.buttonMap = make(map[*ui.Button]*GuiButton) - Data.WindowMap = make(map[string]*GuiWindow) + // Data.WindowMap = make(map[string]*GuiWindow) Data.NodeMap = make(map[string]*Node) Data.NodeSlice = make([]*Node, 0) diff --git a/new-structs.go b/new-structs.go index bba6347..32d34aa 100644 --- a/new-structs.go +++ b/new-structs.go @@ -49,16 +49,18 @@ type Node struct { parent *Node children []*Node - window *GuiWindow + // window *GuiWindow area *GuiArea custom func(*Node) uiControl *ui.Control uiButton *ui.Button uiWindow *ui.Window - uiTab *ui.Tab - uiBox *ui.Box - uiText *ui.EditableCombobox + uiAttrstr *ui.AttributedString + uiTab *ui.Tab + uiBox *ui.Box + uiArea *ui.Area + uiText *ui.EditableCombobox } func (n *Node) Parent() *Node { @@ -83,7 +85,7 @@ 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() window = ", n.window) // log.Println("gui.Node.Dump() box = ", n.box) log.Println("gui.Node.Dump() uiWindow = ", n.uiWindow) diff --git a/structs.go b/structs.go index c31b021..9a47e44 100644 --- a/structs.go +++ b/structs.go @@ -2,7 +2,7 @@ package gui import ( "image/color" - "log" +// "log" "github.com/andlabs/ui" "golang.org/x/image/font" @@ -42,7 +42,7 @@ type GuiData struct { // A map of all the entry boxes AllEntries []*GuiEntry - WindowMap map[string]*GuiWindow + // WindowMap map[string]*GuiWindow // Store access to everything via binary tree's NodeMap map[string]*Node @@ -62,7 +62,7 @@ type GuiData struct { type GuiTab struct { Name string // field for human readable name Number int // the andlabs/ui tab index - Window *GuiWindow // the parent Window + // Window *GuiWindow // the parent Window } // @@ -83,6 +83,7 @@ type GuiTab struct { // 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 @@ -90,11 +91,7 @@ type GuiWindow struct { 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 @@ -104,7 +101,9 @@ type GuiWindow struct { 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) @@ -112,43 +111,6 @@ func (w *GuiWindow) Dump() { 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() @@ -160,27 +122,6 @@ func (w *GuiWindow) SetNode(n *Node) { 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 @@ -189,7 +130,6 @@ func (b *GuiBox) Append(child ui.Control, x bool) { // call this 'GuiMouseClick' type GuiButton struct { Name string // field for human readable name - // box2 *GuiBox // what box the button click was in // a callback function for the main application Custom func(*GuiButton) @@ -210,7 +150,6 @@ type GuiEntry struct { Normalize func(string) string // function to 'normalize' the data B *GuiButton - // Box *GuiBox // andlabs/ui abstraction mapping UiEntry *ui.Entry @@ -223,7 +162,6 @@ type GuiEntry struct { // type GuiArea struct { Button *GuiButton // what button handles mouse events - // Box *GuiBox UiAttrstr *ui.AttributedString UiArea *ui.Area @@ -261,7 +199,6 @@ type TableData struct { Cells [20]CellData Human [20]HumanMap - // Box *GuiBox n *Node lastRow int diff --git a/table.go b/table.go index a149450..378cab2 100644 --- a/table.go +++ b/table.go @@ -97,7 +97,7 @@ func InitColumns(mh *TableData, parts []TableColumnData) { } } -func AddTableTab(gw *GuiWindow, name string, rowcount int, parts []TableColumnData) *TableData { +func AddTableTab(name string, rowcount int, parts []TableColumnData) *TableData { n := NewWindow() return n.AddTableBox(name, rowcount, parts) } diff --git a/window.go b/window.go index 6b2a114..c554d9c 100644 --- a/window.go +++ b/window.go @@ -9,14 +9,19 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) { - ui.MsgBox(gw.UiWindow, msg1, msg2) +func (n *Node) MessageWindow2(msg1 string, msg2 string) (*Node) { + ui.MsgBox(n.uiWindow, msg1, msg2) + // TODO: make new node + return n } -func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) { - ui.MsgBoxError(gw.UiWindow, msg1, msg2) +func (n *Node) ErrorWindow2(msg1 string, msg2 string) (*Node) { + ui.MsgBoxError(n.uiWindow, msg1, msg2) + // TODO: make new node + return n } +/* func DeleteWindow(name string) { log.Println("gui.DeleteWindow() START name =", name) window := Data.WindowMap[name] @@ -51,6 +56,7 @@ func DeleteWindow(name string) { } } } +*/ func makeNode(parent *Node, title string, x int, y int) *Node { var node Node @@ -137,26 +143,6 @@ func (n *Node) uiNewWindow(title string, x int, y int) { 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.EntryMap = make(map[string]*GuiEntry) - - Data.WindowMap[newGuiWindow.Name] = &newGuiWindow node := makeNode(parent, title, x, y) node.uiWindow = window -- cgit v1.2.3 From 86e73bab9f490ddeccb2744f3e7ee1094042616f Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Mon, 1 Nov 2021 01:13:07 -0500 Subject: CLEAN: remove more cruft Signed-off-by: Jeff Carr --- debug.go | 86 ++-------------------------------------------------------- new-structs.go | 11 +++++--- 2 files changed, 9 insertions(+), 88 deletions(-) (limited to 'debug.go') diff --git a/debug.go b/debug.go index 2caf6d0..c895e01 100644 --- a/debug.go +++ b/debug.go @@ -31,71 +31,6 @@ 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() window:", window) - 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 @@ -126,24 +61,6 @@ 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") @@ -151,8 +68,9 @@ func (dn *GuiData) ListChildren(dump bool) { } log.Println("gui.Data.ListChildren() Data.NodeMap:") for name, node := range Data.NodeMap { - log.Println("\tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name) + listChildrenDepth = 0 if (dump == true) { + log.Println("tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name) node.Dump() } node.ListChildren(dump) diff --git a/new-structs.go b/new-structs.go index 92ce84a..daeab64 100644 --- a/new-structs.go +++ b/new-structs.go @@ -135,19 +135,22 @@ 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 tabs string + var space string for i := 0; i < depth; i++ { - tabs = tabs + "\t" + space = space + indent } // newFormat := tabs + strconv.Itoa(depth) + " " + format - newFormat := tabs + format + newFormat := space + format log.Println(newFormat, a) } func (n *Node) ListChildren(dump bool) { - indentPrintln(listChildrenDepth, "\t", n.id, n.Width, n.Height, n.Name) + indentPrintln(listChildrenDepth, "", n.id, n.Width, n.Height, n.Name) if (dump == true) { n.Dump() -- cgit v1.2.3 From 8358ca44efa625be9cd69fab870dfcf9c2a05df5 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Tue, 11 Oct 2022 11:25:46 -0500 Subject: Change Node to Box --- area.go | 58 +++++++++--- box.go | 203 ++++++++++++++++++++++++++++++++++++---- button.go | 151 ++++++++++++++++++++++++------ cmds/gui-example/demo-window.go | 4 +- cmds/helloworld/helloworld | Bin 0 -> 3097960 bytes cmds/helloworld/main.go | 27 ++++++ debug-window.go | 172 +++++++++++++++++++++++++++++++++- debug.go | 90 +++++++++++++++++- demo-window.go | 68 +------------- doc.go | 30 ++++-- entry.go | 104 ++++++++++++++++---- find.go | 59 ++++++++++++ go.mod | 9 +- go.sum | 8 +- gui.go | 6 +- new-structs.go | 111 +++++++--------------- structs.go | 176 ++++++++++++++++++++++++++++++++-- table.go | 14 +-- tableCallbacks.go | 9 +- window.go | 155 +++++++++++++++++++----------- 20 files changed, 1121 insertions(+), 333 deletions(-) create mode 100755 cmds/helloworld/helloworld create mode 100644 cmds/helloworld/main.go (limited to 'debug.go') diff --git a/area.go b/area.go index c4e0cae..7c42c6c 100644 --- a/area.go +++ b/area.go @@ -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) } diff --git a/box.go b/box.go index 67c0c05..7a61f55 100644 --- a/box.go +++ b/box.go @@ -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 "" } diff --git a/button.go b/button.go index 755d9ab..8ad0a3b 100644 --- a/button.go +++ b/button.go @@ -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 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 (n *Node) CreateColorButton(custom func(*Node), name string, values interface {}) *Node { +func CreateFontButton(box *GuiBox, action string) *GuiButton { // create a 'fake' button entry for the mouse clicks - n.uiColorButton = ui.NewColorButton() - n.custom = custom - n.values = values + 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) + } + }) + 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) - n.uiColorButton.OnChanged(func (*ui.ColorButton) { + newCB.CB.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 + r, g, b, a := newCB.CB.Color() log.Println("ColorButton.OnChanged() Color() =", r, g, b, a) - if (n.custom != nil) { - n.custom(n) + if (newCB.Custom != nil) { + newCB.Custom(&newCB) } else if (Data.MouseClick != nil) { - Data.MouseClick(n) + Data.MouseClick(&newCB) } }) - n.uiBox.Append(n.uiColorButton, Config.Stretchy) - return n + box.Append(newCB.CB, false) + return &newCB } diff --git a/cmds/gui-example/demo-window.go b/cmds/gui-example/demo-window.go index f01c1a9..993900d 100644 --- a/cmds/gui-example/demo-window.go +++ b/cmds/gui-example/demo-window.go @@ -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() diff --git a/cmds/helloworld/helloworld b/cmds/helloworld/helloworld new file mode 100755 index 0000000..cc41f78 Binary files /dev/null and b/cmds/helloworld/helloworld differ diff --git a/cmds/helloworld/main.go b/cmds/helloworld/main.go new file mode 100644 index 0000000..1cb1bbd --- /dev/null +++ b/cmds/helloworld/main.go @@ -0,0 +1,27 @@ +// This creates a simple hello world window +package main + +import ( + "git.wit.org/wit/gui" +) + +func main() { + gui.Main(initGUI) +} + +// This initializes the first window +func initGUI() { + gui.Config.Title = "Hello World golang wit/gui Window" + gui.Config.Width = 640 + gui.Config.Height = 480 + node1 := gui.NewWindow() + addDemoTab(node1, "A Simple Tab Demo") + addDemoTab(node1, "A Second Tab") +} + +func addDemoTab(n *gui.Node, title string) { + newNode := n.AddTab(title, nil) + + groupNode1 := newNode.AddGroup("group 1") + groupNode1.AddComboBox("demoCombo2", "more 1", "more 2", "more 3") +} diff --git a/debug-window.go b/debug-window.go index 72272ec..19f276d 100644 --- a/debug-window.go +++ b/debug-window.go @@ -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 } diff --git a/debug.go b/debug.go index c895e01..0b0baa4 100644 --- a/debug.go +++ b/debug.go @@ -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) diff --git a/demo-window.go b/demo-window.go index 6cbb5fd..16566c4 100644 --- a/demo-window.go +++ b/demo-window.go @@ -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 -} diff --git a/doc.go b/doc.go index 3f8bc64..35c6a8f 100644 --- a/doc.go +++ b/doc.go @@ -1,7 +1,6 @@ /* -Package wit/gui implements a abstraction layer for Go visual elements in -a cross platform way. Right now, this abstraction is built on top of -the GUI toolkit 'andlabs/ui' which does the cross platform support. +Package gui implements a abstraction layer for Go visual elements in +a cross platform way. A quick overview of the features, some general design guidelines and principles for how this package should generally work: @@ -15,9 +14,7 @@ Quick Start This section demonstrates how to quickly get started with spew. See the sections below for further details on formatting and configuration options. -To dump a variable with full newlines, indentation, type, and pointer -information use Dump, Fdump, or Sdump: - + // This creates a simple hello world window package main import ( @@ -30,11 +27,12 @@ information use Dump, Fdump, or Sdump: // This initializes the first window func initGUI() { - gui.Config.Title = "WIT GUI Window 1" + gui.Config.Title = "Hello World golang wit/gui Window" gui.Config.Width = 640 gui.Config.Height = 480 node1 := gui.NewWindow() addDemoTab(node1, "A Simple Tab Demo") + addDemoTab(node1, "A Second Tab") } func addDemoTab(n *gui.Node, title string) { @@ -60,10 +58,24 @@ The following configuration options are available: * Debug When 'true' log more output -GUI Usage +Toolkit Usage + +Right now, this abstraction is built on top of the go package 'andlabs/ui' +which does the cross platform support. +The next step is to intent is to allow this to work directly against GTK and QT. +It should be able to add Fyne, WASM, native macos & windows, android, etc. 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. + +Debugging + +To dump variables with full newlines, indentation, type, and pointer +information this uses spew.Dump() + */ package gui diff --git a/entry.go b/entry.go index 524609f..c10b7d0 100644 --- a/entry.go +++ b/entry.go @@ -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") + } + 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 ") } - log.Println("Couldn't find something that has a Margin setting") + 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) { diff --git a/find.go b/find.go index 15f2714..e046161 100644 --- a/find.go +++ b/find.go @@ -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") diff --git a/go.mod b/go.mod index 18a5b64..c72bbca 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index dd2a245..27ff5d2 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/gui.go b/gui.go index ac75f1e..4174133 100644 --- a/gui.go +++ b/gui.go @@ -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() { diff --git a/new-structs.go b/new-structs.go index f806696..4f9989e 100644 --- a/new-structs.go +++ b/new-structs.go @@ -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 } diff --git a/structs.go b/structs.go index 79b3fbf..c15f4b7 100644 --- a/structs.go +++ b/structs.go @@ -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 { diff --git a/table.go b/table.go index 378cab2..92ae871 100644 --- a/table.go +++ b/table.go @@ -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 } diff --git a/tableCallbacks.go b/tableCallbacks.go index f294a9b..6eefd8d 100644 --- a/tableCallbacks.go +++ b/tableCallbacks.go @@ -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") diff --git a/window.go b/window.go index 50f7073..403638e 100644 --- a/window.go +++ b/window.go @@ -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 - } - } - return nil +func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) { + ui.MsgBox(gw.UiWindow, msg1, msg2) } -func MessageWindow(msg1 string, msg2 string) (*Node) { - uiW := findUiWindow() - ui.MsgBox(uiW, msg1, msg2) - // TODO: make new node - return nil +func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) { + ui.MsgBoxError(gw.UiWindow, msg1, msg2) } -func ErrorWindow(msg1 string, msg2 string) (*Node) { - uiW := findUiWindow() - ui.MsgBoxError(uiW, msg1, msg2) - return nil +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) + } + } + } } -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 } -- cgit v1.2.3