From 9f38585892d08690dde1b67b9a01006af308a949 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Fri, 31 Jan 2025 09:02:35 -0600 Subject: I'm trying to make this clearer to understand --- add.go | 94 -------------------------- draw.go | 112 ------------------------------ eventGocui.go | 85 +++++++++++++++++++++++ fakefile.go | 70 ------------------- gocui.go | 85 ----------------------- help.go | 2 +- showStdout.go | 119 -------------------------------- stdoutFakefile.go | 70 +++++++++++++++++++ stdoutShow.go | 119 ++++++++++++++++++++++++++++++++ treeAdd.go | 94 ++++++++++++++++++++++++++ treeDraw.go | 112 ++++++++++++++++++++++++++++++ treeWidget.go | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ widget.go | 198 ------------------------------------------------------ 13 files changed, 679 insertions(+), 679 deletions(-) delete mode 100644 add.go delete mode 100644 draw.go create mode 100644 eventGocui.go delete mode 100644 fakefile.go delete mode 100644 gocui.go delete mode 100644 showStdout.go create mode 100644 stdoutFakefile.go create mode 100644 stdoutShow.go create mode 100644 treeAdd.go create mode 100644 treeDraw.go create mode 100644 treeWidget.go delete mode 100644 widget.go diff --git a/add.go b/add.go deleted file mode 100644 index ea6103e..0000000 --- a/add.go +++ /dev/null @@ -1,94 +0,0 @@ -package main - -import ( - log "go.wit.com/log" - "go.wit.com/toolkits/tree" - "go.wit.com/widget" -) - -var fakeStartWidth int = me.FakeW -var fakeStartHeight int = me.TabH + me.FramePadH - -// setup fake labels for non-visible things off screen -func setFake(n *tree.Node) { - var w *guiWidget - w = n.TK.(*guiWidget) - w.isFake = true - - w.gocuiSetWH(fakeStartWidth, fakeStartHeight) - - fakeStartHeight += w.gocuiSize.Height() - // TODO: use the actual max hight of the terminal window - if fakeStartHeight > 24 { - fakeStartHeight = me.TabH - fakeStartWidth += me.FakeW - } -} - -// set the widget start width & height -// func (n *node) addWidget(n *tree.Node) { -func addWidget(n *tree.Node) { - var nw *guiWidget - nw = n.TK.(*guiWidget) - log.Log(INFO, "setStartWH() w.id =", n.WidgetId, "n.name", n.String()) - switch n.WidgetType { - case widget.Root: - log.Log(INFO, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.String()) - nw.color = &colorRoot - setFake(n) - return - case widget.Flag: - nw.color = &colorFlag - setFake(n) - return - case widget.Window: - nw.frame = false - // nw.color = &colorWindow - nw.setColor(&colorWindow) - wRoot := me.treeRoot.TK.(*guiWidget) - wRoot.redoWindows(0, 0) - // TODO: record the first window here? - // do initial setup of helper widgets here: - if me.dropdownV == nil { - me.dropdownV = makeDropdownView("addWidget() ddview") - } - return - case widget.Tab: - nw.color = &colorTab - // redoWindows(0,0) - return - case widget.Button: - nw.color = &colorButton - case widget.Checkbox: - nw.color = &colorCheckbox - case widget.Dropdown: - nw.color = &colorDropdown - case widget.Combobox: - nw.color = &colorCombobox - case widget.Box: - nw.color = &colorBox - nw.isFake = true - setFake(n) - return - case widget.Grid: - nw.color = &colorGrid - nw.isFake = true - setFake(n) - return - case widget.Group: - nw.color = &colorGroup - nw.frame = false - return - case widget.Label: - nw.color = &colorLabel - nw.frame = false - return - default: - /* - if n.IsCurrent() { - n.updateCurrent() - } - */ - } - nw.showWidgetPlacement("addWidget()") -} diff --git a/draw.go b/draw.go deleted file mode 100644 index 5b92d9e..0000000 --- a/draw.go +++ /dev/null @@ -1,112 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "strconv" - - "github.com/awesome-gocui/gocui" - log "go.wit.com/log" -) - -var toggle bool = true - -func (w *guiWidget) DrawAt(offsetW, offsetH int) { - w.setColor(&colorActiveW) - w.placeWidgets(offsetW, offsetH) // compute the sizes & places for each widget - w.active = false - w.showWidgets() -} - -func (w *guiWidget) toggleTree() { - if toggle { - w.drawTree(toggle) - toggle = false - } else { - w.hideWidgets() - toggle = true - } -} - -// display the widgets in the binary tree -func (w *guiWidget) drawTree(draw bool) { - if w == nil { - return - } - w.showWidgetPlacement("drawTree()") - if draw { - // w.textResize() - w.Show() - } else { - w.Hide() - } - - for _, child := range w.children { - child.drawTree(draw) - } -} - -// display's the text of the widget in gocui -// deletes the old view if it exists and recreates it -func (w *guiWidget) drawView() { - var err error - log.Log(INFO, "drawView() START", w.WidgetType, w.String()) - if me.baseGui == nil { - log.Log(ERROR, "drawView() ERROR: me.baseGui == nil", w) - return - } - - if w.cuiName == "" { - log.Log(ERROR, "drawView() w.cuiName was not set for widget", w) - w.cuiName = strconv.Itoa(w.node.WidgetId) + " TK" - } - log.Log(INFO, "drawView() labelN =", w.labelN) - - // this deletes the button from gocui - me.baseGui.DeleteView(w.cuiName) - w.v = nil - - w.textResize() - a := w.gocuiSize.w0 - b := w.gocuiSize.h0 - c := w.gocuiSize.w1 - d := w.gocuiSize.h1 - - w.v, err = me.baseGui.SetView(w.cuiName, a, b, c, d, 0) - if err == nil { - w.showWidgetPlacement("drawView()") - log.Log(ERROR, "drawView() internal plugin error err = nil") - return - } - if !errors.Is(err, gocui.ErrUnknownView) { - w.showWidgetPlacement("drawView()") - log.Log(ERROR, "drawView() internal plugin error error.IS()", err) - return - } - - // this sets up the keybinding for the name of the window - // does this really need to be done? I think we probably already - // know everything about where all the widgets are so we could bypass - // the gocui package and just handle all the mouse events internally here (?) - // for now, the w.v.Name is a string "1", "2", "3", etc from the widgetId - - // set the binding for this gocui view now that it has been created - // gocui handles overlaps of views so it will run on the view that is clicked on - me.baseGui.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click) - - // this actually sends the text to display to gocui - w.v.Wrap = true - w.v.Frame = w.frame - w.v.Clear() - fmt.Fprint(w.v, w.labelN) - - // if you don't do this here, it will be black & white only - if w.color != nil { - w.v.FrameColor = w.color.frame - w.v.FgColor = w.color.fg - w.v.BgColor = w.color.bg - w.v.SelFgColor = w.color.selFg - w.v.SelBgColor = w.color.selBg - } - log.Log(INFO, "drawView() END") -} diff --git a/eventGocui.go b/eventGocui.go new file mode 100644 index 0000000..c7f4011 --- /dev/null +++ b/eventGocui.go @@ -0,0 +1,85 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is (now) governed by the GPL 3.0 + +// Copyright 2014 The gocui Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "errors" + "fmt" + + "github.com/awesome-gocui/gocui" + + "go.wit.com/log" +) + +// Thanks to the gocui developers -- your package kicks ass +// This function is called on every event. It is a callback function from the gocui package +// which has an excellent implementation. While gocui handles things like text highlighting +// and the layout of the text areas -- also things like handling SIGWINCH and lots of really +// complicated console handling, it sends events here in a clean way. +// This is equivalent to the linux command xev (apt install x11-utils) +func gocuiEvent(g *gocui.Gui) error { + me.ecount += 1 + maxX, maxY := g.Size() + mx, my := g.MousePosition() + log.Verbose("handleEvent() START", maxX, maxY, mx, my, msgMouseDown) + if _, err := g.View("msg"); msgMouseDown && err == nil { + moveMsg(g) + } + if widgetView, _ := g.View("msg"); widgetView == nil { + log.Log(NOW, "handleEvent() create output widget now", maxX, maxY, mx, my) + makeOutputWidget(g, "this is a create before a mouse click") + if me.logStdout != nil { + // setOutput(me.logStdout) + // me.logStdout.Write("test out") + w := me.logStdout.TK.(*guiWidget) + msg := fmt.Sprintf("test out gocuiEvent() %d\n", me.ecount) + w.Write([]byte(msg)) + // log.CaptureMode(w) + log.Log(NOW, "logStdout test out") + } + } else { + log.Verbose("output widget already exists", maxX, maxY, mx, my) + } + mouseMove(g) + log.Verbose("handleEvent() END ", maxX, maxY, mx, my, msgMouseDown) + return nil +} + +func dragOutputWindow() { +} + +// turns off the frame on the global window +func setFrame(b bool) { + // TODO: figure out what this might be useful for + // what is this do? I made it just 2 lines for now. Is this useful for something? + v := SetView("global", 5, 10, 5, 10, 0) // x0, x1, y1, y2, overlap + if v == nil { + log.Log(ERROR, "setFrame() global failed") + } + v.Frame = b +} + +func quit(g *gocui.Gui, v *gocui.View) error { + return gocui.ErrQuit +} + +func SetView(name string, x0, y0, x1, y1 int, overlaps byte) *gocui.View { + if me.baseGui == nil { + log.Log(ERROR, "SetView() ERROR: me.baseGui == nil") + return nil + } + + v, err := me.baseGui.SetView(name, x0, y0, x1, y1, overlaps) + if err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + log.Log(ERROR, "SetView() global failed on name =", name) + } + return nil + } + return v +} diff --git a/fakefile.go b/fakefile.go deleted file mode 100644 index 5c54762..0000000 --- a/fakefile.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "bytes" - "errors" - "io" - - "github.com/awesome-gocui/gocui" -) - -type FakeFile struct { - reader *bytes.Reader - buffer *bytes.Buffer - offset int64 - view *gocui.View -} - -func (f *FakeFile) Read(p []byte) (n int, err error) { - n, err = f.reader.ReadAt(p, f.offset) - f.offset += int64(n) - return n, err -} - -var fakecount int = 0 - -func (f *FakeFile) Write(p []byte) (n int, err error) { - n, err = f.buffer.Write(p) - f.offset += int64(n) - f.reader.Reset(f.buffer.Bytes()) - f.view.Write(p) - fakecount += 1 - if fakecount > 20 { - fakecount = 0 - f.view.Clear() - } - return n, err -} - -func (f *FakeFile) Seek(offset int64, whence int) (int64, error) { - newOffset := f.offset - - switch whence { - case io.SeekStart: - newOffset = offset - case io.SeekCurrent: - newOffset += offset - case io.SeekEnd: - newOffset = int64(f.buffer.Len()) + offset - default: - return 0, errors.New("Seek: whence not at start,current or end") - } - // never can get here right? - - if newOffset < 0 { - return 0, errors.New("Seek: offset < 0") - } - - f.offset = newOffset - return f.offset, nil -} - -func NewFakeFile(v *gocui.View) *FakeFile { - buf := &bytes.Buffer{} - return &FakeFile{ - reader: bytes.NewReader(buf.Bytes()), - buffer: buf, - offset: 0, - view: v, - } -} diff --git a/gocui.go b/gocui.go deleted file mode 100644 index c7f4011..0000000 --- a/gocui.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2017-2025 WIT.COM Inc. All rights reserved. -// Use of this source code is (now) governed by the GPL 3.0 - -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "errors" - "fmt" - - "github.com/awesome-gocui/gocui" - - "go.wit.com/log" -) - -// Thanks to the gocui developers -- your package kicks ass -// This function is called on every event. It is a callback function from the gocui package -// which has an excellent implementation. While gocui handles things like text highlighting -// and the layout of the text areas -- also things like handling SIGWINCH and lots of really -// complicated console handling, it sends events here in a clean way. -// This is equivalent to the linux command xev (apt install x11-utils) -func gocuiEvent(g *gocui.Gui) error { - me.ecount += 1 - maxX, maxY := g.Size() - mx, my := g.MousePosition() - log.Verbose("handleEvent() START", maxX, maxY, mx, my, msgMouseDown) - if _, err := g.View("msg"); msgMouseDown && err == nil { - moveMsg(g) - } - if widgetView, _ := g.View("msg"); widgetView == nil { - log.Log(NOW, "handleEvent() create output widget now", maxX, maxY, mx, my) - makeOutputWidget(g, "this is a create before a mouse click") - if me.logStdout != nil { - // setOutput(me.logStdout) - // me.logStdout.Write("test out") - w := me.logStdout.TK.(*guiWidget) - msg := fmt.Sprintf("test out gocuiEvent() %d\n", me.ecount) - w.Write([]byte(msg)) - // log.CaptureMode(w) - log.Log(NOW, "logStdout test out") - } - } else { - log.Verbose("output widget already exists", maxX, maxY, mx, my) - } - mouseMove(g) - log.Verbose("handleEvent() END ", maxX, maxY, mx, my, msgMouseDown) - return nil -} - -func dragOutputWindow() { -} - -// turns off the frame on the global window -func setFrame(b bool) { - // TODO: figure out what this might be useful for - // what is this do? I made it just 2 lines for now. Is this useful for something? - v := SetView("global", 5, 10, 5, 10, 0) // x0, x1, y1, y2, overlap - if v == nil { - log.Log(ERROR, "setFrame() global failed") - } - v.Frame = b -} - -func quit(g *gocui.Gui, v *gocui.View) error { - return gocui.ErrQuit -} - -func SetView(name string, x0, y0, x1, y1 int, overlaps byte) *gocui.View { - if me.baseGui == nil { - log.Log(ERROR, "SetView() ERROR: me.baseGui == nil") - return nil - } - - v, err := me.baseGui.SetView(name, x0, y0, x1, y1, overlaps) - if err != nil { - if !errors.Is(err, gocui.ErrUnknownView) { - log.Log(ERROR, "SetView() global failed on name =", name) - } - return nil - } - return v -} diff --git a/help.go b/help.go index 8131b19..832cd9a 100644 --- a/help.go +++ b/help.go @@ -14,7 +14,7 @@ import ( var helpText []string = []string{"KEYBINDINGS", "", - "?: toggle help", + "?: toggle helps", "d: toggle debugging", "r: redraw widgets", "s/h: show/hide all widgets", diff --git a/showStdout.go b/showStdout.go deleted file mode 100644 index 4950e68..0000000 --- a/showStdout.go +++ /dev/null @@ -1,119 +0,0 @@ -package main - -import ( - "errors" - "fmt" - - "github.com/awesome-gocui/gocui" - - "go.wit.com/log" - "go.wit.com/widget" -) - -var outputW int = 180 -var outputH int = 40 - -func moveMsg(g *gocui.Gui) { - mx, my := g.MousePosition() - if !movingMsg && (mx != initialMouseX || my != initialMouseY) { - movingMsg = true - } - g.SetView("msg", mx-xOffset, my-yOffset, mx-xOffset+outputW, my-yOffset+outputH+me.FramePadH, 0) - me.startOutputW = mx - xOffset - me.startOutputH = my - yOffset - g.SetViewOnBottom("msg") -} - -func showMsg(g *gocui.Gui, v *gocui.View) error { - var l string - var err error - - log.Log(NOW, "showMsg() v.name =", v.Name()) - if _, err := g.SetCurrentView(v.Name()); err != nil { - return err - } - - _, cy := v.Cursor() - if l, err = v.Line(cy); err != nil { - l = "" - } - - outv := makeOutputWidget(g, l) - outv.Write([]byte("test out2")) - log.Info("test out2") - return nil -} - -func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View { - maxX, maxY := g.Size() - - if me.treeRoot == nil { - // keep skipping this until the binary tree is initialized - return nil - } - - if me.logStdout == nil { - a := new(widget.Action) - a.ProgName = "stdout" - a.WidgetType = widget.Stdout - a.WidgetId = -3 - a.ParentId = 0 - // n := addNode(a) - n := me.myTree.AddNode(a) - n.TK = initWidget(n) - me.logStdout = n - - var tk *guiWidget - tk = me.logStdout.TK.(*guiWidget) - // tk.gocuiSize.w0 = maxX - 32 - // tk.gocuiSize.h0 = maxY / 2 - tk.gocuiSize.w0 = me.startOutputW - tk.gocuiSize.h0 = me.startOutputH - tk.gocuiSize.w1 = tk.gocuiSize.w0 + outputW - tk.gocuiSize.h1 = tk.gocuiSize.h0 + outputH - } - v, err := g.View("msg") - if v == nil { - log.Log(NOW, "makeoutputwindow() this is supposed to happen. v == nil", err) - } else { - log.Log(NOW, "makeoutputwindow() msg != nil. WTF now? err =", err) - } - - // help, err := g.SetView("help", maxX-32, 0, maxX-1, 13, 0) - // v, err = g.SetView("msg", 3, 3, 30, 30, 0) - - if me.startOutputW == 0 { - me.startOutputW = maxX - 32 - } - if me.startOutputW == 0 { - me.startOutputH = maxY / 2 - } - - // v, err = g.SetView("msg", maxX-32, maxY/2, maxX/2+outputW, maxY/2+outputH, 0) - v, err = g.SetView("msg", me.startOutputW, me.startOutputH, maxX/2+outputW, maxY/2+outputH, 0) - if errors.Is(err, gocui.ErrUnknownView) { - log.Log(NOW, "makeoutputwindow() this is supposed to happen?", err) - } - - if err != nil { - log.Log(NOW, "makeoutputwindow() create output window failed", err) - return nil - } - - if v == nil { - log.Log(NOW, "makeoutputwindow() msg == nil. WTF now? err =", err) - return nil - } else { - var tk *guiWidget - tk = me.logStdout.TK.(*guiWidget) - tk.v = v - } - - v.Clear() - v.SelBgColor = gocui.ColorCyan - v.SelFgColor = gocui.ColorBlack - fmt.Fprintln(v, "figure out how to capture STDOUT to here\n"+stringFromMouseClick) - g.SetViewOnBottom("msg") - // g.SetViewOnBottom(v.Name()) - return v -} diff --git a/stdoutFakefile.go b/stdoutFakefile.go new file mode 100644 index 0000000..5c54762 --- /dev/null +++ b/stdoutFakefile.go @@ -0,0 +1,70 @@ +package main + +import ( + "bytes" + "errors" + "io" + + "github.com/awesome-gocui/gocui" +) + +type FakeFile struct { + reader *bytes.Reader + buffer *bytes.Buffer + offset int64 + view *gocui.View +} + +func (f *FakeFile) Read(p []byte) (n int, err error) { + n, err = f.reader.ReadAt(p, f.offset) + f.offset += int64(n) + return n, err +} + +var fakecount int = 0 + +func (f *FakeFile) Write(p []byte) (n int, err error) { + n, err = f.buffer.Write(p) + f.offset += int64(n) + f.reader.Reset(f.buffer.Bytes()) + f.view.Write(p) + fakecount += 1 + if fakecount > 20 { + fakecount = 0 + f.view.Clear() + } + return n, err +} + +func (f *FakeFile) Seek(offset int64, whence int) (int64, error) { + newOffset := f.offset + + switch whence { + case io.SeekStart: + newOffset = offset + case io.SeekCurrent: + newOffset += offset + case io.SeekEnd: + newOffset = int64(f.buffer.Len()) + offset + default: + return 0, errors.New("Seek: whence not at start,current or end") + } + // never can get here right? + + if newOffset < 0 { + return 0, errors.New("Seek: offset < 0") + } + + f.offset = newOffset + return f.offset, nil +} + +func NewFakeFile(v *gocui.View) *FakeFile { + buf := &bytes.Buffer{} + return &FakeFile{ + reader: bytes.NewReader(buf.Bytes()), + buffer: buf, + offset: 0, + view: v, + } +} diff --git a/stdoutShow.go b/stdoutShow.go new file mode 100644 index 0000000..4950e68 --- /dev/null +++ b/stdoutShow.go @@ -0,0 +1,119 @@ +package main + +import ( + "errors" + "fmt" + + "github.com/awesome-gocui/gocui" + + "go.wit.com/log" + "go.wit.com/widget" +) + +var outputW int = 180 +var outputH int = 40 + +func moveMsg(g *gocui.Gui) { + mx, my := g.MousePosition() + if !movingMsg && (mx != initialMouseX || my != initialMouseY) { + movingMsg = true + } + g.SetView("msg", mx-xOffset, my-yOffset, mx-xOffset+outputW, my-yOffset+outputH+me.FramePadH, 0) + me.startOutputW = mx - xOffset + me.startOutputH = my - yOffset + g.SetViewOnBottom("msg") +} + +func showMsg(g *gocui.Gui, v *gocui.View) error { + var l string + var err error + + log.Log(NOW, "showMsg() v.name =", v.Name()) + if _, err := g.SetCurrentView(v.Name()); err != nil { + return err + } + + _, cy := v.Cursor() + if l, err = v.Line(cy); err != nil { + l = "" + } + + outv := makeOutputWidget(g, l) + outv.Write([]byte("test out2")) + log.Info("test out2") + return nil +} + +func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View { + maxX, maxY := g.Size() + + if me.treeRoot == nil { + // keep skipping this until the binary tree is initialized + return nil + } + + if me.logStdout == nil { + a := new(widget.Action) + a.ProgName = "stdout" + a.WidgetType = widget.Stdout + a.WidgetId = -3 + a.ParentId = 0 + // n := addNode(a) + n := me.myTree.AddNode(a) + n.TK = initWidget(n) + me.logStdout = n + + var tk *guiWidget + tk = me.logStdout.TK.(*guiWidget) + // tk.gocuiSize.w0 = maxX - 32 + // tk.gocuiSize.h0 = maxY / 2 + tk.gocuiSize.w0 = me.startOutputW + tk.gocuiSize.h0 = me.startOutputH + tk.gocuiSize.w1 = tk.gocuiSize.w0 + outputW + tk.gocuiSize.h1 = tk.gocuiSize.h0 + outputH + } + v, err := g.View("msg") + if v == nil { + log.Log(NOW, "makeoutputwindow() this is supposed to happen. v == nil", err) + } else { + log.Log(NOW, "makeoutputwindow() msg != nil. WTF now? err =", err) + } + + // help, err := g.SetView("help", maxX-32, 0, maxX-1, 13, 0) + // v, err = g.SetView("msg", 3, 3, 30, 30, 0) + + if me.startOutputW == 0 { + me.startOutputW = maxX - 32 + } + if me.startOutputW == 0 { + me.startOutputH = maxY / 2 + } + + // v, err = g.SetView("msg", maxX-32, maxY/2, maxX/2+outputW, maxY/2+outputH, 0) + v, err = g.SetView("msg", me.startOutputW, me.startOutputH, maxX/2+outputW, maxY/2+outputH, 0) + if errors.Is(err, gocui.ErrUnknownView) { + log.Log(NOW, "makeoutputwindow() this is supposed to happen?", err) + } + + if err != nil { + log.Log(NOW, "makeoutputwindow() create output window failed", err) + return nil + } + + if v == nil { + log.Log(NOW, "makeoutputwindow() msg == nil. WTF now? err =", err) + return nil + } else { + var tk *guiWidget + tk = me.logStdout.TK.(*guiWidget) + tk.v = v + } + + v.Clear() + v.SelBgColor = gocui.ColorCyan + v.SelFgColor = gocui.ColorBlack + fmt.Fprintln(v, "figure out how to capture STDOUT to here\n"+stringFromMouseClick) + g.SetViewOnBottom("msg") + // g.SetViewOnBottom(v.Name()) + return v +} diff --git a/treeAdd.go b/treeAdd.go new file mode 100644 index 0000000..ea6103e --- /dev/null +++ b/treeAdd.go @@ -0,0 +1,94 @@ +package main + +import ( + log "go.wit.com/log" + "go.wit.com/toolkits/tree" + "go.wit.com/widget" +) + +var fakeStartWidth int = me.FakeW +var fakeStartHeight int = me.TabH + me.FramePadH + +// setup fake labels for non-visible things off screen +func setFake(n *tree.Node) { + var w *guiWidget + w = n.TK.(*guiWidget) + w.isFake = true + + w.gocuiSetWH(fakeStartWidth, fakeStartHeight) + + fakeStartHeight += w.gocuiSize.Height() + // TODO: use the actual max hight of the terminal window + if fakeStartHeight > 24 { + fakeStartHeight = me.TabH + fakeStartWidth += me.FakeW + } +} + +// set the widget start width & height +// func (n *node) addWidget(n *tree.Node) { +func addWidget(n *tree.Node) { + var nw *guiWidget + nw = n.TK.(*guiWidget) + log.Log(INFO, "setStartWH() w.id =", n.WidgetId, "n.name", n.String()) + switch n.WidgetType { + case widget.Root: + log.Log(INFO, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.String()) + nw.color = &colorRoot + setFake(n) + return + case widget.Flag: + nw.color = &colorFlag + setFake(n) + return + case widget.Window: + nw.frame = false + // nw.color = &colorWindow + nw.setColor(&colorWindow) + wRoot := me.treeRoot.TK.(*guiWidget) + wRoot.redoWindows(0, 0) + // TODO: record the first window here? + // do initial setup of helper widgets here: + if me.dropdownV == nil { + me.dropdownV = makeDropdownView("addWidget() ddview") + } + return + case widget.Tab: + nw.color = &colorTab + // redoWindows(0,0) + return + case widget.Button: + nw.color = &colorButton + case widget.Checkbox: + nw.color = &colorCheckbox + case widget.Dropdown: + nw.color = &colorDropdown + case widget.Combobox: + nw.color = &colorCombobox + case widget.Box: + nw.color = &colorBox + nw.isFake = true + setFake(n) + return + case widget.Grid: + nw.color = &colorGrid + nw.isFake = true + setFake(n) + return + case widget.Group: + nw.color = &colorGroup + nw.frame = false + return + case widget.Label: + nw.color = &colorLabel + nw.frame = false + return + default: + /* + if n.IsCurrent() { + n.updateCurrent() + } + */ + } + nw.showWidgetPlacement("addWidget()") +} diff --git a/treeDraw.go b/treeDraw.go new file mode 100644 index 0000000..5b92d9e --- /dev/null +++ b/treeDraw.go @@ -0,0 +1,112 @@ +package main + +import ( + "errors" + "fmt" + "strconv" + + "github.com/awesome-gocui/gocui" + log "go.wit.com/log" +) + +var toggle bool = true + +func (w *guiWidget) DrawAt(offsetW, offsetH int) { + w.setColor(&colorActiveW) + w.placeWidgets(offsetW, offsetH) // compute the sizes & places for each widget + w.active = false + w.showWidgets() +} + +func (w *guiWidget) toggleTree() { + if toggle { + w.drawTree(toggle) + toggle = false + } else { + w.hideWidgets() + toggle = true + } +} + +// display the widgets in the binary tree +func (w *guiWidget) drawTree(draw bool) { + if w == nil { + return + } + w.showWidgetPlacement("drawTree()") + if draw { + // w.textResize() + w.Show() + } else { + w.Hide() + } + + for _, child := range w.children { + child.drawTree(draw) + } +} + +// display's the text of the widget in gocui +// deletes the old view if it exists and recreates it +func (w *guiWidget) drawView() { + var err error + log.Log(INFO, "drawView() START", w.WidgetType, w.String()) + if me.baseGui == nil { + log.Log(ERROR, "drawView() ERROR: me.baseGui == nil", w) + return + } + + if w.cuiName == "" { + log.Log(ERROR, "drawView() w.cuiName was not set for widget", w) + w.cuiName = strconv.Itoa(w.node.WidgetId) + " TK" + } + log.Log(INFO, "drawView() labelN =", w.labelN) + + // this deletes the button from gocui + me.baseGui.DeleteView(w.cuiName) + w.v = nil + + w.textResize() + a := w.gocuiSize.w0 + b := w.gocuiSize.h0 + c := w.gocuiSize.w1 + d := w.gocuiSize.h1 + + w.v, err = me.baseGui.SetView(w.cuiName, a, b, c, d, 0) + if err == nil { + w.showWidgetPlacement("drawView()") + log.Log(ERROR, "drawView() internal plugin error err = nil") + return + } + if !errors.Is(err, gocui.ErrUnknownView) { + w.showWidgetPlacement("drawView()") + log.Log(ERROR, "drawView() internal plugin error error.IS()", err) + return + } + + // this sets up the keybinding for the name of the window + // does this really need to be done? I think we probably already + // know everything about where all the widgets are so we could bypass + // the gocui package and just handle all the mouse events internally here (?) + // for now, the w.v.Name is a string "1", "2", "3", etc from the widgetId + + // set the binding for this gocui view now that it has been created + // gocui handles overlaps of views so it will run on the view that is clicked on + me.baseGui.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click) + + // this actually sends the text to display to gocui + w.v.Wrap = true + w.v.Frame = w.frame + w.v.Clear() + fmt.Fprint(w.v, w.labelN) + + // if you don't do this here, it will be black & white only + if w.color != nil { + w.v.FrameColor = w.color.frame + w.v.FgColor = w.color.fg + w.v.BgColor = w.color.bg + w.v.SelFgColor = w.color.selFg + w.v.SelBgColor = w.color.selBg + } + log.Log(INFO, "drawView() END") +} diff --git a/treeWidget.go b/treeWidget.go new file mode 100644 index 0000000..d72f957 --- /dev/null +++ b/treeWidget.go @@ -0,0 +1,198 @@ +package main + +import ( + "strconv" + + "github.com/awesome-gocui/gocui" + "go.wit.com/log" + "go.wit.com/toolkits/tree" + "go.wit.com/widget" +) + +func initWidget(n *tree.Node) *guiWidget { + var w *guiWidget + w = new(guiWidget) + + w.node = n + w.cuiName = strconv.Itoa(w.node.WidgetId) + " TK" + w.WidgetType = n.WidgetType + w.labelN = n.State.Label + if w.labelN == "" { + // remove this debugging hack once things are stable and fixed + w.labelN = n.GetProgName() + } + w.frame = true + w.enable = n.State.Enable + + if n.WidgetType == widget.Root { + log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId) + } + + if n.WidgetType == widget.Grid { + w.widths = make(map[int]int) // how tall each row in the grid is + w.heights = make(map[int]int) // how wide each column in the grid is + } + + p := n.Parent + if p == nil { + log.Log(ERROR, "parent == nil", w.String(), n.WidgetId, w.WidgetType) + return w + } + if p.TK == nil { + log.Log(ERROR, "parent.TK == nil", w.String(), n.WidgetId, w.WidgetType) + return w + } + + // set the parent and append to parent children + var ptk *guiWidget + ptk = p.TK.(*guiWidget) + w.parent = ptk + ptk.children = append(ptk.children, w) + return w +} + +func setupCtrlDownWidget() { + a := new(widget.Action) + a.ProgName = "ctrlDown" + a.WidgetType = widget.Dialog + a.WidgetId = -1 + a.ParentId = 0 + // n := addNode(a) + n := me.myTree.AddNode(a) + + me.ctrlDown = n +} + +func (w *guiWidget) deleteView() { + // make sure the view isn't really there + log.Log(GOCUI, "deleteView()", w.cuiName, w.WidgetType, w.node.WidgetId) + me.baseGui.DeleteView(w.cuiName) + w.v = nil +} + +func (w *guiWidget) IsCurrent() bool { + if w.node.WidgetType == widget.Tab { + return w.isCurrent + } + if w.node.WidgetType == widget.Window { + log.Log(GOCUI, "IsCurrent() found current window", w.cuiName, w.String()) + log.Log(GOCUI, "IsCurrent() window w.isCurrent =", w.isCurrent) + return w.isCurrent + } + if w.node.WidgetType == widget.Root { + return false + } + return w.parent.IsCurrent() +} + +func (tk *guiWidget) String() string { + return tk.node.String() +} + +func (tk *guiWidget) Visible() bool { + if tk == nil { + return false + } + if tk.v == nil { + return false + } + tk.v.Visible = true + return true +} + +func (w *guiWidget) Show() { + // always should the dropdown widget + if w == me.dropdownV { + me.dropdownV.drawView() + return + } + + // don't display fake widgets + if w.isFake { + return + } + + // if this isn't in the binary tree + // it's some internal widget so always display those + if w.node == nil { + w.drawView() + return + } + + // always show window titles + if w.node.WidgetType == widget.Window { + w.drawView() + return + } + + if w.node.WidgetType == widget.Dropdown { + log.Log(NOW, "Show() dropdown", w.cuiName, w.String()) + log.Log(NOW, "Show() dropdown n.Strings() =", w.node.Strings()) + } + if w.node.WidgetType == widget.Combobox { + log.Log(NOW, "Show() dropdown", w.cuiName, w.String()) + log.Log(NOW, "Show() dropdown n.Strings() =", w.node.Strings()) + } + + // if the widget is not in the current displayed windo + // then ignore it + log.Log(GOCUI, "Show() widget =", w.cuiName, w.String()) + log.Log(GOCUI, "Show() w.IsCurrent() returned", w.IsCurrent()) + if !w.IsCurrent() { + log.Log(GOCUI, "Show() NOT drawing", w.cuiName, w.String()) + return + } + log.Log(GOCUI, "Show() drawing", w.cuiName, w.String()) + + // finally, check if the widget State is hidden or not + if w.node.Hidden() { + // don't display hidden widgets + return + } + + // okay, if you made it this far, then display the widget + w.drawView() +} + +func (tk *guiWidget) Hide() { + tk.deleteView() +} + +func (tk *guiWidget) SetVisible(b bool) { + if b { + tk.Show() + } else { + tk.Hide() + } +} + +func (tk *guiWidget) findWidgetByName(name string) *guiWidget { + if tk.cuiName == name { + return tk + } + for _, child := range tk.children { + found := child.findWidgetByName(name) + if found != nil { + return found + } + } + return nil +} + +func (tk *guiWidget) findWidgetByView(v *gocui.View) *guiWidget { + if tk.v == v { + return tk + } + if tk.cuiName == v.Name() { + log.Log(NOW, "findWidget() error. names are mismatched or out of sync", tk.cuiName) + log.Log(NOW, "findWidget() or maybe the view has been deleted") + // return tk + } + for _, child := range tk.children { + found := child.findWidgetByView(v) + if found != nil { + return found + } + } + return nil +} diff --git a/widget.go b/widget.go deleted file mode 100644 index d72f957..0000000 --- a/widget.go +++ /dev/null @@ -1,198 +0,0 @@ -package main - -import ( - "strconv" - - "github.com/awesome-gocui/gocui" - "go.wit.com/log" - "go.wit.com/toolkits/tree" - "go.wit.com/widget" -) - -func initWidget(n *tree.Node) *guiWidget { - var w *guiWidget - w = new(guiWidget) - - w.node = n - w.cuiName = strconv.Itoa(w.node.WidgetId) + " TK" - w.WidgetType = n.WidgetType - w.labelN = n.State.Label - if w.labelN == "" { - // remove this debugging hack once things are stable and fixed - w.labelN = n.GetProgName() - } - w.frame = true - w.enable = n.State.Enable - - if n.WidgetType == widget.Root { - log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId) - } - - if n.WidgetType == widget.Grid { - w.widths = make(map[int]int) // how tall each row in the grid is - w.heights = make(map[int]int) // how wide each column in the grid is - } - - p := n.Parent - if p == nil { - log.Log(ERROR, "parent == nil", w.String(), n.WidgetId, w.WidgetType) - return w - } - if p.TK == nil { - log.Log(ERROR, "parent.TK == nil", w.String(), n.WidgetId, w.WidgetType) - return w - } - - // set the parent and append to parent children - var ptk *guiWidget - ptk = p.TK.(*guiWidget) - w.parent = ptk - ptk.children = append(ptk.children, w) - return w -} - -func setupCtrlDownWidget() { - a := new(widget.Action) - a.ProgName = "ctrlDown" - a.WidgetType = widget.Dialog - a.WidgetId = -1 - a.ParentId = 0 - // n := addNode(a) - n := me.myTree.AddNode(a) - - me.ctrlDown = n -} - -func (w *guiWidget) deleteView() { - // make sure the view isn't really there - log.Log(GOCUI, "deleteView()", w.cuiName, w.WidgetType, w.node.WidgetId) - me.baseGui.DeleteView(w.cuiName) - w.v = nil -} - -func (w *guiWidget) IsCurrent() bool { - if w.node.WidgetType == widget.Tab { - return w.isCurrent - } - if w.node.WidgetType == widget.Window { - log.Log(GOCUI, "IsCurrent() found current window", w.cuiName, w.String()) - log.Log(GOCUI, "IsCurrent() window w.isCurrent =", w.isCurrent) - return w.isCurrent - } - if w.node.WidgetType == widget.Root { - return false - } - return w.parent.IsCurrent() -} - -func (tk *guiWidget) String() string { - return tk.node.String() -} - -func (tk *guiWidget) Visible() bool { - if tk == nil { - return false - } - if tk.v == nil { - return false - } - tk.v.Visible = true - return true -} - -func (w *guiWidget) Show() { - // always should the dropdown widget - if w == me.dropdownV { - me.dropdownV.drawView() - return - } - - // don't display fake widgets - if w.isFake { - return - } - - // if this isn't in the binary tree - // it's some internal widget so always display those - if w.node == nil { - w.drawView() - return - } - - // always show window titles - if w.node.WidgetType == widget.Window { - w.drawView() - return - } - - if w.node.WidgetType == widget.Dropdown { - log.Log(NOW, "Show() dropdown", w.cuiName, w.String()) - log.Log(NOW, "Show() dropdown n.Strings() =", w.node.Strings()) - } - if w.node.WidgetType == widget.Combobox { - log.Log(NOW, "Show() dropdown", w.cuiName, w.String()) - log.Log(NOW, "Show() dropdown n.Strings() =", w.node.Strings()) - } - - // if the widget is not in the current displayed windo - // then ignore it - log.Log(GOCUI, "Show() widget =", w.cuiName, w.String()) - log.Log(GOCUI, "Show() w.IsCurrent() returned", w.IsCurrent()) - if !w.IsCurrent() { - log.Log(GOCUI, "Show() NOT drawing", w.cuiName, w.String()) - return - } - log.Log(GOCUI, "Show() drawing", w.cuiName, w.String()) - - // finally, check if the widget State is hidden or not - if w.node.Hidden() { - // don't display hidden widgets - return - } - - // okay, if you made it this far, then display the widget - w.drawView() -} - -func (tk *guiWidget) Hide() { - tk.deleteView() -} - -func (tk *guiWidget) SetVisible(b bool) { - if b { - tk.Show() - } else { - tk.Hide() - } -} - -func (tk *guiWidget) findWidgetByName(name string) *guiWidget { - if tk.cuiName == name { - return tk - } - for _, child := range tk.children { - found := child.findWidgetByName(name) - if found != nil { - return found - } - } - return nil -} - -func (tk *guiWidget) findWidgetByView(v *gocui.View) *guiWidget { - if tk.v == v { - return tk - } - if tk.cuiName == v.Name() { - log.Log(NOW, "findWidget() error. names are mismatched or out of sync", tk.cuiName) - log.Log(NOW, "findWidget() or maybe the view has been deleted") - // return tk - } - for _, child := range tk.children { - found := child.findWidgetByView(v) - if found != nil { - return found - } - } - return nil -} -- cgit v1.2.3