// 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) 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) 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 */ }