2024-01-18 00:08:37 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-02-02 11:07:56 -06:00
|
|
|
"errors"
|
|
|
|
|
2024-01-18 00:08:37 -06:00
|
|
|
"github.com/awesome-gocui/gocui"
|
|
|
|
"go.wit.com/log"
|
2024-01-18 04:10:08 -06:00
|
|
|
"go.wit.com/widget"
|
2024-01-18 00:08:37 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// set isCurrent = false everywhere
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) unsetCurrent() {
|
2024-01-18 00:08:37 -06:00
|
|
|
w.isCurrent = false
|
|
|
|
|
2024-01-28 02:20:31 -06:00
|
|
|
if w.node.WidgetType == widget.Tab {
|
2024-01-18 00:08:37 -06:00
|
|
|
// n.tk.color = &colorTab
|
|
|
|
// n.setColor()
|
|
|
|
}
|
|
|
|
|
2024-01-28 02:20:31 -06:00
|
|
|
for _, child := range w.children {
|
2024-01-28 11:07:51 -06:00
|
|
|
child.unsetCurrent()
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// when adding a new widget, this will update the display
|
|
|
|
// of the current widgets if that widget is supposed
|
|
|
|
// to be in current display
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) updateCurrent() {
|
2024-01-28 02:20:31 -06:00
|
|
|
log.Log(NOW, "updateCurrent()", w.String())
|
2024-01-28 11:07:51 -06:00
|
|
|
if w.WidgetType == widget.Tab {
|
2024-01-28 02:20:31 -06:00
|
|
|
if w.IsCurrent() {
|
2024-01-18 00:08:37 -06:00
|
|
|
// n.tk.color = &colorActiveT
|
2024-01-28 11:07:51 -06:00
|
|
|
w.setColor(&colorActiveT)
|
2024-01-28 02:20:31 -06:00
|
|
|
w.hideView()
|
|
|
|
w.showView()
|
2024-01-28 11:07:51 -06:00
|
|
|
w.setCurrentTab()
|
2024-01-18 00:08:37 -06:00
|
|
|
} else {
|
|
|
|
// n.tk.color = &colorTab
|
|
|
|
// n.setColor()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2024-01-28 11:07:51 -06:00
|
|
|
if w.WidgetType == widget.Window {
|
2024-01-28 02:20:31 -06:00
|
|
|
if w.IsCurrent() {
|
2024-01-18 00:08:37 -06:00
|
|
|
// setCurrentWindow(n)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2024-01-28 11:07:51 -06:00
|
|
|
if w.WidgetType == widget.Root {
|
2024-01-18 00:08:37 -06:00
|
|
|
return
|
|
|
|
}
|
2024-01-28 11:07:51 -06:00
|
|
|
w.parent.updateCurrent()
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// shows the widgets in a window
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) setCurrentWindow() {
|
2024-01-28 02:20:31 -06:00
|
|
|
if w.IsCurrent() {
|
2024-01-18 00:08:37 -06:00
|
|
|
return
|
|
|
|
}
|
2024-01-28 11:07:51 -06:00
|
|
|
if w.WidgetType != widget.Window {
|
2024-01-18 00:08:37 -06:00
|
|
|
return
|
|
|
|
}
|
2024-01-28 02:20:31 -06:00
|
|
|
var rootTK *guiWidget
|
|
|
|
rootTK = me.treeRoot.TK.(*guiWidget)
|
2024-01-28 11:07:51 -06:00
|
|
|
rootTK.unsetCurrent()
|
2024-01-18 00:08:37 -06:00
|
|
|
|
2024-01-28 02:20:31 -06:00
|
|
|
if w.hasTabs {
|
2024-01-18 00:08:37 -06:00
|
|
|
// set isCurrent = true on the first tab
|
2024-01-28 02:20:31 -06:00
|
|
|
for _, child := range w.children {
|
|
|
|
child.isCurrent = true
|
2024-01-18 00:08:37 -06:00
|
|
|
break
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
w.isCurrent = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// shows the widgets in a tab
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) setCurrentTab() {
|
|
|
|
var p, rootTK *guiWidget
|
|
|
|
if w.WidgetType != widget.Tab {
|
2024-01-18 00:08:37 -06:00
|
|
|
return
|
|
|
|
}
|
2024-01-28 02:20:31 -06:00
|
|
|
rootTK = me.treeRoot.TK.(*guiWidget)
|
2024-01-28 11:07:51 -06:00
|
|
|
rootTK.unsetCurrent()
|
2024-01-18 00:08:37 -06:00
|
|
|
w.isCurrent = true
|
2024-01-28 11:07:51 -06:00
|
|
|
p = w.parent
|
2024-01-18 00:08:37 -06:00
|
|
|
p.isCurrent = true
|
2024-01-28 11:07:51 -06:00
|
|
|
log.Log(NOW, "setCurrent()", w.String())
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) doWidgetClick() {
|
|
|
|
switch w.WidgetType {
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Root:
|
|
|
|
// THIS IS THE BEGINING OF THE LAYOUT
|
2024-01-28 11:07:51 -06:00
|
|
|
log.Log(NOW, "doWidgetClick()", w.String())
|
2024-01-29 23:01:39 -06:00
|
|
|
wRoot := me.treeRoot.TK.(*guiWidget)
|
|
|
|
wRoot.redoWindows(0, 0)
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Flag:
|
2024-01-28 11:07:51 -06:00
|
|
|
log.Log(NOW, "doWidgetClick() FLAG widget name =", w.String())
|
2024-01-18 00:08:37 -06:00
|
|
|
log.Log(NOW, "doWidgetClick() if this is the dropdown menu, handle it here?")
|
|
|
|
case widget.Window:
|
2024-01-28 11:44:36 -06:00
|
|
|
log.Log(NOW, "doWidgetClick() START on window", w.String())
|
2024-01-29 23:23:04 -06:00
|
|
|
if me.currentWindow == w.node {
|
2024-01-30 03:17:15 -06:00
|
|
|
if !w.active {
|
2024-01-29 23:23:04 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2024-01-29 23:10:15 -06:00
|
|
|
if me.currentWindow != nil {
|
|
|
|
var curw *guiWidget
|
|
|
|
curw = me.currentWindow.TK.(*guiWidget)
|
|
|
|
curw.unsetCurrent()
|
|
|
|
curw.setColor(&colorWindow)
|
|
|
|
curw.hideWidgets()
|
|
|
|
}
|
2024-01-28 11:07:51 -06:00
|
|
|
me.currentWindow = w.node
|
2024-01-28 02:20:31 -06:00
|
|
|
|
2024-01-28 11:44:36 -06:00
|
|
|
log.Log(NOW, "doWidgetClick() set currentWindow to", w.String())
|
2024-01-28 11:07:51 -06:00
|
|
|
w.setColor(&colorActiveW)
|
2024-01-29 23:23:04 -06:00
|
|
|
|
|
|
|
w.active = false
|
2024-02-01 10:06:09 -06:00
|
|
|
// w.dumpTree("before")
|
2024-01-29 23:23:04 -06:00
|
|
|
w.placeWidgets(3, 2)
|
|
|
|
w.showWidgets()
|
|
|
|
|
2024-01-29 23:39:33 -06:00
|
|
|
hideFake()
|
2024-01-29 23:23:04 -06:00
|
|
|
showDebug = true
|
|
|
|
|
2024-02-01 10:06:09 -06:00
|
|
|
// w.dumpTree("after")
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Group:
|
|
|
|
// n.placeWidgets(p.tk.startH, newH)
|
2024-02-01 10:06:09 -06:00
|
|
|
// w.dumpTree("click start")
|
2024-01-28 13:14:43 -06:00
|
|
|
if w.active {
|
|
|
|
w.active = false
|
2024-01-28 20:36:59 -06:00
|
|
|
w.placeWidgets(w.startW, w.startH)
|
2024-01-28 14:03:06 -06:00
|
|
|
w.showWidgets()
|
|
|
|
/*
|
2024-01-28 20:15:59 -06:00
|
|
|
for _, child := range w.children {
|
|
|
|
log.Log(INFO, "START W,H", startW, startH)
|
|
|
|
child.placeWidgets(startW, startH)
|
|
|
|
child.showWidgets()
|
|
|
|
}
|
2024-01-28 14:03:06 -06:00
|
|
|
*/
|
2024-01-28 13:14:43 -06:00
|
|
|
} else {
|
|
|
|
w.active = true
|
|
|
|
for _, child := range w.children {
|
|
|
|
child.hideWidgets()
|
|
|
|
}
|
|
|
|
}
|
2024-02-01 10:06:09 -06:00
|
|
|
// w.dumpTree("click end")
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Checkbox:
|
2024-02-01 11:59:21 -06:00
|
|
|
if w.node.State.Checked {
|
|
|
|
log.Log(WARN, "checkbox is being set to false")
|
|
|
|
w.node.State.Checked = false
|
|
|
|
w.setCheckbox()
|
2024-01-18 00:08:37 -06:00
|
|
|
} else {
|
2024-02-01 11:59:21 -06:00
|
|
|
log.Log(WARN, "checkbox is being set to true")
|
|
|
|
w.node.State.Checked = true
|
|
|
|
w.setCheckbox()
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
2024-02-01 11:59:21 -06:00
|
|
|
me.myTree.SendUserEvent(w.node)
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Grid:
|
2024-01-28 11:07:51 -06:00
|
|
|
newR := w.realGocuiSize()
|
2024-01-18 00:08:37 -06:00
|
|
|
|
|
|
|
// w,h := n.logicalSize()
|
|
|
|
// w := newR.w1 - newR.w0
|
|
|
|
// h := newR.h1 - newR.h0
|
|
|
|
|
2024-01-28 11:07:51 -06:00
|
|
|
w.placeGrid(newR.w0, newR.h0)
|
2024-01-28 02:20:31 -06:00
|
|
|
w.showWidgets()
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Box:
|
|
|
|
// w.showWidgetPlacement(logNow, "drawTree()")
|
2024-01-28 02:20:31 -06:00
|
|
|
if w.direction == widget.Horizontal {
|
2024-01-28 11:07:51 -06:00
|
|
|
log.Log(NOW, "BOX IS HORIZONTAL", w.String())
|
2024-01-18 00:08:37 -06:00
|
|
|
} else {
|
2024-01-28 11:07:51 -06:00
|
|
|
log.Log(NOW, "BOX IS VERTICAL", w.String())
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
2024-01-28 11:07:51 -06:00
|
|
|
w.placeWidgets(me.RawW, me.RawH)
|
|
|
|
w.toggleTree()
|
2024-01-18 00:08:37 -06:00
|
|
|
case widget.Button:
|
2024-01-28 02:20:31 -06:00
|
|
|
// doUserEvent(n)
|
2024-02-02 11:07:56 -06:00
|
|
|
me.myTree.SendFromUser(w.node)
|
2024-02-01 20:12:26 -06:00
|
|
|
case widget.Combobox:
|
|
|
|
log.Log(NOW, "do the combobox here")
|
2024-02-02 11:07:56 -06:00
|
|
|
w.showDropdown()
|
2024-02-01 20:12:26 -06:00
|
|
|
case widget.Dropdown:
|
|
|
|
log.Log(NOW, "do the dropdown here")
|
2024-02-02 11:07:56 -06:00
|
|
|
w.showDropdown()
|
2024-01-18 00:08:37 -06:00
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var toggle bool = true
|
|
|
|
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) toggleTree() {
|
2024-01-18 00:08:37 -06:00
|
|
|
if toggle {
|
2024-01-28 11:07:51 -06:00
|
|
|
w.drawTree(toggle)
|
2024-01-18 00:08:37 -06:00
|
|
|
toggle = false
|
|
|
|
} else {
|
2024-01-28 02:20:31 -06:00
|
|
|
w.hideWidgets()
|
2024-01-18 00:08:37 -06:00
|
|
|
toggle = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// display the widgets in the binary tree
|
2024-01-28 11:07:51 -06:00
|
|
|
func (w *guiWidget) drawTree(draw bool) {
|
2024-01-18 00:08:37 -06:00
|
|
|
if w == nil {
|
|
|
|
return
|
|
|
|
}
|
2024-01-28 13:14:43 -06:00
|
|
|
w.showWidgetPlacement("drawTree()")
|
2024-01-18 00:08:37 -06:00
|
|
|
if draw {
|
|
|
|
// w.textResize()
|
2024-01-28 02:20:31 -06:00
|
|
|
w.showView()
|
2024-01-18 00:08:37 -06:00
|
|
|
} else {
|
2024-01-28 02:20:31 -06:00
|
|
|
w.deleteView()
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
|
2024-01-28 02:20:31 -06:00
|
|
|
for _, child := range w.children {
|
2024-01-28 11:07:51 -06:00
|
|
|
child.drawTree(draw)
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func click(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
// var l string
|
|
|
|
// var err error
|
|
|
|
|
2024-02-02 11:07:56 -06:00
|
|
|
log.Log(NOW, "click() START gocui name:", v.Name())
|
2024-01-18 00:08:37 -06:00
|
|
|
// n := me.rootNode.findWidgetName(v.Name())
|
2024-02-02 11:07:56 -06:00
|
|
|
w := findUnderMouse()
|
|
|
|
if w == nil {
|
|
|
|
log.Error(errors.New("click() could not find widget for view =" + v.Name()))
|
|
|
|
} else {
|
2024-01-28 11:07:51 -06:00
|
|
|
log.Log(NOW, "click() Found widget =", w.node.WidgetId, w.String(), ",", w.labelN)
|
|
|
|
w.doWidgetClick()
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:49:17 -06:00
|
|
|
rootTK := me.treeRoot.TK.(*guiWidget)
|
|
|
|
realTK := rootTK.findWidgetByView(v)
|
|
|
|
if realTK == nil {
|
|
|
|
log.Error(errors.New("toolkit click() out of reality with gocui. v.Name() not in binary tree " + v.Name()))
|
|
|
|
log.Log(NOW, "click() END FAILURE ON gocui v.Name =", v.Name())
|
|
|
|
// return nil // otherwise gocui exits
|
|
|
|
}
|
|
|
|
|
|
|
|
// double check the widget view really still exists
|
|
|
|
nameTK := rootTK.findWidgetByName(v.Name())
|
|
|
|
if nameTK == nil {
|
|
|
|
log.Error(errors.New("toolkit click() out of reality with gocui. v.Name() not in binary tree " + v.Name()))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if nameTK.v == nil {
|
|
|
|
log.Log(NOW, "click() maybe this widget has had it's view distroyed?", nameTK.cuiName, nameTK.WidgetType)
|
|
|
|
log.Log(NOW, "yep. it's gone now")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetCurrentView dies if it's sent an non-existent view
|
2024-01-18 00:08:37 -06:00
|
|
|
if _, err := g.SetCurrentView(v.Name()); err != nil {
|
2024-02-02 11:58:33 -06:00
|
|
|
log.Log(NOW, "click() END v.Name =", v.Name(), "err =", err)
|
2024-02-02 14:49:17 -06:00
|
|
|
// return err // return causes gocui.MainLoop() to exit. Do we ever want that to happen here?
|
|
|
|
return nil
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
|
2024-02-02 11:07:56 -06:00
|
|
|
log.Log(NOW, "click() END gocui name:", v.Name())
|
2024-01-18 00:08:37 -06:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-02-02 11:07:56 -06:00
|
|
|
func findUnderMouse() *guiWidget {
|
|
|
|
var widgets []*guiWidget
|
|
|
|
var f func(w *guiWidget)
|
2024-01-18 00:08:37 -06:00
|
|
|
w, h := me.baseGui.MousePosition()
|
|
|
|
|
2024-02-01 20:12:26 -06:00
|
|
|
// if the dropdown view is visable, close it
|
2024-02-02 11:07:56 -06:00
|
|
|
if me.dropdownV.Visible() {
|
|
|
|
me.dropdownV.dropdownClicked(w, h)
|
|
|
|
return me.dropdownV
|
2024-02-01 20:12:26 -06:00
|
|
|
}
|
|
|
|
|
2024-01-18 00:08:37 -06:00
|
|
|
// find buttons that are below where the mouse button click
|
2024-02-02 11:07:56 -06:00
|
|
|
f = func(widget *guiWidget) {
|
2024-01-18 00:08:37 -06:00
|
|
|
// ignore widgets that are not visible
|
2024-01-28 10:38:47 -06:00
|
|
|
if widget.Visible() {
|
2024-01-18 00:08:37 -06:00
|
|
|
if (widget.gocuiSize.w0 <= w) && (w <= widget.gocuiSize.w1) &&
|
|
|
|
(widget.gocuiSize.h0 <= h) && (h <= widget.gocuiSize.h1) {
|
2024-02-02 11:07:56 -06:00
|
|
|
widgets = append(widgets, widget)
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-28 02:20:31 -06:00
|
|
|
for _, child := range widget.children {
|
2024-02-02 11:07:56 -06:00
|
|
|
f(child)
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
}
|
2024-02-02 11:07:56 -06:00
|
|
|
rootW := me.treeRoot.TK.(*guiWidget)
|
|
|
|
f(rootW)
|
|
|
|
|
|
|
|
var found *guiWidget
|
2024-01-18 00:08:37 -06:00
|
|
|
// widgets has everything that matches
|
2024-02-02 11:07:56 -06:00
|
|
|
for _, w := range widgets {
|
|
|
|
w.showWidgetPlacement("findUnderMouse() FOUND")
|
|
|
|
// prioritize window buttons. This means if some code covers
|
|
|
|
// up the window widgets, then it will ignore everything else
|
|
|
|
// and allow the user (hopefully) to redraw or switch windows
|
|
|
|
// TODO: display the window widgets on top
|
|
|
|
if w.WidgetType == widget.Window {
|
|
|
|
return w
|
|
|
|
}
|
|
|
|
found = w
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
|
|
|
return found
|
|
|
|
}
|
|
|
|
|
|
|
|
// find the widget under the mouse click
|
|
|
|
func ctrlDown(g *gocui.Gui, v *gocui.View) error {
|
2024-02-02 11:07:56 -06:00
|
|
|
var found *guiWidget
|
2024-01-18 00:08:37 -06:00
|
|
|
// var widgets []*node
|
|
|
|
// var f func (n *node)
|
|
|
|
found = findUnderMouse()
|
|
|
|
if me.ctrlDown == nil {
|
|
|
|
setupCtrlDownWidget()
|
2024-01-28 02:20:31 -06:00
|
|
|
|
|
|
|
var tk *guiWidget
|
|
|
|
tk = me.ctrlDown.TK.(*guiWidget)
|
2024-01-28 03:33:08 -06:00
|
|
|
tk.labelN = found.String()
|
2024-01-28 02:20:31 -06:00
|
|
|
tk.cuiName = "ctrlDown"
|
2024-01-18 00:08:37 -06:00
|
|
|
// me.ctrlDown.parent = me.rootNode
|
|
|
|
}
|
2024-01-28 02:20:31 -06:00
|
|
|
var tk *guiWidget
|
|
|
|
tk = me.ctrlDown.TK.(*guiWidget)
|
2024-01-18 00:08:37 -06:00
|
|
|
if found == nil {
|
2024-02-02 11:07:56 -06:00
|
|
|
found = me.treeRoot.TK.(*guiWidget)
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
2024-01-28 03:33:08 -06:00
|
|
|
tk.labelN = found.String()
|
2024-02-02 11:07:56 -06:00
|
|
|
newR := found.realGocuiSize()
|
2024-01-28 02:20:31 -06:00
|
|
|
tk.gocuiSize.w0 = newR.w0
|
|
|
|
tk.gocuiSize.h0 = newR.h0
|
|
|
|
tk.gocuiSize.w1 = newR.w1
|
|
|
|
tk.gocuiSize.h1 = newR.h1
|
|
|
|
if tk.Visible() {
|
|
|
|
// me.ctrlDown.hideView()
|
2024-01-18 00:08:37 -06:00
|
|
|
} else {
|
2024-01-28 02:20:31 -06:00
|
|
|
// me.ctrlDown.showView()
|
2024-01-18 00:08:37 -06:00
|
|
|
}
|
2024-01-28 13:14:43 -06:00
|
|
|
// me.ctrlDown.showWidgetPlacement("ctrlDown:")
|
2024-01-18 00:08:37 -06:00
|
|
|
return nil
|
|
|
|
}
|