gocui: rework spacing logic

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-04-05 13:06:42 -05:00
parent 89ef92e200
commit fb43b88a0b
9 changed files with 202 additions and 54 deletions

View File

@ -23,10 +23,13 @@ func (w *cuiWidget) doWidgetClick() {
case toolkit.Tab: case toolkit.Tab:
w.redoBox(true) w.redoBox(true)
w.toggleTree() w.toggleTree()
case toolkit.Group:
w.redoBox(true)
w.toggleTree()
case toolkit.Grid: case toolkit.Grid:
w.setParentLogical() // w.setParentLogical()
w.gridBounds() w.gridBounds()
w.setParentLogical() // w.setParentLogical()
for _, child := range w.children { for _, child := range w.children {
child.showWidgetPlacement(logNow, "gridBounds:") child.showWidgetPlacement(logNow, "gridBounds:")
if (child.v == nil) { if (child.v == nil) {

View File

@ -29,24 +29,22 @@ func setupWidget(a *toolkit.Action) *cuiWidget {
// set the name used by gocui to the id // set the name used by gocui to the id
w.cuiName = strconv.Itoa(w.id) w.cuiName = strconv.Itoa(w.id)
w.parent = findWidget(a.ParentId, me.rootNode) if w.widgetType == toolkit.Root {
log(logInfo, "setupWidget() w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId) log(logInfo, "setupWidget() FOUND ROOT w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
if (w.id == 0) { w.id = 0
me.rootNode = w me.rootNode = w
// this is the rootNode
return w return w
} }
w.parent = findWidget(a.ParentId, me.rootNode)
log(logInfo, "setupWidget() w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
if (w.parent == nil) { if (w.parent == nil) {
log(logError, "setupWidget() ERROR: PARENT = NIL w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId) log(logError, "setupWidget() ERROR: PARENT = NIL w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
// just use the rootNode (hopefully it's not nil) // just use the rootNode (hopefully it's not nil)
w.parent = me.rootNode w.parent = me.rootNode
// return w // return w
} }
if (w.parent == nil) {
log(logError, "setupWidget() ERROR: PARENT = NIL w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
me.rootNode = w
return w
}
// add this widget as a child for the parent // add this widget as a child for the parent
w.parent.Append(w) w.parent.Append(w)
@ -58,11 +56,9 @@ func setupWidget(a *toolkit.Action) *cuiWidget {
} }
} }
if (a.WidgetType == toolkit.Grid) { if (a.WidgetType == toolkit.Grid) {
w.logicalW = make(map[int]int) // how tall each row in the grid is w.widths = make(map[int]int) // how tall each row in the grid is
w.logicalH = make(map[int]int) // how wide each column in the grid is w.heights = make(map[int]int) // how wide each column in the grid is
} }
// w.showWidgetPlacement(logNow)
return w return w
} }

View File

@ -33,23 +33,30 @@ func (w *cuiWidget) dumpTree(draw bool) {
} }
func (w *cuiWidget) showWidgetPlacement(b bool, s string) { func (w *cuiWidget) showWidgetPlacement(b bool, s string) {
var s1 string
var pId int
if (w == nil) { if (w == nil) {
log(logError, "WTF w == nil") log(logError, "WTF w == nil")
return return
} }
if (w.id == 0) {
log(logVerbose, "showWidgetPlacement() parent == nil ok. This is the rootNode", w.id, w.cuiName)
return
}
if (w.parent == nil) { if (w.parent == nil) {
log(logError, "showWidgetPlacement() ERROR parent == nil", w.id, w.cuiName) log(logVerbose, "showWidgetPlacement() parent == nil", w.id, w.cuiName)
pId = 0
} else {
pId = w.parent.id
} }
log(b, "dump()", s, s1 = fmt.Sprintf("(wId,pId)=(%2d,%2d) ", w.id, pId)
fmt.Sprintf("(wId,pId)=(%3d,%3d)", w.id, w.parent.id), s1 += fmt.Sprintf("real()=(%2d,%2d,%2d,%2d) ", w.realSize.w0, w.realSize.h0, w.realSize.w1, w.realSize.h1)
fmt.Sprintf("real()=(%3d,%3d,%3d,%3d)", w.realSize.w0, w.realSize.h0, w.realSize.w1, w.realSize.h1), s1 += fmt.Sprintf("size()=(%2d,%2d) ", w.realWidth, w.realHeight)
"size()=(", w.realWidth, ",", w.realHeight, ")",
"logical()=(", w.logicalSize.w0, ",", w.logicalSize.h0, ",", w.logicalSize.w1, ",", w.logicalSize.h1, ")", switch w.widgetType {
w.widgetType, ",", w.name, "text=", w.text) case toolkit.Grid:
s1 += fmt.Sprintf("next()=(%2d,%2d)", w.nextW, w.nextH)
default:
s1 += fmt.Sprintf("L()=(%2d,%2d,%2d,%2d)",
w.logicalSize.w0, w.logicalSize.h0, w.logicalSize.w1, w.logicalSize.h1)
}
log(b, s1, s, w.widgetType, ",", w.name) // , "text=", w.text)
if (w.realWidth != (w.realSize.w1 - w.realSize.w0)) { if (w.realWidth != (w.realSize.w1 - w.realSize.w0)) {
log(b, "dump()", s, log(b, "dump()", s,

View File

@ -40,7 +40,6 @@ func defaultKeybindings(g *gocui.Gui) error {
var showDebug bool = true var showDebug bool = true
// dump out the widgets
func addDebugKeys(g *gocui.Gui) { func addDebugKeys(g *gocui.Gui) {
// dump all widget info to the log // dump all widget info to the log
g.SetKeybinding("", 'd', gocui.ModNone, g.SetKeybinding("", 'd', gocui.ModNone,

View File

@ -9,7 +9,7 @@ import (
var logNow bool = true // useful for active development var logNow bool = true // useful for active development
var logError bool = true var logError bool = true
var logWarn bool = false var logWarn bool = false
var logInfo bool = false var logInfo bool = true
var logVerbose bool = false var logVerbose bool = false
func log(a ...any) { func log(a ...any) {

View File

@ -6,6 +6,7 @@ import (
var adjusted bool = false var adjusted bool = false
/*
// expands the logical size of the parents // expands the logical size of the parents
func (w *cuiWidget) setParentLogical() { func (w *cuiWidget) setParentLogical() {
p := w.parent p := w.parent
@ -71,3 +72,4 @@ func (w *cuiWidget) setParentLogical() {
pP.setParentLogical() pP.setParentLogical()
} }
} }
*/

View File

@ -29,7 +29,6 @@ func (w *cuiWidget) setFake() {
func findPlace(w *cuiWidget) { func findPlace(w *cuiWidget) {
w.isFake = false w.isFake = false
w.visable = true
switch w.widgetType { switch w.widgetType {
case toolkit.Root: case toolkit.Root:
w.isFake = true w.isFake = true
@ -48,6 +47,75 @@ func findPlace(w *cuiWidget) {
} }
} }
// find the start (w,h) for child a inside a box widget
func (w *cuiWidget) getBoxWH() {
p := w.parent // the parent must be a box widget
// update parent realSize
p.realWidth = 0
p.realHeight = 0
for _, child := range p.children {
p.realWidth += child.realWidth
p.realHeight += child.realHeight
}
// compute child offset
w.startW = p.startW
w.startH = p.startH
for _, child := range p.children {
if (p.horizontal) {
log("BOX IS HORIZONTAL (w,h)", w.startW, w.startH)
log("BOX IS HORIZONTAL (w,h)", w.startW, w.startH)
log("BOX IS HORIZONTAL (w,h)", w.startW, w.startH)
w.startW += child.realWidth
} else {
log("BOX IS VERTICAL (w,h)", w.startW, w.startH)
log("BOX IS VERTICAL (w,h)", w.startW, w.startH)
log("BOX IS VERTICAL (w,h)", w.startW, w.startH)
w.startH += child.realHeight
}
if child == w {
return
}
}
return
}
// find the start (w,h) for child a inside a Group widget
func (w *cuiWidget) getGroupWH() {
p := w.parent // the parent must be a group widget
// update parent realSize
p.realWidth = 0
p.realHeight = 0
p.realHeight += me.buttonPadding // pad height for the group label
for _, child := range p.children {
p.realWidth += child.realWidth
p.realHeight += child.realHeight
}
// compute child offset
w.startW = p.startW
w.startH = p.startH
for _, child := range p.children {
w.startH += child.realHeight
if child == w {
return
}
}
return
}
// find the start (w,h) for child a inside a Grid widget
func (w *cuiWidget) getGridWH() {
p := w.parent
w.startW = p.startW
w.startH = p.startH
w.nextW = p.startW
w.nextH = p.startH
w.gridBounds()
}
func (w *cuiWidget) redoBox(draw bool) { func (w *cuiWidget) redoBox(draw bool) {
if (w == nil) { if (w == nil) {
return return
@ -126,10 +194,14 @@ func (w *cuiWidget) redoBox(draw bool) {
} }
func (w *cuiWidget) moveTo(leftW int, topH int) { func (w *cuiWidget) moveTo(leftW int, topH int) {
w.realSize.w0 = leftW if (w.isFake) {
w.realSize.h0 = topH // don't ever move these
w.realSize.w1 = leftW + w.realWidth } else {
w.realSize.h1 = topH + w.realHeight w.realSize.w0 = leftW
w.realSize.h0 = topH
}
w.realSize.w1 = w.realSize.w0 + w.realWidth
w.realSize.h1 = w.realSize.h0 + w.realHeight
w.logicalSize.w0 = w.realSize.w0 w.logicalSize.w0 = w.realSize.w0
w.logicalSize.h0 = w.realSize.h0 w.logicalSize.h0 = w.realSize.h0
@ -166,7 +238,7 @@ func (w *cuiWidget) gridBounds() {
for a := 0; a < w.x; a++ { for a := 0; a < w.x; a++ {
for b := 0; b < w.y; b++ { for b := 0; b < w.y; b++ {
log(logNow, "gridBounds() (w,h)", a, b, log(logNow, "gridBounds() (w,h)", a, b,
"logical(W,H)", w.logicalW[a], w.logicalH[b], "logical(W,H)", w.widths[a], w.heights[b],
"p.next(W,H)", p.nextW, p.nextH) "p.next(W,H)", p.nextW, p.nextH)
} }
log("\n") log("\n")
@ -183,11 +255,11 @@ func (w *cuiWidget) gridBounds() {
// set the child's realWidth, and grid offset // set the child's realWidth, and grid offset
child.parentH = hCount child.parentH = hCount
child.parentW = wCount child.parentW = wCount
if (w.logicalW[wCount] < child.realWidth) { if (w.widths[wCount] < child.realWidth) {
w.logicalW[wCount] = child.realWidth w.widths[wCount] = child.realWidth
} }
if (w.logicalH[hCount] < child.realHeight) { if (w.heights[hCount] < child.realHeight) {
w.logicalH[hCount] = child.realHeight w.heights[hCount] = child.realHeight
} }
log(logNow, "redoBox(GRID) (w,h count)", wCount, hCount, "(X,Y)", w.x, w.y, w.name) log(logNow, "redoBox(GRID) (w,h count)", wCount, hCount, "(X,Y)", w.x, w.y, w.name)
child.showWidgetPlacement(logNow, "grid:") child.showWidgetPlacement(logNow, "grid:")
@ -200,17 +272,26 @@ func (w *cuiWidget) gridBounds() {
} }
} }
// reset the size of the whole grid
w.realWidth = 0
w.realHeight = 0
for _, val := range w.widths {
w.realWidth += val
}
for _, val := range w.heights {
w.realHeight += val
}
for _, child := range w.children { for _, child := range w.children {
child.showWidgetPlacement(logVerbose, "gridBounds:") child.showWidgetPlacement(logVerbose, "gridBounds:")
var totalW, totalH int var totalW, totalH int
for i, val := range w.logicalW { for i, val := range w.widths {
if (i < child.parentW) { if (i < child.parentW) {
log(logVerbose, "gridBounds() (w, logicalW[])", i, val) log(logVerbose, "gridBounds() (w, widths[])", i, val)
totalW += w.logicalW[i] totalW += w.widths[i]
} }
} }
for i, h := range w.logicalH { for i, h := range w.heights {
if (i < child.parentH) { if (i < child.parentH) {
totalH += h totalH += h
} }
@ -228,6 +309,6 @@ func (w *cuiWidget) gridBounds() {
child.showWidgetPlacement(logInfo, "gridBounds:") child.showWidgetPlacement(logInfo, "gridBounds:")
log(logInfo) log(logInfo)
} }
w.updateLogicalSizes() // w.updateLogicalSizes()
w.showWidgetPlacement(logNow, "gridBounds:") w.showWidgetPlacement(logNow, "gridBounds:")
} }

View File

@ -10,14 +10,69 @@ func Quit() {
me.baseGui.Close() me.baseGui.Close()
} }
// set the widget start width & height
// re-run this when things change to recalibrate the position of the gocui view rect
func (w *cuiWidget) setStartWH() {
log(logInfo, "setStartWH() w.id =", w.id, "w.name", w.name)
switch w.widgetType {
case toolkit.Root:
log(logInfo, "setStartWH() rootNode w.id =", w.id, "w.name", w.name)
w.startW = 1
w.startH = 1
w.id = 0
w.isFake = true
w.setFake()
w.showWidgetPlacement(logNow, "Tree:")
return
case toolkit.Flag:
w.startW = 1
w.startH = 1
w.isFake = true
w.setFake()
w.showWidgetPlacement(logNow, "Tree:")
return
case toolkit.Window:
w.startW = 1
w.startH = 3
return
case toolkit.Tab:
w.startW = 1
w.startH = 3
return
}
p := w.parent
switch p.widgetType {
case toolkit.Box:
if (w.isFake == false) {
w.isFake = true
w.setFake()
}
w.getBoxWH()
return
case toolkit.Grid:
if (w.isFake == false) {
w.isFake = true
w.setFake()
}
w.getGridWH()
return
case toolkit.Group:
w.getGroupWH()
return
}
}
func Action(a *toolkit.Action) { func Action(a *toolkit.Action) {
log(logInfo, "Action() START", a.WidgetId, a.ActionType, a.WidgetType, a.Name) log(logInfo, "Action() START", a.WidgetId, a.ActionType, a.WidgetType, a.Name)
w := findWidget(a.WidgetId, me.rootNode) w := findWidget(a.WidgetId, me.rootNode)
switch a.ActionType { switch a.ActionType {
case toolkit.Add: case toolkit.Add:
w = setupWidget(a) w = setupWidget(a)
findPlace(w) w.setStartWH()
w.moveTo(w.startW, w.startH)
w.drawView() w.drawView()
// findPlace(w)
case toolkit.Show: case toolkit.Show:
if (a.B) { if (a.B) {
w.drawView() w.drawView()

View File

@ -87,20 +87,29 @@ type cuiWidget struct {
vals []string // dropdown menu options vals []string // dropdown menu options
visable bool // track if it's currently supposed to be shown // visable bool // track if it's currently supposed to be shown
isFake bool // widget types like 'box' are 'false' isFake bool // widget types like 'box' are 'false'
realWidth int // the real width
realHeight int // the real height // where the widget should calculate it's existance from
startW int
startH int
// the widget size to reserve or things will overlap
realWidth int
realHeight int
realSize rectType // the display size of this widget realSize rectType // the display size of this widget
logicalSize rectType // the logical size. Includes all the child widgets logicalSize rectType // the logical size. Includes all the child widgets
// used to track the size of grids // used to track the size of grids
logicalW map[int]int // how tall each row in the grid is widths map[int]int // how tall each row in the grid is
logicalH map[int]int // how wide each column in the grid is heights map[int]int // how wide each column in the grid is
// where in the parent grid this widget should go
// deprecate // where in the parent grid this widget should go
parentW int parentW int
parentH int parentH int
// deprecate
nextW int nextW int
nextH int nextH int
@ -113,10 +122,6 @@ type cuiWidget struct {
width int width int
height int height int
//deprecate
// nextX int
// nextY int
// horizontal=true means layout widgets like books on a bookshelf // horizontal=true means layout widgets like books on a bookshelf
// horizontal=false means layout widgets like books in a stack // horizontal=false means layout widgets like books in a stack
horizontal bool `default:false` horizontal bool `default:false`