// Copyright 2025 WIT.COM Inc Licensed GPL 3.0 package cobol import ( "fmt" "os" "time" "go.wit.com/lib/gui/shell" "go.wit.com/lib/protobuf/guipb" "go.wit.com/log" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" ) func PrintTable(pb *guipb.Table) { // log.Info("print PB here") if pb.Grid == nil { // log.Info("grid = nil") } else { // log.Info("grid.Id =", pb.Grid.Id) } var h int = 0 var w int = 0 var HEIGHT int if pb.Height == 0 { HEIGHT = 4 } // log.Info("pb.Height", pb.Height, HEIGHT) var args []string var sizes []int for _, name := range pb.Order { arg, attr, tmp := getColAttr(pb, name) if attr == nil { continue } HEIGHT = tmp args = append(args, arg) if attr.Width == 0 { sizes = append(sizes, 8) } else { sizes = append(sizes, int(attr.Width)) } } // sizes = []int{24, 5, 8, 32, 13, 4, 4, 4, 4} header, _ := StandardTableRow(sizes, args) log.Info(header) for i := range HEIGHT { var cells []string for _, name := range pb.Order { if val, ok := getAnyCell(pb, name, int(i)); ok { h += 1 cells = append(cells, val) continue } if val, ok := getTableCell(pb, name, int(i)); ok { // log.Info("tree: CELL GOOD", pb.Title, name, w, h, val) h += 1 cells = append(cells, val) } else { log.Info("tree: CELL FAIL", pb.Title, name, w, h, val) cells = append(cells, "err") } } line, fmtline := StandardTableRow(sizes, cells) if os.Getenv("TABLEPB_VERBOSE") == "true" { line += "FMT: " + fmtline } log.Info(line) } } func makeGridLabel(pb *guipb.Widget, w int, h int) { log.Info("MAKE GRID LABEL", w, h, pb.Name) } func extractInt64(anyVal *anypb.Any) (int64, error) { val := &wrapperspb.Int64Value{} if err := anyVal.UnmarshalTo(val); err != nil { return 0, err } return val.Value, nil } func getTableCell(t *guipb.Table, name string, row int) (string, bool) { // find the Column that matches the "name" for _, r := range t.StringCols { if name != r.Header.Name { // log.Info("skip string row:", r.Header.Name, "!=", name) continue } // log.Info("Cell value:", r.Vals[row]) return r.Vals[row], true } for _, r := range t.ButtonCols { if name != r.Header.Name { // log.Info("skip string row:", r.Header.Name, "!=", name) continue } // log.Info("Cell value:", r.Vals[row]) return r.Vals[row], true } for _, r := range t.IntCols { if name != r.Header.Name { // log.Info("skip string row:", r.Header.Name, "!=", name) continue } return fmt.Sprintf("%d", r.Vals[row]), true } for _, r := range t.TimeCols { if name != r.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } cellTime := r.Vals[row] s := shell.FormatDuration(time.Since(cellTime.AsTime())) return s, true } for _, r := range t.AnyCols { if name != r.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } // cellTime := r.Vals[row] // s := shell.FormatDuration(time.Since(cellTime.AsTime())) return "fixme", true } return "", false } func getAnyCell(t *guipb.Table, name string, row int) (string, bool) { for _, col := range t.AnyCols { if name != col.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } anyVal := col.Vals[row] switch col.Attr.Type { case guipb.ColAttr_STRING: // return col.Vals[row] true // Assume 'anyVal' is an element from your r.Vals slice var stringValue wrapperspb.StringValue if err := anyVal.UnmarshalTo(&stringValue); err == nil { // It's a string, now convert it back to a native Go string goString := stringValue.GetValue() // fmt.Printf("Successfully unpacked string: %s\n", goString) return goString, true } case guipb.ColAttr_INT: var finalInt int32 // 1. Check if the Any contains an Int32Value if anyVal.MessageIs(&wrapperspb.Int32Value{}) { var intValue wrapperspb.Int32Value // 2. Unmarshal into the wrapper if err := anyVal.UnmarshalTo(&intValue); err == nil { // 3. Get the native Go int32 from the wrapper finalInt = intValue.GetValue() } } return fmt.Sprintf("%d", finalInt), true case guipb.ColAttr_DURATION: case guipb.ColAttr_TIME: var sout string var tsProto timestamppb.Timestamp if err := anyVal.UnmarshalTo(&tsProto); err == nil { // It's a timestamp, now convert it back to a Go time.Time goTime := tsProto.AsTime() // fmt.Printf("Successfully unpacked timestamp: %v\n", goTime) sout = shell.FormatDuration(time.Since(goTime)) return sout, true } return "", false default: log.Info("cell unhandled type", col.Attr.Type) } // cellTime := r.Vals[row] // s := shell.FormatDuration(time.Since(cellTime.AsTime())) return "fixme", true } return "", false } func getColAttr(t *guipb.Table, name string) (string, *guipb.ColAttr, int) { // find the Column that matches the "name" for _, r := range t.StringCols { if name != r.Header.Name { continue } return r.Header.Name, r.Attr, len(r.Vals) } for _, r := range t.ButtonCols { if name != r.Header.Name { // log.Info("skip string row:", r.Header.Name, "!=", name) continue } return r.Header.Name, r.Attr, len(r.Vals) } for _, r := range t.IntCols { if name != r.Header.Name { // log.Info("skip string row:", r.Header.Name, "!=", name) continue } return r.Header.Name, r.Attr, len(r.Vals) } for _, r := range t.TimeCols { if name != r.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } return r.Header.Name, r.Attr, len(r.Vals) } for _, r := range t.AnyCols { if name != r.Header.Name { // log.Info("skip sint row:", r.Header.Name, "!=", name) continue } return r.Header.Name, r.Attr, len(r.Vals) } return "", nil, 0 }