github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/core/utils/pdf/pdftable.go (about) 1 package pdf 2 3 import ( 4 "math" 5 6 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 7 ) 8 9 const paddingCells = 2 10 11 type ColumnMetas struct { 12 Field rd.Field 13 Label string 14 Width float64 15 Align string 16 } 17 18 func (pdf CustomPdf) splitLine(w float64, fullTxt string) []string { 19 bytes := pdf.SplitLines([]byte(pdf.Tr(fullTxt)), w) 20 out := make([]string, len(bytes)) 21 for index, b := range bytes { 22 out[index] = string(b) 23 } 24 return out 25 } 26 27 func (pdf CustomPdf) drawCell(w, lh, maxHeight, padding float64, lines []string, alignStr string, fill bool) { 28 x, y := pdf.GetXY() 29 styleStr := "D" 30 if fill { 31 styleStr = "FD" 32 } 33 cellsHeight := lh * float64(len(lines)) 34 ySpacing := (maxHeight - cellsHeight - 2*padding) / 2 35 pdf.Rect(x, y, w, maxHeight, styleStr) 36 pdf.SetXY(x+padding, y+ySpacing+padding) 37 for _, line := range lines { 38 pdf.Fpdf.CellFormat(w-2*padding, lh, line, "", 2, alignStr, false, 0, "") 39 } 40 pdf.SetXY(x+w, y) 41 } 42 43 func (pdf CustomPdf) setBold(field rd.Field, data rd.Item, force bool) { 44 style := "" 45 if force || data.Bolds[field] { 46 style = "B" 47 } 48 pdf.SetFontStyle(style) 49 } 50 51 func (pdf CustomPdf) setupLine(fields []ColumnMetas, data rd.Item, lH, 52 padding float64, forceBold bool) ([][]string, float64) { 53 maxLines := 0 54 splittedLines := make([][]string, len(fields)) 55 for index, col := range fields { // calcul du nombre de ligne nécéssaires 56 pdf.setBold(col.Field, data, forceBold) 57 neededLines := pdf.splitLine(col.Width-2*padding, data.Fields.Data(col.Field).String()) 58 if len(neededLines) > maxLines { 59 maxLines = len(neededLines) 60 } 61 splittedLines[index] = neededLines 62 } 63 rowHeight := float64(maxLines)*lH + 2*padding 64 if pdf.GetY()+rowHeight > pdf.areaBottomLimit() { 65 pdf.AddPage() 66 } 67 return splittedLines, rowHeight 68 } 69 70 func (pdf CustomPdf) drawRow(fields []ColumnMetas, data rd.Item, lH, 71 padding float64, fill, forceBold, forceCenter bool) { 72 splittedLines, rowHeight := pdf.setupLine(fields, data, lH, padding, forceBold) 73 x, y := pdf.GetXY() 74 for index, col := range fields { 75 pdf.setBold(col.Field, data, forceBold) 76 alignStr := col.Align 77 if forceCenter { // defaut au centre 78 alignStr = "C" 79 } 80 pdf.drawCell(col.Width, lH, rowHeight, padding, splittedLines[index], alignStr, fill) 81 } 82 pdf.SetXY(x, y+rowHeight) 83 } 84 85 // setup fields wdith 86 func (pdf CustomPdf) drawHeaderTable(fields []ColumnMetas) []ColumnMetas { 87 pdf.SetFontSize(11) // influe lineHeight 88 aW := pdf.AreaWidth() 89 fieldsAbsolute := make([]ColumnMetas, len(fields)) 90 for index, col := range fields { 91 fieldsAbsolute[index] = col // copy 92 fieldsAbsolute[index].Width = aW * col.Width // relative to absolute 93 } 94 headers := rd.Item{Fields: make(rd.F)} 95 for _, col := range fields { 96 headers.Fields[col.Field] = rd.String(col.Label) 97 } 98 lH, padding := pdf.LineHeight(), 0.5 99 pdf.drawRow(fieldsAbsolute, headers, lH, padding, true, true, true) // background + bold 100 return fieldsAbsolute 101 } 102 103 // fields Width est relative (0,1) 104 func (pdf CustomPdf) drawTable(fields []ColumnMetas, data []rd.Item) { 105 pdf.SetFillColor(primaryColor) 106 fields = pdf.drawHeaderTable(fields) // absolute width 107 pdf.SetFont("Arial", "", 9) 108 lH, padding := pdf.LineHeight(), 1. 109 for _, item := range data { 110 pdf.drawRow(fields, item, lH, padding, false, false, false) 111 } 112 } 113 114 // support html syntax, but must be left aligned 115 func (pdf CustomPdf) drawMergedColumns(marginLeft, rightWidth, lH float64, left, right string, fill bool) { 116 h := pdf.HTMLBasicNew() 117 mL, _, mR, _ := pdf.GetMargins() 118 aW := pdf.AreaWidth() 119 leftWidth := aW - rightWidth - marginLeft 120 y := pdf.GetY() 121 oldR, oldG, oldB := pdf.GetTextColor() 122 pdf.Fpdf.SetTextColor(255, 255, 255) 123 pdf.SetLeftMargin(mL + marginLeft + paddingCells) // besoin de connaitre la hauteur avant 124 pdf.SetRightMargin(mR + (aW - marginLeft - leftWidth) + paddingCells) 125 pdf.SetY(0) 126 h.Write(lH, pdf.Tr(left)) 127 neededHeight := pdf.GetY() + lH 128 pdf.SetRightMargin(mR + paddingCells) 129 pdf.SetLeftMargin(mL + leftWidth + marginLeft + paddingCells) 130 h.Write(lH, pdf.Tr(right)) 131 neededHeight = math.Max(neededHeight, pdf.GetY()+lH) + 2*paddingCells 132 if y+neededHeight > pdf.areaBottomLimit() { 133 pdf.AddPage() 134 y = pdf.GetY() 135 pdf.Line(mL, y, mL+aW, y) 136 } 137 if fill { 138 pdf.Rect(mL, y, aW, neededHeight, "F") 139 } 140 pdf.Line(mL, y+neededHeight, mL+aW, y+neededHeight) 141 pdf.Line(mL, y, mL, y+neededHeight) 142 pdf.Line(mL+aW, y, mL+aW, y+neededHeight) 143 pdf.Fpdf.SetTextColor(oldR, oldG, oldB) 144 pdf.SetXY(mL+paddingCells+marginLeft, y+paddingCells) 145 pdf.SetLeftMargin(mL + marginLeft + paddingCells) 146 pdf.SetRightMargin(mR + (aW - marginLeft - leftWidth) + paddingCells) 147 h.Write(lH, pdf.Tr(left)) 148 pdf.SetXY(mL+leftWidth+paddingCells+marginLeft, y+paddingCells) 149 pdf.SetRightMargin(mR + paddingCells) 150 pdf.SetLeftMargin(mL + leftWidth + marginLeft + paddingCells) 151 h.Write(lH, pdf.Tr(right)) 152 pdf.SetXY(mL, y+neededHeight) 153 pdf.SetRightMargin(mR) 154 pdf.SetLeftMargin(mL) 155 }