// Although most code from WIT.COM Inc is under the GPL // This code is more generic because it must be able // to be used in any GUI plugin package tree import ( "fmt" "time" "go.wit.com/lib/gui/shell" "go.wit.com/lib/protobuf/guipb" "go.wit.com/log" "go.wit.com/widget" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/timestamppb" ) // repeated string order = 1; // // repeated StringRow StringRows = 2; // repeated IntRow IntRows = 3; // repeated TimeRow TimeRows = 4; // repeated BoolRow BoolRows = 5; func (me *TreeInfo) doTable(a widget.Action) { if a.TablePB == nil { log.Log(TREE, "tree: action didn't have a Table PB") return } pb := guipb.NewTables() if err := pb.Unmarshal(a.TablePB); err != nil { log.Info("unmarshal error", err, "data len =", len(a.TablePB)) return } log.Info("tree.doTables() start. # of tables:", len(pb.Tables)) all := pb.All() for all.Scan() { t := all.Next() // for i, o := range t.Order { // log.Info("got order:", t.Title, i, o) // } // dumpTable(t) // me.ShowTable(t) log.Info("TREE FOUND TABLE UUID", t.Uuid) for i, ot := range me.currentTables { log.Info("TREE already has UUID", i, ot.Uuid) if t.Uuid == ot.Uuid { log.Info("TREE found UUID! update table here", i, ot.Uuid) me.updateTable(t) return } } me.currentTables = append(me.currentTables, t) me.makeTable(t) } } func makeTableWindow(pb *guipb.Widget) *Node { a := new(widget.Action) a.WidgetType = widget.Window a.WidgetId = int(pb.Id) a.ParentId = 0 a.State.Enable = true return AddNode(a) } func (win *Node) makeWindowGrid(pb *guipb.Widget) *Node { a := new(widget.Action) a.WidgetType = widget.Grid a.WidgetId = int(pb.Id) a.ParentId = win.WidgetId a.State.Enable = true return AddNode(a) } func (grid *Node) makeGridLabel(pb *guipb.Widget, w int, h int) *Node { a := new(widget.Action) a.WidgetType = widget.Label a.WidgetId = int(pb.Id) a.ParentId = grid.WidgetId a.State.Enable = true a.State.Label = pb.Name a.State.AtW = w a.State.AtH = h a.State.GridOffset.X = w a.State.GridOffset.Y = h // log.Info("makeGridLabel()", a.State) return AddNode(a) } func (me *TreeInfo) updateTable(t *guipb.Table) { log.Info("todo: compare table here...") for _, name := range t.Order { me.updateRow(t, name) } } func (me *TreeInfo) updateRow(t *guipb.Table, name string) { for _, r := range t.StringRows { if name == r.Header.Name { id := r.Header.Id n := treeRoot.FindWidgetId(int(id)) if n == nil { log.Info("could not find widget id", id) } // log.Info("tree.updateRow() start found header", id, r.Header, "len =", len(r.Widgets)) // if r.Header.Name == "Hostname" { // } // log.Info("tree.updateRow() found Hostnames", r.Vals) for i, v := range r.Vals { // log.Info("tree: Hostname Widget", i, v, w.Name) w := r.Widgets[i] if v != w.Name { log.Info("tree: need to update:", i, v, "vs", w.Name, w.Id) n := treeRoot.FindWidgetId(int(w.Id)) if n == nil { log.Info("tree.TableUpdate() err n == nil ", w.Id, w.Name) continue } me.SetText(n, v) } } return } } } func (me *TreeInfo) makeTable(t *guipb.Table) { var grid *Node if t.Window != nil { // deprecate this early hack win := makeTableWindow(t.Window) me.Add(win) win.makeWindowGrid(t.Grid) } if t.Parent != nil { a := new(widget.Action) a.WidgetType = widget.Grid a.WidgetId = int(t.Grid.Id) a.ParentId = int(t.Parent.Id) a.State.Enable = true grid = AddNode(a) } if grid == nil { log.Info("tree: makeTable() failed to make grid") return } me.Add(grid) log.Info("tree: makeTable() finished add win & grid") var h int = 0 var w int = 0 for _, name := range t.Order { // log.Info("got order:", t.Title, name) if me.addTableRow(t, grid, name, w) { // log.Info("tree:row() COLUMN GOOD", t.Title, name, w, h) } else { log.Info("tree:row() COLOMN FAIL", t.Title, name, w, h) } w += 1 } /* for i, r := range t.StringRows { log.Info("got string row:", t.Title, i, r.Header, r.Vals) for _, v := range r.Widgets { log.Info("tree: add to grid here", v.Id, v.Name) lab := grid.makeGridLabel(v, w, h) me.Add(lab) h += 1 } } */ } func (me *TreeInfo) addTableRow(t *guipb.Table, grid *Node, name string, w int) bool { var h int = 0 for _, r := range t.StringRows { if name != r.Header.Name { // log.Info("skip string row:", r.Header.Name, "!=", name) continue } // log.Info("tree: Add()ing to grid here", r.Header.Id, r.Header.Name, w, h) head := grid.makeGridLabel(r.Header, w, h) me.Add(head) h += 1 for _, v := range r.Widgets { // log.Info("tree: Add()ing to grid here", v.Id, v.Name, w, h) lab := grid.makeGridLabel(v, w, h) me.Add(lab) h += 1 } return true } for _, r := range t.IntRows { if name != r.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } // log.Info("tree: Add()ing to grid here", r.Header.Id, r.Header.Name, w, h) head := grid.makeGridLabel(r.Header, w, h) me.Add(head) h += 1 for _, v := range r.Widgets { v.Name = fmt.Sprintf("%d", v.Size) // log.Info("tree: Add()ing to grid here", v.Id, v.Name, w, h) lab := grid.makeGridLabel(v, w, h) me.Add(lab) h += 1 } return true } for _, r := range t.TimeRows { if name != r.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } // log.Info("tree: Add()ing to grid here", r.Header.Id, r.Header.Name, w, h) head := grid.makeGridLabel(r.Header, w, h) me.Add(head) h += 1 for _, widg := range r.Widgets { msg, err := anypb.UnmarshalNew(widg.Val, proto.UnmarshalOptions{}) if err != nil { log.Fatalf("failed to unmarshal: %v", err) } switch v := msg.(type) { case *timestamppb.Timestamp: // fmt.Println("Unpacked Timestamp:", shell.FormatDuration(time.Since(v.AsTime()))) widg.Name = shell.FormatDuration(time.Since(v.AsTime())) default: fmt.Println("Unknown type:", v) widg.Name = fmt.Sprintf("%v", v) } // log.Info("tree: Add()ing to grid here", widg.Id, widg.Name, w, h) lab := grid.makeGridLabel(widg, w, h) me.Add(lab) h += 1 } return true } return false } func dumpTable(t *guipb.Table) { for i, o := range t.Order { log.Info("got order:", t.Title, i, o) } for i, r := range t.StringRows { log.Info("got string row:", t.Title, i, r.Header.Name, r.Vals) for _, v := range r.Widgets { log.Info("tree: got string widget:", v.Id, v.Name) } } for i, r := range t.IntRows { log.Info("got int row:", t.Title, i, r.Header.Name, r.Vals) for _, v := range r.Widgets { log.Info("tree: got int widget:", v.Id, v.Size) } } } type TreeTable struct { PB *guipb.Table /* hostnames []string columns []*gui.NodeColumn order []*gui.NodeColumn */ }