summaryrefslogtreecommitdiff
path: root/structs.go
diff options
context:
space:
mode:
Diffstat (limited to 'structs.go')
-rw-r--r--structs.go422
1 files changed, 162 insertions, 260 deletions
diff --git a/structs.go b/structs.go
index fedb34a..d9b5bef 100644
--- a/structs.go
+++ b/structs.go
@@ -1,31 +1,38 @@
package gui
import (
- "image/color"
"log"
- "github.com/andlabs/ui"
- "golang.org/x/image/font"
-
- // "github.com/davecgh/go-spew/spew"
-
- // _ "github.com/andlabs/ui/winmanifest"
)
+import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+
//
// 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
+// within the toolkit/ abstraction layer
+//
+// More than one Window is not supported in a cross platform
+// sense & may never be. On many toolkits you have to have 'tabs'
+// Native Windows and MacOS toolkits work with tabs
//
-var Data GuiData
+// If that is the case, this code should abstract the concept of
+// windows and make everything 'tabs'
+//
+
var Config GuiConfig
type GuiConfig struct {
+ // This is the master node. The Binary Tree starts here
+ master *Node
+
+ // These are shortcuts to pass default values to make a new window
Title string
Width int
Height int
Exit func(*Node)
+ // These are global debugging settings
+ // TODO: move to a standard logging system
Debug bool
DebugNode bool
DebugTabs bool
@@ -33,295 +40,190 @@ type GuiConfig struct {
DebugWindow bool
DebugToolkit bool
+ // hacks
depth int
counter int // used to make unique ID's
prefix string
}
-type GuiData struct {
- // a fallback default function to handle mouse events
- // if nothing else is defined to handle them
- MouseClick func(*GuiButton)
-
- // A map of all the entry boxes
- AllEntries []*GuiEntry
- WindowMap map[string]*GuiWindow
+type Widget int
- // 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
-}
+// https://ieftimov.com/post/golang-datastructures-trees/
+const (
+ Unknown Widget = iota
+ Window
+ Tab
+ Frame
+ Dropbox
+ Spinner
+ Label
+)
-type GuiTab struct {
- Name string // field for human readable name
- Number int // the andlabs/ui tab index
- Window *GuiWindow // the parent Window
+func (s Widget) String() string {
+ switch s {
+ case Window:
+ return "Window"
+ case Tab:
+ return "Tab"
+ case Frame:
+ return "Frame"
+ case Label:
+ return "Label"
+ case Dropbox:
+ return "Dropbox"
+ }
+ return "unknown"
}
-//
-// 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 Node is simply the name and the size of whatever GUI element exists
+type Node struct {
+ id string
- // the callback function to make the window contents
- // MakeWindow func(*GuiBox) *GuiBox
+ Name string
+ Width int
+ Height int
- // the components of the window
- BoxMap map[string]*GuiBox
- EntryMap map[string]*GuiEntry
- Area *GuiArea
+ parent *Node
+ children []*Node
- node *Node
+ custom func(*Node)
+ OnChanged func(*Node)
- // andlabs/ui abstraction mapping
- UiWindow *ui.Window
- UiTab *ui.Tab // if this != nil, the window is 'tabbed'
+ toolkit *toolkit.Toolkit
}
-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)
+func (n *Node) Parent() *Node {
+ return n.parent
}
-// 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 (n *Node) Window() *Node {
+ return n.parent
}
-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 (n *Node) Dump() {
+ IndentPrintln("id = ", n.id)
+ IndentPrintln("Name = ", n.Name)
+ IndentPrintln("Width = ", n.Width)
+ IndentPrintln("Height = ", n.Height)
-func (b *GuiBox) SetTitle(title string) {
- log.Println("DID IT!", title)
- if b.Window == nil {
- return
- }
- if b.Window.UiWindow == nil {
- return
+ if (n.parent == nil) {
+ IndentPrintln("parent = nil")
+ } else {
+ IndentPrintln("parent =", n.parent.id)
}
- b.Window.UiWindow.SetTitle(title)
- return
-}
-
-func (w *GuiWindow) SetNode(n *Node) {
- if (w.node != nil) {
- w.Dump()
- panic("gui.SetNode() Error not nil")
+ if (n.children != nil) {
+ IndentPrintln("children = ", n.children)
}
- w.node = n
- if (w.node == nil) {
- w.Dump()
- panic("gui.SetNode() node == nil")
+ if (n.toolkit != nil) {
+ IndentPrintln("toolkit = ", n.toolkit)
+ n.toolkit.Dump()
}
-}
-
-func (b *GuiBox) SetNode(n *Node) {
- if (b.node != nil) {
- b.Dump()
- panic("gui.SetNode() Error not nil")
+ if (n.custom != nil) {
+ IndentPrintln("custom = ", n.custom)
}
- b.node = n
- if (b.node == nil) {
- b.Dump()
- panic("gui.SetNode() node == nil")
+ if (n.OnChanged != nil) {
+ IndentPrintln("OnChanged = ", n.OnChanged)
}
-}
-
-func (b *GuiBox) Append(child ui.Control, x bool) {
- if b.UiBox == nil {
- // spew.Dump(b)
- b.Dump()
- panic("GuiBox.Append() can't work. UiBox == nil")
- return
+ if (n.id == "") {
+ // Node structs should never have a nil id.
+ // I probably shouldn't panic here, but this is just to check the sanity of
+ // the gui package to make sure it's not exiting
+ panic("gui.Node.Dump() id == nil TODO: make a unigue id here in the golang gui library")
}
- 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
-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
-
- B *GuiButton
- Box *GuiBox
-
- // andlabs/ui abstraction mapping
- UiEntry *ui.Entry
+func (n *Node) SetName(name string) {
+ n.toolkit.SetWindowTitle(name)
+ return
}
-//
-// AREA STRUCTURES START
-// AREA STRUCTURES START
-// AREA STRUCTURES START
-//
-type GuiArea struct {
- Button *GuiButton // what button handles mouse events
- Box *GuiBox
-
- UiAttrstr *ui.AttributedString
- UiArea *ui.Area
+func (n *Node) Append(child *Node) {
+ 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)
}
-type FontString struct {
- S string
- Size int
- F font.Face
- W font.Weight
+/*
+func (n *Node) List() {
+ findByIdDFS(n, "test")
}
+*/
-//
-// AREA STRUCTURES END
-// AREA STRUCTURES END
-// AREA STRUCTURES END
-//
-
-//
-// TABLE DATA STRUCTURES START
-// TABLE DATA STRUCTURES START
-// TABLE DATA STRUCTURES START
-//
-
-//
-// This is the structure that andlabs/ui uses to pass information
-// to the GUI. This is the "authoritative" data.
-//
-type TableData struct {
- RowCount int // This is the number of 'rows' which really means data elements not what the human sees
- RowWidth int // This is how wide each row is
- Rows []RowData // This is all the table data by row
- generatedColumnTypes []ui.TableValue // generate this dynamically
-
- Cells [20]CellData
- Human [20]HumanMap
+var listChildrenParent *Node
+var listChildrenDepth int = 0
+var defaultPadding = " "
- Box *GuiBox
-
- lastRow int
- lastColumn int
+func IndentPrintln(a ...interface{}) {
+ indentPrintln(listChildrenDepth, defaultPadding, a)
}
-//
-// This maps the andlabs/ui & libui components into a "human"
-// readable cell reference list. The reason is that there
-// are potentially 3 values for each cell. The Text, the Color
-// and an image. These are not always needed so the number
-// of fields varies between 1 and 3. Internally, the toolkit
-// GUI abstraction needs to list all of them, but it's then
-// hard to figure out which column goes with the columns that
-// you see when you visually are looking at it like a spreadsheet
-//
-// This makes a map so that we can say "give me the value at
-// row 4 and column 2" and find the fields that are needed
-//
-// TODO: re-add images and the progress bar (works in andlabs/ui)
-//
-type HumanCellData struct {
- Name string // what kind of row is this?
- Text string
- TextID int
- Color color.RGBA
- ColorID int
- Button *GuiButton
-}
-
-type HumanMap struct {
- Name string // what kind of row is this?
- TextID int
- ColorID int
-}
+func indentPrintln(depth int, format string, a ...interface{}) {
+ var tabs string
+ for i := 0; i < depth; i++ {
+ tabs = tabs + format
+ }
-type TableColumnData struct {
- Index int
- CellType string
- Heading string
- Color string
+ // newFormat := tabs + strconv.Itoa(depth) + " " + format
+ newFormat := tabs + format
+ log.Println(newFormat, a)
}
-type CellData struct {
- Index int
- HumanID int
- Name string // what type of cell is this?
-}
+func (n *Node) ListChildren(dump bool) {
+ indentPrintln(listChildrenDepth, defaultPadding, n.id, n.Width, n.Height, n.Name)
-// 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
+ 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
}
-
-//
-// TABLE DATA STRUCTURES END
-//