diff options
| author | Jeff Carr <[email protected]> | 2022-10-20 06:55:42 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2022-10-20 06:55:42 -0500 |
| commit | b8ef0bb05dc14bc4291f3d156b199fa125cdb9d7 (patch) | |
| tree | 71280d7f01805dfbd430f71df16858079686b8fc /toolkit/andlabs/old | |
| parent | f3af1f5b7ff78b3f73d7510622fc9633dec36d35 (diff) | |
Squashed commit of the following:
all non binary tree structs are gone (almost all)
Use names from https://en.wikipedia.org/wiki/Graphical_widget
toolkit andlabs/ui is isolated from being accessable
all direct references to andlabs are removed
working dropdown widgets
add debugging more buttons and windows
Diffstat (limited to 'toolkit/andlabs/old')
| -rw-r--r-- | toolkit/andlabs/old/area.go | 136 | ||||
| -rw-r--r-- | toolkit/andlabs/old/color.go | 31 | ||||
| -rw-r--r-- | toolkit/andlabs/old/seperator.go | 25 | ||||
| -rw-r--r-- | toolkit/andlabs/old/structs.go | 273 | ||||
| -rw-r--r-- | toolkit/andlabs/old/table.go | 150 | ||||
| -rw-r--r-- | toolkit/andlabs/old/tableCallbacks.go | 108 |
6 files changed, 723 insertions, 0 deletions
diff --git a/toolkit/andlabs/old/area.go b/toolkit/andlabs/old/area.go new file mode 100644 index 0000000..7c42c6c --- /dev/null +++ b/toolkit/andlabs/old/area.go @@ -0,0 +1,136 @@ +package gui + +import "log" + +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +import "github.com/davecgh/go-spew/spew" + +func makeGenericArea(gb *GuiBox, newText *ui.AttributedString, custom func(*GuiButton)) { + // make this button just to get the default font (but don't display the button) + // There should be another way to do this (?) + var newB *GuiButton + newB = CreateFontButton(gb, "AREA") + newB.Box = gb + newB.Custom = custom + + gw := gb.Window + // initialize the GuiArea{} + gw.Area = new(GuiArea) + gw.Area.Button = newB + gw.Area.Box = gb + gw.Area.UiAttrstr = newText + gw.Area.UiArea = ui.NewArea(gw.Area) + + if (Config.Debug) { + spew.Dump(gw.Area.UiArea) + log.Println("DEBUGGING", Config.Debug) + } else { + log.Println("NOT DEBUGGING AREA mhAH.Button =", gw.Area.Button) + } +} + +func AreaAppendText(newText *ui.AttributedString, what string, attrs ...ui.Attribute) { + start := len(newText.String()) + end := start + len(what) + newText.AppendUnattributed(what) + for _, a := range attrs { + newText.SetAttribute(a, start, end) + } +} + +func appendWithAttributes(newText *ui.AttributedString, what string, attrs ...ui.Attribute) { + start := len(newText.String()) + end := start + len(what) + newText.AppendUnattributed(what) + for _, a := range attrs { + newText.SetAttribute(a, start, end) + } +} + +func (ah GuiArea) Draw(a *ui.Area, p *ui.AreaDrawParams) { + tl := ui.DrawNewTextLayout(&ui.DrawTextLayoutParams{ + String: ah.UiAttrstr, + DefaultFont: ah.Button.FB.Font(), + Width: p.AreaWidth, + Align: ui.DrawTextAlign(1), + }) + p.Context.Text(tl, 0, 0) + defer tl.Free() +} + +func (ah GuiArea) MouseEvent(a *ui.Area, me *ui.AreaMouseEvent) { + if (Config.Debug) { + log.Println("GOT MouseEvent() ah.Button =", ah.Button) + spew.Dump(me) + } + if (me.Down == 1) { + log.Println("GOT MOUSE DOWN") + log.Println("GOT MOUSE DOWN ah.Button =", ah.Button) + log.Println("GOT MOUSE UP ah.Button.FB =", ah.Button.FB) + } + if (me.Up == 1) { + log.Println("GOT MOUSE UP") + log.Println("GOT MOUSE UP ah.Button =", ah.Button) + log.Println("GOT MOUSE UP ah.Button.FB =", ah.Button.FB) + if (ah.Button.Custom != nil) { + ah.Button.Custom(ah.Button) + } else if (Data.MouseClick != nil) { + Data.MouseClick(ah.Button) + } + } +} + +func (ah GuiArea) MouseCrossed(a *ui.Area, left bool) { + log.Println("GOT MouseCrossed()") +} + +func (ah GuiArea) DragBroken(a *ui.Area) { + log.Println("GOT DragBroken()") +} + +// TODO: fix KeyEvents +func (ah GuiArea) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) { + log.Println("GOT KeyEvent()") + if (ke.Key == 10) { + log.Println("GOT ENTER") + log.Println("GOT ENTER") + log.Println("GOT ENTER") + } + if (ke.Key == 32) { + log.Println("GOT ENTER") + log.Println("GOT ENTER") + log.Println("GOT ENTER") + } + spew.Dump(ke) + return false +} + +func (b *GuiBox) ShowTextBox(newText *ui.AttributedString, custom func(*GuiButton), name string) { + log.Println("ShowTextBox() START") + + gw := b.Window + if (gw == nil) { + log.Println("ShowTextBox() ERROR gw = nil") + return + } + log.Println("ShowTextBox() START gw =", gw) + + /* + var newbox *GuiBox + newbox = new(GuiBox) + newbox.Window = gw + newbox.Name = name + hbox := ui.NewVerticalBox() + newbox.UiBox = hbox + */ + + // TODO: allow padded & axis here + b.UiBox.SetPadded(true) + + // add(gw.BoxMap["MAINBOX"], newbox) + + makeGenericArea(b, newText, custom) + b.UiBox.Append(b.Window.Area.UiArea, true) +} diff --git a/toolkit/andlabs/old/color.go b/toolkit/andlabs/old/color.go new file mode 100644 index 0000000..cf4a362 --- /dev/null +++ b/toolkit/andlabs/old/color.go @@ -0,0 +1,31 @@ +package gui + +// +// convert between 'standard' golang Color and andlabs/ui Color +// + +// import "log" +// import "fmt" +import "image/color" + +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +func libuiColorToGOlangColor(rgba color.RGBA) ui.TableColor { + /* a hack to see if colors work differently on macos or windows + if (rgba.R == 72) { + log.Println("SETTING COLOR TO NIL") + log.Println("SETTING COLOR TO NIL") + log.Println("SETTING COLOR TO NIL") + return ui.TableColor{} + } + */ + return ui.TableColor{float64(rgba.R) / 256, float64(rgba.G) / 256, float64(rgba.B) / 256, float64(rgba.A) / 256} +} + +/* +func golangColorGOlibuiColorTo (ui.TableColor) (rgba color.RGBA) { + color.RGBA{float64(, 100, 200, 100} + return ui.TableColor{float64(rgba.R) / 256, float64(rgba.G) / 256, float64(rgba.B) / 256, float64(rgba.A) / 256} +} +*/ diff --git a/toolkit/andlabs/old/seperator.go b/toolkit/andlabs/old/seperator.go new file mode 100644 index 0000000..ca152a8 --- /dev/null +++ b/toolkit/andlabs/old/seperator.go @@ -0,0 +1,25 @@ +package gui + +import "log" +import "os" + +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +func HorizontalBreak(box *GuiBox) { + log.Println("VerticalSeparator added to box =", box.Name) + tmp := ui.NewHorizontalSeparator() + if (box == nil) { + return + } + if (box.UiBox == nil) { + return + } + box.UiBox.Append(tmp, false) +} + +func VerticalBreak(box *GuiBox) { + log.Println("VerticalSeparator added to box =", box.Name) + tmp := ui.NewVerticalSeparator() + box.UiBox.Append(tmp, false) +} diff --git a/toolkit/andlabs/old/structs.go b/toolkit/andlabs/old/structs.go new file mode 100644 index 0000000..4a16438 --- /dev/null +++ b/toolkit/andlabs/old/structs.go @@ -0,0 +1,273 @@ +package gui + +import ( + "image/color" + + "github.com/andlabs/ui" +// "golang.org/x/image/font" + + // "github.com/davecgh/go-spew/spew" + + // _ "github.com/andlabs/ui/winmanifest" +) + +// +// All GUI Data Structures and functions that are external +// If you need cross platform support, these might only +// be the safe way to interact with the GUI +// +var Data GuiData +var Config GuiConfig + +type GuiConfig struct { + Title string + Width int + Height int + Exit func(*Node) + + Debug bool + DebugNode bool + DebugTabs bool + DebugTable bool + DebugWindow bool + DebugToolkit bool + + depth int + counter int // used to make unique ID's + prefix string +} + +type GuiData struct { + // a fallback default function to handle mouse events + // if nothing else is defined to handle them + MouseClick func(*GuiButton) + + // A map of all the entry boxes + // AllEntries []*GuiEntry + WindowMap map[string]*GuiWindow + + // Store access to everything via binary tree's + NodeMap map[string]*Node + NodeArray []*Node + NodeSlice []*Node + + // A map of all buttons everywhere on all + // windows, all tabs, across all goroutines + // This is "GLOBAL" + // + // This has to work this way because of how + // andlabs/ui & andlabs/libui work + AllButtons []*GuiButton +// buttonMap map[*ui.Button]*GuiButton +} + +/* +type GuiTab struct { + Name string // field for human readable name + Number int // the andlabs/ui tab index + Window *GuiWindow // the parent Window +} +*/ + +// +// stores information on the 'window' +// +// This merges the concept of andlabs/ui *Window and *Tab +// +// More than one Window is not supported in a cross platform +// sense & may never be. On Windows and MacOS, you have to have +// 'tabs'. Even under Linux, more than one Window is currently +// unstable +// +// This code will make a 'GuiWindow' regardless of if it is +// a stand alone window (which is more or less working on Linux) +// or a 'tab' inside a window (which is all that works on MacOS +// and MSWindows. +// +// This struct keeps track of what is in the window so you +// can destroy and replace it with something else +// +type GuiWindow struct { + Name string // field for human readable name + Width int + Height int + Axis int // does it add items to the X or Y axis + TabNumber *int // the andlabs/ui tab index + + // the callback function to make the window contents + // MakeWindow func(*GuiBox) *GuiBox + + // the components of the window + BoxMap map[string]*GuiBox + // EntryMap map[string]*GuiEntry + + node *Node + + // andlabs/ui abstraction mapping + UiWindow *ui.Window + UiTab *ui.Tab // if this != nil, the window is 'tabbed' +} + +/* +func (w *GuiWindow) Dump() { + log.Println("gui.GuiWindow.Dump() Name = ", w.Name) + log.Println("gui.GuiWindow.Dump() node = ", w.node) + log.Println("gui.GuiWindow.Dump() Width = ", w.Width) + log.Println("gui.GuiWindow.Dump() Height = ", w.Height) +} +*/ + +// GuiBox is any type of ui.Hbox or ui.Vbox +// There can be lots of these for each GuiWindow +type GuiBox struct { + Name string // field for human readable name + Axis int // does it add items to the X or Y axis + Window *GuiWindow // the parent Window + + node *Node + + // andlabs/ui abstraction mapping + UiBox *ui.Box +} + +func (b *GuiBox) Append(child ui.Control, x bool) { + if b.UiBox == nil { + // spew.Dump(b) + // b.Dump() + panic("GuiBox.Append() can't work. UiBox == nil") + return + } + b.UiBox.Append(child, x) +} + +// Note: every mouse click is handled +// as a 'Button' regardless of where +// the user clicks it. You could probably +// call this 'GuiMouseClick' +type GuiButton struct { + Name string // field for human readable name + Box *GuiBox // what box the button click was in + + // a callback function for the main application + Custom func(*GuiButton) + Values interface{} + Color color.RGBA + + // andlabs/ui abstraction mapping + B *ui.Button + FB *ui.FontButton + CB *ui.ColorButton +} + +/* +// +// AREA STRUCTURES START +// AREA STRUCTURES START +// AREA STRUCTURES START +// +type GuiArea struct { + Button *GuiButton // what button handles mouse events + Box *GuiBox + + UiAttrstr *ui.AttributedString + UiArea *ui.Area +} + +type FontString struct { + S string + Size int + F font.Face + W font.Weight +} + +// +// AREA STRUCTURES END +// AREA STRUCTURES END +// AREA STRUCTURES END +// + +// +// TABLE DATA STRUCTURES START +// TABLE DATA STRUCTURES START +// TABLE DATA STRUCTURES START +// + +// +// This is the structure that andlabs/ui uses to pass information +// to the GUI. This is the "authoritative" data. +// +type TableData struct { + RowCount int // This is the number of 'rows' which really means data elements not what the human sees + RowWidth int // This is how wide each row is + Rows []RowData // This is all the table data by row + generatedColumnTypes []ui.TableValue // generate this dynamically + + Cells [20]CellData + Human [20]HumanMap + + Box *GuiBox + + lastRow int + lastColumn int +} + +// +// This maps the andlabs/ui & libui components into a "human" +// readable cell reference list. The reason is that there +// are potentially 3 values for each cell. The Text, the Color +// and an image. These are not always needed so the number +// of fields varies between 1 and 3. Internally, the toolkit +// GUI abstraction needs to list all of them, but it's then +// hard to figure out which column goes with the columns that +// you see when you visually are looking at it like a spreadsheet +// +// This makes a map so that we can say "give me the value at +// row 4 and column 2" and find the fields that are needed +// +// TODO: re-add images and the progress bar (works in andlabs/ui) +// +type HumanCellData struct { + Name string // what kind of row is this? + Text string + TextID int + Color color.RGBA + ColorID int + Button *GuiButton +} + +type HumanMap struct { + Name string // what kind of row is this? + TextID int + ColorID int +} + +type TableColumnData struct { + Index int + CellType string + Heading string + Color string +} + +type CellData struct { + Index int + HumanID int + Name string // what type of cell is this? +} + +// hmm. will this stand the test of time? +type RowData struct { + Name string // what kind of row is this? + Status string // status of the row? + // + // TODO: These may or may not be implementable + // depending on if it's possible to detect the bgcolor or what row is selected + // click func() // what function to call if the user clicks on it + // doubleclick func() // what function to call if the user double clicks on it + // + HumanData [20]HumanCellData +} +*/ + +// +// TABLE DATA STRUCTURES END +// diff --git a/toolkit/andlabs/old/table.go b/toolkit/andlabs/old/table.go new file mode 100644 index 0000000..92ae871 --- /dev/null +++ b/toolkit/andlabs/old/table.go @@ -0,0 +1,150 @@ +// based off andlabs/ui/examples/table.go + +package gui + +import "log" + +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +// import "github.com/davecgh/go-spew/spew" + +func initRowBTcolor(mh *TableData, intBG int, cell TableColumnData) { + humanInt := cell.Index + + // setup mapping from human readable indexes to internal libUI indexes + mh.Human[humanInt].Name = "BG" + mh.Human[humanInt].ColorID = intBG + mh.Human[humanInt].TextID = -1 + + mh.Cells[intBG].Name = "BG" + mh.Cells[intBG].HumanID = humanInt + + log.Println("intBG, humanInt", intBG, humanInt) +} + +func initRowButtonColumn(mh *TableData, buttonID int, junk string, cell TableColumnData) { + humanInt := cell.Index + + // setup mapping from human readable indexes to internal libUI indexes + mh.Human[humanInt].Name = "BUTTON" + mh.Human[humanInt].ColorID = -1 + mh.Human[humanInt].TextID = buttonID + + mh.Cells[buttonID].Name = "BUTTON" + mh.Cells[buttonID].HumanID = humanInt + + log.Println("buttonID, humanInt", buttonID, humanInt) +} + +func initRowTextColorColumn(mh *TableData, stringID int, colorID int, junk string, color ui.TableColor, cell TableColumnData) { + humanInt := cell.Index + + // setup mapping from human readable indexes to internal libUI indexes + mh.Human[humanInt].Name = "EDIT" + mh.Human[humanInt].ColorID = colorID + mh.Human[humanInt].TextID = stringID + + // text for Column humanInt + mh.Cells[stringID].Name = "EDIT" + mh.Cells[stringID].HumanID = humanInt + + mh.Cells[colorID].Name = "COLOR" + mh.Cells[colorID].HumanID = humanInt +} + +func initRowTextColumn(mh *TableData, stringID int, junk string, cell TableColumnData) { + humanInt := cell.Index + + // setup mapping from human readable indexes to internal libUI indexes + mh.Human[humanInt].Name = "EDIT" + mh.Human[humanInt].ColorID = -1 + mh.Human[humanInt].TextID = stringID + + mh.Cells[stringID].Name = "EDIT" + mh.Cells[stringID].HumanID = humanInt +} + +func InitColumns(mh *TableData, parts []TableColumnData) { + tmpBTindex := 0 + humanID := 0 + for key, foo := range parts { + log.Println("key, foo =", key, foo) + + parts[key].Index = humanID + humanID += 1 + + if (foo.CellType == "BG") { + mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableColor{}) + initRowBTcolor (mh, tmpBTindex, parts[key]) + tmpBTindex += 1 + } else if (foo.CellType == "BUTTON") { + mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableString("")) + initRowButtonColumn (mh, tmpBTindex, parts[key].Heading, parts[key]) + tmpBTindex += 1 + } else if (foo.CellType == "TEXTCOLOR") { + mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableString("")) + mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableColor{}) + initRowTextColorColumn(mh, tmpBTindex, tmpBTindex + 1, parts[key].Heading, ui.TableColor{0.0, 0, 0.9, 1}, parts[key]) + tmpBTindex += 2 + } else if (foo.CellType == "TEXT") { + mh.generatedColumnTypes = append(mh.generatedColumnTypes, ui.TableString("")) + initRowTextColumn (mh, tmpBTindex, parts[key].Heading, parts[key]) + tmpBTindex += 1 + } else { + panic("I don't know what this is in initColumnNames") + } + } +} + +func AddTableTab(gw *GuiWindow, name string, rowcount int, parts []TableColumnData) *TableData { + node := NewWindow() + b := node.box + return b.AddTableBox(name, rowcount, parts) +} + +func (b *GuiBox) AddTableBox(name string, rowcount int, parts []TableColumnData) *TableData { + mh := new(TableData) + + mh.RowCount = rowcount + mh.Rows = make([]RowData, mh.RowCount) + + InitColumns(mh, parts) + + model := ui.NewTableModel(mh) + table := ui.NewTable( + &ui.TableParams{ + Model: model, + RowBackgroundColorModelColumn: 0, // Row Background color is always index zero + }) + + tmpBTindex := 0 + for key, foo := range parts { + log.Println(key, foo) + if (foo.CellType == "BG") { + } else if (foo.CellType == "BUTTON") { + tmpBTindex += 1 + table.AppendButtonColumn(foo.Heading, tmpBTindex, ui.TableModelColumnAlwaysEditable) + } else if (foo.CellType == "TEXTCOLOR") { + tmpBTindex += 1 + table.AppendTextColumn(foo.Heading, tmpBTindex, ui.TableModelColumnAlwaysEditable, + &ui.TableTextColumnOptionalParams{ + ColorModelColumn: tmpBTindex + 1, + }); + tmpBTindex += 1 + } else if (foo.CellType == "TEXT") { + tmpBTindex += 1 + table.AppendTextColumn(foo.Heading, tmpBTindex, ui.TableModelColumnAlwaysEditable, nil) + } else { + panic("I don't know what this is in initColumnNames") + } + } + + // is this needed? + // gw.BoxMap[name] = box + mh.Box = b + + b.UiBox.Append(table, true) + + return mh +} diff --git a/toolkit/andlabs/old/tableCallbacks.go b/toolkit/andlabs/old/tableCallbacks.go new file mode 100644 index 0000000..6eefd8d --- /dev/null +++ b/toolkit/andlabs/old/tableCallbacks.go @@ -0,0 +1,108 @@ +package gui + +// +// These functions are the hooks to the andlabs libui +// They eventually feed information to the OS native GUI toolkits +// and feed back user interaction with the GUI +// + +import "log" +// import "fmt" +import "image/color" +import "runtime" + +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +func (mh *TableData) NumRows(m *ui.TableModel) int { + if (Config.Debug) { + log.Println("NumRows = mh.RowCount = ", mh.RowCount, "(last Row & Column =", mh.lastRow, mh.lastColumn, ")") + } + return mh.RowCount +} + +// FYI: this routine seems to be called around 10 to 100 times a second for each table +func (mh *TableData) ColumnTypes(m *ui.TableModel) []ui.TableValue { + if (Config.DebugTable) { + log.Println("ColumnTypes = ", mh.generatedColumnTypes) + } + return mh.generatedColumnTypes +} + +// TODO: Figure out why this is being called 1000 times a second (10 times for each row & column) +// +// Nevermind that TODO. Who gives a shit. This is a really smart way to treat the OS toolkits +func (mh *TableData) CellValue(m *ui.TableModel, row, column int) ui.TableValue { + if (Config.DebugTable) { + log.Println("CellValue() row, column =", row, column) + } + mh.lastRow = row + mh.lastColumn = column + humanID := mh.Cells[column].HumanID + if (column == mh.Human[humanID].TextID) { + return ui.TableString(mh.Rows[row].HumanData[humanID].Text) + } + if (column == mh.Human[humanID].ColorID) { + if (column == 0) { + // ignore BG color on windows for now + if (runtime.GOOS == "windows") { + // TODO: fix colors on windows + // log.Println("CellValue() WINDOWS is BG COLOR row, column =", row, column) + // return nil + } + + if (mh.Rows[row].HumanData[humanID].Color == color.RGBA{255, 255, 255, 255}) { + log.Println("CellValue() color.RGBA{255, 255, 255, 255} so return nil. row, column =", row, column) + return nil + } + + bgcolor := libuiColorToGOlangColor(mh.Rows[row].HumanData[humanID].Color) + if (Config.Debug) { + log.Println("CellValue() BGCOLOR =", bgcolor) + } + return bgcolor + } + return libuiColorToGOlangColor(mh.Rows[row].HumanData[humanID].Color) + } + log.Println("CellValue() FAILURE") + log.Println("CellValue() FAILURE") + log.Println("CellValue() row, column = ", row, column) + log.Println("CellValue() FAILURE") + log.Println("CellValue() FAILURE") + log.Println("CellValue() mh.Cells", mh.Cells) + log.Println("CellValue() mh.Human", mh.Human) + panic("CellValue() not sure what sort of ui.TableValue to return in CellValue()") + return ui.TableString("") +} + +func (mh *TableData) SetCellValue(m *ui.TableModel, row, column int, value ui.TableValue) { + log.Println("SetCellValue() START row=", row, "column=", column, "value=", value) + + defaultSetCellValue(mh, row, column) + + log.Println("mh.Cells[column].HumanID =", mh.Cells[column].HumanID) + // log.Println("mh.Rows[row].Cells[column].HumanID =", mh.Rows[row].Cells[column].HumanID) + + humanID := mh.Cells[column].HumanID + log.Println("mh.Human[humanID].ColorID =", mh.Human[humanID].ColorID) + log.Println("mh.Human[humanID].TextID =", mh.Human[humanID].TextID) + + log.Println("SetCellValue() END") +} + +func defaultSetCellValue(mh *TableData, row int, column int) { + if (mh.Cells[column].Name == "BUTTON") { + humanID := mh.Cells[column].HumanID + log.Println("defaultSetCellValue() FOUND THE TABLE BUTTON ", row, humanID) + + button := mh.Rows[row].HumanData[humanID].Button + if (button != nil) { + guiButtonClick(button) + return + } + log.Println("defaultSetCellValue() ERROR: UNKNOWN BUTTON IN TABLE") + if (Config.Debug) { + panic("defaultSetCellValue() GOT AN UNKNOWN BUTTON CLICK IN TABLE") + } + } +} |
