feat: support table render
This commit is contained in:
parent
8c5647f65f
commit
2fb0ebcbf7
6 changed files with 476 additions and 23 deletions
|
|
@ -23,6 +23,7 @@
|
||||||
package charts
|
package charts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
|
|
@ -336,3 +337,71 @@ func FunnelRender(values []float64, opts ...OptionFunc) (*Painter, error) {
|
||||||
SeriesList: seriesList,
|
SeriesList: seriesList,
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TableRender(opt TableChartOption) (*Painter, error) {
|
||||||
|
if opt.Type == "" {
|
||||||
|
opt.Type = ChartOutputPNG
|
||||||
|
}
|
||||||
|
if opt.Width <= 0 {
|
||||||
|
opt.Width = defaultChartWidth
|
||||||
|
}
|
||||||
|
if opt.Height <= 0 {
|
||||||
|
opt.Height = defaultChartHeight
|
||||||
|
}
|
||||||
|
if opt.Font == nil {
|
||||||
|
opt.Font, _ = chart.GetDefaultFont()
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := NewPainter(PainterOptions{
|
||||||
|
Type: opt.Type,
|
||||||
|
Width: opt.Width,
|
||||||
|
Height: opt.Height,
|
||||||
|
Font: opt.Font,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
info, err := NewTableChart(p, opt).render()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println(*info)
|
||||||
|
fmt.Println(info.Height)
|
||||||
|
|
||||||
|
p, err = NewPainter(PainterOptions{
|
||||||
|
Type: opt.Type,
|
||||||
|
Width: info.Width,
|
||||||
|
Height: info.Height,
|
||||||
|
Font: opt.Font,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = NewTableChart(p, opt).Render()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// opt := ChartOption{}
|
||||||
|
// for _, fn := range opts {
|
||||||
|
// fn(&opt)
|
||||||
|
// }
|
||||||
|
// opt.fillDefault()
|
||||||
|
// p, err := NewPainter(PainterOptions{
|
||||||
|
// Type: opt.Type,
|
||||||
|
// Width: opt.Width,
|
||||||
|
// Height: opt.Height,
|
||||||
|
// Font: opt.font,
|
||||||
|
// })
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// _, err = NewTableChart(p, TableChartOption{
|
||||||
|
// Header: header,
|
||||||
|
// Data: data,
|
||||||
|
// }).Render()
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
79
examples/table/main.go
Normal file
79
examples/table/main.go
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/vicanso/go-charts/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func writeFile(buf []byte) error {
|
||||||
|
tmpPath := "./tmp"
|
||||||
|
err := os.MkdirAll(tmpPath, 0700)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file := filepath.Join(tmpPath, "table.png")
|
||||||
|
err = ioutil.WriteFile(file, buf, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p, err := charts.TableRender(charts.TableChartOption{
|
||||||
|
Header: []string{
|
||||||
|
"Name",
|
||||||
|
"Age",
|
||||||
|
"Address",
|
||||||
|
"Tag",
|
||||||
|
"Action",
|
||||||
|
},
|
||||||
|
Spans: []int{
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
Data: [][]string{
|
||||||
|
{
|
||||||
|
"John Brown",
|
||||||
|
"32",
|
||||||
|
"New York No. 1 Lake Park",
|
||||||
|
"nice, developer",
|
||||||
|
"Send Mail",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Jim Green ",
|
||||||
|
"42",
|
||||||
|
"London No. 1 Lake Park",
|
||||||
|
"wow",
|
||||||
|
"Send Mail",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Joe Black ",
|
||||||
|
"32",
|
||||||
|
"Sidney No. 1 Lake Park",
|
||||||
|
"cool, teacher",
|
||||||
|
"Send Mail",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := p.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = writeFile(buf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
painter.go
10
painter.go
|
|
@ -468,7 +468,7 @@ func (p *Painter) SmoothLineStroke(points []Point) *Painter {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Painter) SetBackground(width, height int, color Color) *Painter {
|
func (p *Painter) SetBackground(width, height int, color Color, inside ...bool) *Painter {
|
||||||
r := p.render
|
r := p.render
|
||||||
s := chart.Style{
|
s := chart.Style{
|
||||||
FillColor: color,
|
FillColor: color,
|
||||||
|
|
@ -476,12 +476,20 @@ func (p *Painter) SetBackground(width, height int, color Color) *Painter {
|
||||||
// 背景色
|
// 背景色
|
||||||
p.SetDrawingStyle(s)
|
p.SetDrawingStyle(s)
|
||||||
defer p.ResetStyle()
|
defer p.ResetStyle()
|
||||||
|
if len(inside) != 0 && inside[0] {
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
p.LineTo(width, 0)
|
||||||
|
p.LineTo(width, height)
|
||||||
|
p.LineTo(0, height)
|
||||||
|
p.LineTo(0, 0)
|
||||||
|
} else {
|
||||||
// 设置背景色不使用box,因此不直接使用Painter
|
// 设置背景色不使用box,因此不直接使用Painter
|
||||||
r.MoveTo(0, 0)
|
r.MoveTo(0, 0)
|
||||||
r.LineTo(width, 0)
|
r.LineTo(width, 0)
|
||||||
r.LineTo(width, height)
|
r.LineTo(width, height)
|
||||||
r.LineTo(0, height)
|
r.LineTo(0, height)
|
||||||
r.LineTo(0, 0)
|
r.LineTo(0, 0)
|
||||||
|
}
|
||||||
p.FillStroke()
|
p.FillStroke()
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,13 +143,13 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
A: 255,
|
A: 255,
|
||||||
},
|
},
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -165,13 +165,13 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
A: 255,
|
A: 255,
|
||||||
},
|
},
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -187,13 +187,13 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
A: 255,
|
A: 255,
|
||||||
},
|
},
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -209,13 +209,13 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
A: 255,
|
A: 255,
|
||||||
},
|
},
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -231,13 +231,13 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
A: 255,
|
A: 255,
|
||||||
},
|
},
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -253,13 +253,13 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
A: 255,
|
A: 255,
|
||||||
},
|
},
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -279,7 +279,7 @@ func TestPainter(t *testing.T) {
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetStyle(Style{
|
p.SetStyle(Style{
|
||||||
StrokeWidth: 1,
|
StrokeWidth: 1,
|
||||||
StrokeColor: drawing.Color{
|
StrokeColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
@ -297,7 +297,7 @@ func TestPainter(t *testing.T) {
|
||||||
{
|
{
|
||||||
fn: func(p *Painter) {
|
fn: func(p *Painter) {
|
||||||
p.SetDrawingStyle(Style{
|
p.SetDrawingStyle(Style{
|
||||||
FillColor: drawing.Color{
|
FillColor: Color{
|
||||||
R: 84,
|
R: 84,
|
||||||
G: 112,
|
G: 112,
|
||||||
B: 198,
|
B: 198,
|
||||||
|
|
|
||||||
201
table.go
201
table.go
|
|
@ -22,6 +22,14 @@
|
||||||
|
|
||||||
package charts
|
package charts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/golang/freetype/truetype"
|
||||||
|
"github.com/wcharczuk/go-chart/v2"
|
||||||
|
"github.com/wcharczuk/go-chart/v2/drawing"
|
||||||
|
)
|
||||||
|
|
||||||
type tableChart struct {
|
type tableChart struct {
|
||||||
p *Painter
|
p *Painter
|
||||||
opt *TableChartOption
|
opt *TableChartOption
|
||||||
|
|
@ -38,16 +46,205 @@ func NewTableChart(p *Painter, opt TableChartOption) *tableChart {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TableChartOption struct {
|
type TableChartOption struct {
|
||||||
|
// The output type
|
||||||
|
Type string
|
||||||
|
// The width of table
|
||||||
|
Width int
|
||||||
|
// The height of table
|
||||||
|
Height int
|
||||||
// The theme
|
// The theme
|
||||||
Theme ColorPalette
|
Theme ColorPalette
|
||||||
// The padding of table cell
|
// The padding of table cell
|
||||||
Padding Box
|
Padding Box
|
||||||
// The header data of table
|
// The header data of table
|
||||||
HeaderData []string
|
Header []string
|
||||||
// The data of table
|
// The data of table
|
||||||
Data [][]string
|
Data [][]string
|
||||||
|
// The span of table column
|
||||||
|
Spans []int
|
||||||
|
// The font size of table
|
||||||
|
FontSize float64
|
||||||
|
Font *truetype.Font
|
||||||
|
// The font color of table
|
||||||
|
FontColor Color
|
||||||
|
// The background color of header
|
||||||
|
HeaderBackgroundColor Color
|
||||||
|
// The header font color
|
||||||
|
HeaderFontColor Color
|
||||||
|
// The background color of row
|
||||||
|
RowBackgroundColors []Color
|
||||||
|
// The background color
|
||||||
|
BackgroundColor Color
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultTableHeaderColor = Color{
|
||||||
|
R: 34,
|
||||||
|
G: 34,
|
||||||
|
B: 34,
|
||||||
|
A: 255,
|
||||||
|
}
|
||||||
|
var defaultTableRowColors = []Color{
|
||||||
|
drawing.ColorWhite,
|
||||||
|
{
|
||||||
|
R: 242,
|
||||||
|
G: 242,
|
||||||
|
B: 242,
|
||||||
|
A: 255,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var defaultTablePadding = Box{
|
||||||
|
Left: 10,
|
||||||
|
Top: 10,
|
||||||
|
Right: 10,
|
||||||
|
Bottom: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
type renderInfo struct {
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
HeaderHeight int
|
||||||
|
RowHeights []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tableChart) render() (*renderInfo, error) {
|
||||||
|
info := renderInfo{
|
||||||
|
RowHeights: make([]int, 0),
|
||||||
|
}
|
||||||
|
p := c.p
|
||||||
|
opt := c.opt
|
||||||
|
if len(opt.Header) == 0 {
|
||||||
|
return nil, errors.New("header can not be nil")
|
||||||
|
}
|
||||||
|
theme := opt.Theme
|
||||||
|
if theme == nil {
|
||||||
|
theme = p.theme
|
||||||
|
}
|
||||||
|
fontSize := opt.FontSize
|
||||||
|
if fontSize == 0 {
|
||||||
|
fontSize = 12
|
||||||
|
}
|
||||||
|
fontColor := opt.FontColor
|
||||||
|
if fontColor.IsZero() {
|
||||||
|
fontColor = theme.GetTextColor()
|
||||||
|
}
|
||||||
|
font := opt.Font
|
||||||
|
if font == nil {
|
||||||
|
font = theme.GetFont()
|
||||||
|
}
|
||||||
|
headerFontColor := opt.HeaderFontColor
|
||||||
|
if opt.HeaderFontColor.IsZero() {
|
||||||
|
headerFontColor = drawing.ColorWhite
|
||||||
|
}
|
||||||
|
|
||||||
|
spans := opt.Spans
|
||||||
|
if len(spans) != 0 && len(spans) != len(opt.Header) {
|
||||||
|
newSpans := make([]int, len(opt.Header))
|
||||||
|
for index := range opt.Header {
|
||||||
|
if len(spans) < index {
|
||||||
|
newSpans[index] = 1
|
||||||
|
} else {
|
||||||
|
newSpans[index] = spans[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spans = newSpans
|
||||||
|
}
|
||||||
|
|
||||||
|
values := autoDivideSpans(p.Width(), len(opt.Header)+1, spans)
|
||||||
|
height := 0
|
||||||
|
textStyle := Style{
|
||||||
|
FontSize: fontSize,
|
||||||
|
FontColor: headerFontColor,
|
||||||
|
FillColor: headerFontColor,
|
||||||
|
Font: font,
|
||||||
|
}
|
||||||
|
p.SetStyle(textStyle)
|
||||||
|
|
||||||
|
headerHeight := 0
|
||||||
|
padding := opt.Padding
|
||||||
|
if padding.IsZero() {
|
||||||
|
padding = defaultTablePadding
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTableCells := func(textList []string, currentHeight int, cellPadding Box) int {
|
||||||
|
cellMaxHeight := 0
|
||||||
|
paddingHeight := cellPadding.Top + cellPadding.Bottom
|
||||||
|
paddingWidth := cellPadding.Left + cellPadding.Right
|
||||||
|
for index, text := range textList {
|
||||||
|
x := values[index]
|
||||||
|
y := currentHeight + cellPadding.Top
|
||||||
|
width := values[index+1] - x
|
||||||
|
x += cellPadding.Left
|
||||||
|
width -= paddingWidth
|
||||||
|
box := p.TextFit(text, x, y+int(fontSize), width)
|
||||||
|
if box.Height()+paddingHeight > cellMaxHeight {
|
||||||
|
cellMaxHeight = box.Height() + paddingHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cellMaxHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
headerHeight = renderTableCells(opt.Header, height, padding)
|
||||||
|
height += headerHeight
|
||||||
|
info.HeaderHeight = headerHeight
|
||||||
|
|
||||||
|
textStyle.FontColor = fontColor
|
||||||
|
textStyle.FillColor = fontColor
|
||||||
|
p.SetStyle(textStyle)
|
||||||
|
for _, textList := range opt.Data {
|
||||||
|
cellHeight := renderTableCells(textList, height, padding)
|
||||||
|
info.RowHeights = append(info.RowHeights, cellHeight)
|
||||||
|
height += cellHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Width = p.Width()
|
||||||
|
info.Height = height
|
||||||
|
return &info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *tableChart) Render() (Box, error) {
|
func (c *tableChart) Render() (Box, error) {
|
||||||
return BoxZero, nil
|
p := c.p
|
||||||
|
opt := c.opt
|
||||||
|
if !opt.BackgroundColor.IsZero() {
|
||||||
|
p.SetBackground(p.Width(), p.Height(), opt.BackgroundColor)
|
||||||
|
}
|
||||||
|
headerBGColor := opt.HeaderBackgroundColor
|
||||||
|
if headerBGColor.IsZero() {
|
||||||
|
headerBGColor = defaultTableHeaderColor
|
||||||
|
}
|
||||||
|
|
||||||
|
r := p.render
|
||||||
|
newRender, err := chart.SVG(p.Width(), 100)
|
||||||
|
if err != nil {
|
||||||
|
return BoxZero, err
|
||||||
|
}
|
||||||
|
p.render = newRender
|
||||||
|
info, err := c.render()
|
||||||
|
if err != nil {
|
||||||
|
return BoxZero, err
|
||||||
|
}
|
||||||
|
p.render = r
|
||||||
|
// 如果设置表头背景色
|
||||||
|
p.SetBackground(info.Width, info.HeaderHeight, headerBGColor, true)
|
||||||
|
currentHeight := info.HeaderHeight
|
||||||
|
rowColors := opt.RowBackgroundColors
|
||||||
|
if len(rowColors) == 0 {
|
||||||
|
rowColors = defaultTableRowColors
|
||||||
|
}
|
||||||
|
for index, h := range info.RowHeights {
|
||||||
|
color := rowColors[index%len(rowColors)]
|
||||||
|
child := p.Child(PainterPaddingOption(Box{
|
||||||
|
Top: currentHeight,
|
||||||
|
}))
|
||||||
|
child.SetBackground(p.Width(), h, color, true)
|
||||||
|
currentHeight += h
|
||||||
|
}
|
||||||
|
_, err = c.render()
|
||||||
|
if err != nil {
|
||||||
|
return BoxZero, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Box{
|
||||||
|
Right: info.Width,
|
||||||
|
Bottom: info.Height,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
100
table_test.go
Normal file
100
table_test.go
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
// Copyright (c) 2022 Tree Xie
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package charts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTableChart(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
render func(*Painter) ([]byte, error)
|
||||||
|
result string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
render: func(p *Painter) ([]byte, error) {
|
||||||
|
_, err := NewTableChart(p, TableChartOption{
|
||||||
|
Header: []string{
|
||||||
|
"Name",
|
||||||
|
"Age",
|
||||||
|
"Address",
|
||||||
|
"Tag",
|
||||||
|
"Action",
|
||||||
|
},
|
||||||
|
Spans: []int{
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
Data: [][]string{
|
||||||
|
{
|
||||||
|
"John Brown",
|
||||||
|
"32",
|
||||||
|
"New York No. 1 Lake Park",
|
||||||
|
"nice, developer",
|
||||||
|
"Send Mail",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Jim Green ",
|
||||||
|
"42",
|
||||||
|
"London No. 1 Lake Park",
|
||||||
|
"wow",
|
||||||
|
"Send Mail",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Joe Black ",
|
||||||
|
"32",
|
||||||
|
"Sidney No. 1 Lake Park",
|
||||||
|
"cool, teacher",
|
||||||
|
"Send Mail",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).Render()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p.Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
p, err := NewPainter(PainterOptions{
|
||||||
|
Type: ChartOutputSVG,
|
||||||
|
Width: 600,
|
||||||
|
Height: 400,
|
||||||
|
}, PainterThemeOption(defaultTheme))
|
||||||
|
assert.Nil(err)
|
||||||
|
data, err := tt.render(p)
|
||||||
|
assert.Nil(err)
|
||||||
|
fmt.Println(string(data))
|
||||||
|
assert.Equal(tt.result, string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue