// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 package main import ( "fmt" "io" "os" "unicode" "go.wit.com/log" ) // this file is named poorly. It has more than Sort() func untitle(s string) string { if s == "" { return s } runes := []rune(s) runes[0] = unicode.ToLower(runes[0]) return string(runes) } func (pb *Files) makeGuiFile(pf *File) error { newf, _ := os.OpenFile(pf.Filebase+".gui.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) defer newf.Close() headerGui(newf, pf) fmt.Fprintf(newf, "// START GUI\n") fmt.Fprintf(newf, "\n") /* FRUITS := pf.Bases.Name FRUIT := pf.Base.Name fruitVars := pf.Base.Vars pf.generateAutoTablePB(newf, FRUITS, FRUIT, fruitVars) */ for _, msg := range pf.allMsg() { if msg.DoGui { color := pf.findMsg(msg.GuiVarName) if color == nil { return fmt.Errorf("failed to find struct %s", msg.GuiVarName) } FRUITS := msg.Name FRUIT := msg.GuiVarName fruitVars := color.Vars pf.generateAutoTablePB(newf, FRUITS, FRUIT, fruitVars) log.Printf("Added GUI functions for protobuf '%s' with record '%s' using mutex '%s'\n", msg.Name, msg.GuiVarName, color.Lockname) } } fmt.Fprintf(newf, "\n") fmt.Fprintf(newf, "// END GUI\n") return nil } func (pf *File) generateAutoTablePB(newf *os.File, FRUITS string, FRUIT string, fruitVars []*MsgVar) { fRUITS := untitle(FRUITS) fRUIT := untitle(FRUIT) guiMain(newf, FRUITS, FRUIT) guiStringFuncs(newf, pf.Package, FRUITS, FRUIT) for _, v := range fruitVars { if v.IsRepeated { // can't work against slices continue } if v.VarType == "string" { log.Printf("make Add function here %s %s %s\n", FRUITS, FRUIT, v.VarName) guiAddStringFunc(newf, FRUITS, FRUIT, v.VarName) continue } if v.VarType == "int64" { log.Printf("make Add function here %s %s %s\n", FRUITS, FRUIT, v.VarName) guiAddIntFunc(newf, FRUITS, FRUIT, v.VarName) continue } /* continue if !v.HasSort { continue } if v.VarType != "string" { continue } VARNAME := v.VarName funcdef := msg.newSortType(wSort, PARENT, VARNAME) log.Printf("Adding %s\n", funcdef) */ } guiUpdate(newf, FRUITS, FRUIT) guiTableDelete(newf, FRUITS, FRUIT) guiTableCustom(newf, FRUITS, fRUITS, FRUIT, fRUIT) } func headerGui(w io.Writer, pf *File) { // header must come first headerComment(w) fmt.Fprintf(w, "package %s\n", pf.Package) fmt.Fprintln(w, "") fmt.Fprintln(w, "import (") fmt.Fprintln(w, " \"time\"") fmt.Fprintln(w, "") fmt.Fprintln(w, " \"go.wit.com/gui\"") fmt.Fprintln(w, " \"go.wit.com/lib/protobuf/guipb\"") fmt.Fprintln(w, " \"go.wit.com/log\"") fmt.Fprintln(w, " anypb \"google.golang.org/protobuf/types/known/anypb\"") fmt.Fprintln(w, " timestamppb \"google.golang.org/protobuf/types/known/timestamppb\"") fmt.Fprintln(w, ")") fmt.Fprintln(w, "") } func guiMain(w io.Writer, FRUITS string, FRUIT string) { fmt.Fprintln(w, "func (x *"+FRUITS+") NewTable(title string) *"+FRUITS+"Table {") fmt.Fprintln(w, " t := new("+FRUITS+"Table)") fmt.Fprintln(w, " t.x = x") fmt.Fprintln(w, " pb := new(guipb.Table)") fmt.Fprintln(w, " pb.Title = title") fmt.Fprintln(w, " t.pb = pb") fmt.Fprintln(w, " return t") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddStringFunc(title string, f func(*"+FRUIT+") string) *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, "") fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " }") fmt.Fprintln(w, " sf.order = t.order") fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)") fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_STRING") fmt.Fprintln(w, "") fmt.Fprintln(w, " t.order += 1") fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)") fmt.Fprintln(w, " return sf") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddButtonFunc(title string, f func(*"+FRUIT+") string) *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, "") fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " }") fmt.Fprintln(w, " sf.order = t.order") fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)") fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_STRING") fmt.Fprintln(w, " sf.attr.Click = true") fmt.Fprintln(w, "") fmt.Fprintln(w, " t.order += 1") fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)") fmt.Fprintln(w, " return sf") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddIntFunc(title string, f func(*"+FRUIT+") int) *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, "") fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " }") fmt.Fprintln(w, " sf.order = t.order") fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)") fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_INT") fmt.Fprintln(w, "") fmt.Fprintln(w, " t.order += 1") fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)") fmt.Fprintln(w, " return sf") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddTimeFunc(title string, f func(*"+FRUIT+") time.Time) *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, "") fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " }") fmt.Fprintln(w, " sf.order = t.order") fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)") fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_TIME") fmt.Fprintln(w, "") fmt.Fprintln(w, " t.order += 1") fmt.Fprintln(w, " // t.timeFuncs = append(t.timeFuncs, sf)") fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)") fmt.Fprintln(w, " return sf") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (sf *"+FRUIT+"AnyFunc) SetTitle(title string) {") fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) SetParent(p *gui.Node) {") fmt.Fprintln(w, " mt.parent = p") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) ShowTable() {") fmt.Fprintln(w, " // log.Info(\"ShowTable() SENDING TO GUI\")") fmt.Fprintln(w, " mt.MakeTable()") /* fmt.Fprintln(w, " if mt.parent == nil {") fmt.Fprintln(w, " gui.ShowTable(mt.pb)") fmt.Fprintln(w, " return") fmt.Fprintln(w, " }") */ fmt.Fprintln(w, " mt.parent.ShowTable(mt.pb)") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "type "+FRUIT+"AnyFunc struct {") fmt.Fprintln(w, " title string") fmt.Fprintln(w, " f func(*"+FRUIT+") any") fmt.Fprintln(w, " Custom func(*"+FRUIT+")") fmt.Fprintln(w, " order int") fmt.Fprintln(w, " Width int") fmt.Fprintln(w, " attr *guipb.ColAttr") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "type "+FRUITS+"Table struct {") fmt.Fprintln(w, " pb *guipb.Table") fmt.Fprintln(w, " parent *gui.Node") fmt.Fprintln(w, " x *"+FRUITS+"") fmt.Fprintln(w, " hostnames []string") fmt.Fprintln(w, "") fmt.Fprintln(w, " anyFuncs []*"+FRUIT+"AnyFunc") fmt.Fprintln(w, "") fmt.Fprintln(w, " CustomFunc func(*"+FRUIT+")") fmt.Fprintln(w, " order int") fmt.Fprintln(w, "}") } func guiStringFuncs(w io.Writer, ZOOPB string, FRUITS string, FRUIT string) { fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) doAnyFunc(name string) bool {") fmt.Fprintln(w, " for _, sf := range mt.anyFuncs {") fmt.Fprintln(w, " if sf.title != name {") fmt.Fprintln(w, " continue") fmt.Fprintln(w, " }") fmt.Fprintln(w, " r := new(guipb.AnyCol)") fmt.Fprintln(w, " r.Header = new(guipb.Widget)") fmt.Fprintln(w, " r.Header.Name = name") fmt.Fprintln(w, " r.Attr = proto.Clone(sf.attr).(*guipb.ColAttr)") fmt.Fprintln(w, "") fmt.Fprintln(w, " for m := range mt.x.IterAll() {") fmt.Fprintln(w, " t := sf.f(m)") fmt.Fprintln(w, " switch r.Attr.Type {") fmt.Fprintln(w, " case guipb.ColAttr_STRING:") fmt.Fprintln(w, " // anyProto, err := anypb.New(tsProto)") fmt.Fprintln(w, " stringValue := wrapperspb.String(t.(string))") fmt.Fprintln(w, " anyProto, err := anypb.New(stringValue)") fmt.Fprintln(w, " _ = err // do something with err someday (?)") fmt.Fprintln(w, " r.Vals = append(r.Vals, anyProto)") fmt.Fprintln(w, " // return col.Vals[row] true") fmt.Fprintln(w, " case guipb.ColAttr_INT:") fmt.Fprintln(w, " var finalInt int") fmt.Fprintln(w, " finalInt = t.(int)") fmt.Fprintln(w, " intVal := wrapperspb.Int32(int32(finalInt))") fmt.Fprintln(w, " anyProto, _ := anypb.New(intVal)") fmt.Fprintln(w, " r.Vals = append(r.Vals, anyProto)") fmt.Fprintln(w, " case guipb.ColAttr_DURATION:") fmt.Fprintln(w, " case guipb.ColAttr_TIME:") fmt.Fprintln(w, " var goTime time.Time") fmt.Fprintln(w, " goTime = t.(time.Time)") fmt.Fprintln(w, " tsProto := timestamppb.New(goTime)") fmt.Fprintln(w, " anyProto, err := anypb.New(tsProto)") fmt.Fprintln(w, " _ = err // do something with err someday (?)") fmt.Fprintln(w, " r.Vals = append(r.Vals, anyProto)") fmt.Fprintln(w, " default:") fmt.Fprintln(w, " log.Info(\"cell unhandled type\", r.Attr.Type)") fmt.Fprintln(w, " }") fmt.Fprintln(w, " // cellTime := r.Vals[row]") fmt.Fprintln(w, " // s := shell.FormatDuration(time.Since(cellTime.AsTime()))") fmt.Fprintln(w, " }") fmt.Fprintln(w, "") fmt.Fprintln(w, " mt.pb.AnyCols = append(mt.pb.AnyCols, r)") fmt.Fprintln(w, " return true") fmt.Fprintln(w, " }") fmt.Fprintln(w, " return false") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) MakeTable() {") fmt.Fprintln(w, " for _, name := range mt.pb.Order {") fmt.Fprintln(w, " if mt.doAnyFunc(name) {") fmt.Fprintln(w, " continue") fmt.Fprintln(w, " }") fmt.Fprintln(w, " }") fmt.Fprintln(w, "}") } func guiAddStringFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) { fmt.Fprintln(w, "") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) Add"+BRAND+"() *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, " sf := t.AddStringFunc(\""+BRAND+"\", func(m *"+FRUIT+") string {") fmt.Fprintln(w, " return m."+BRAND+"") fmt.Fprintln(w, " })") fmt.Fprintln(w, " return sf") fmt.Fprintln(w, "}") } func guiAddIntFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) { fmt.Fprintln(w, "") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) Add"+BRAND+"() *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, " custf := t.AddIntFunc(\""+BRAND+"\", func(m *"+FRUIT+") int {") fmt.Fprintln(w, " return int(m."+BRAND+")") fmt.Fprintln(w, " })") fmt.Fprintln(w, " return custf") fmt.Fprintln(w, "}") } func guiUpdate(w io.Writer, FRUITS string, FRUIT string) { fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) NewUuid() {") fmt.Fprintln(w, " mt.pb.Uuid = uuid.New().String()") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "// START TABLE UPDATE (doesn't work yet)") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) dumpStringFunc(name string) {") fmt.Fprintln(w, " for i, r := range mt.pb.StringCols {") fmt.Fprintln(w, " // log.Info(\"could use\", i, r.Header.Name, \"for name =\", name)") fmt.Fprintln(w, " if r.Header.Name == name {") fmt.Fprintln(w, " log.Info(\"dump Strings row\", i, r.Header.Name, r.Vals)") fmt.Fprintln(w, " break") fmt.Fprintln(w, " }") fmt.Fprintln(w, " }") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") } func guiTableDelete(w io.Writer, FRUITS string, FRUIT string) { fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) Delete() {") fmt.Fprintln(w, " if mt == nil {") fmt.Fprintln(w, " log.Info(\"mt == nil table already deleted\")") fmt.Fprintln(w, " return") fmt.Fprintln(w, " }") fmt.Fprintln(w, " // log.Info(\"table Delete here\")") fmt.Fprintln(w, " mt.parent.DeleteTable(mt.pb)") fmt.Fprintln(w, "}") } func guiTableCustom(w io.Writer, FRUITS string, fRUITS string, FRUIT string, fRUIT string) { fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) "+fRUITS+"Custom(w *guipb.Widget) {") fmt.Fprintln(w, " row := mt.x."+FRUITS+"[w.Location.Y-1]") fmt.Fprintln(w, " // log.Info(\"got to "+fRUITS+"Custom() with\", w.Location.X, w.Location.Y-1)") fmt.Fprintln(w, "") fmt.Fprintln(w, " for _, sf := range mt.anyFuncs {") fmt.Fprintln(w, " if sf.order == int(w.Location.X) {") fmt.Fprintln(w, " // log.Info(\"found order\", sf.order)") fmt.Fprintln(w, " if sf.Custom != nil {") fmt.Fprintln(w, " log.Info(\"doing Custom() func for button\")") fmt.Fprintln(w, " sf.Custom(row)") fmt.Fprintln(w, " return") fmt.Fprintln(w, " }") fmt.Fprintln(w, " }") fmt.Fprintln(w, " }") fmt.Fprintln(w, " mt.CustomFunc(row)") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) Custom(f func(*"+FRUIT+")) {") fmt.Fprintln(w, " mt.pb.RegisterCustom(mt."+fRUITS+"Custom)") fmt.Fprintln(w, " mt.CustomFunc = f") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) GetUuid() string {") fmt.Fprintln(w, " return mt.pb.Uuid") fmt.Fprintln(w, "}") fmt.Fprintln(w, "// END TABLE UPDATE") }