diff --git a/echarts.go b/echarts.go index b0cbe8a..02cede2 100644 --- a/echarts.go +++ b/echarts.go @@ -112,12 +112,15 @@ func (ep *EChartsPadding) UnmarshalJSON(data []byte) error { default: result := make([]int, 4) copy(result, arr) + if len(arr) == 3 { + result[3] = result[1] + } // 上右下左 ep.box = chart.Box{ - Top: arr[0], - Right: arr[1], - Bottom: arr[2], - Left: arr[3], + Top: result[0], + Right: result[1], + Bottom: result[2], + Left: result[3], } } return nil diff --git a/echarts_test.go b/echarts_test.go new file mode 100644 index 0000000..99bf414 --- /dev/null +++ b/echarts_test.go @@ -0,0 +1,381 @@ +// MIT License + +// Copyright (c) 2021 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 ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2" +) + +func TestConvertToArray(t *testing.T) { + assert := assert.New(t) + + assert.Nil(convertToArray([]byte(" "))) + + assert.Equal([]byte("[{}]"), convertToArray([]byte("{}"))) + assert.Equal([]byte("[{}]"), convertToArray([]byte("[{}]"))) +} + +func TestECharsSeriesData(t *testing.T) { + assert := assert.New(t) + + es := ECharsSeriesData{} + err := es.UnmarshalJSON([]byte(" ")) + assert.Nil(err) + assert.Equal(ECharsSeriesData{}, es) + + es = ECharsSeriesData{} + err = es.UnmarshalJSON([]byte("12.1")) + assert.Nil(err) + assert.Equal(ECharsSeriesData{ + Value: 12.1, + }, es) + + es = ECharsSeriesData{} + err = es.UnmarshalJSON([]byte(`{ + "value": 12.1, + "name": "test", + "itemStyle": { + "color": "#333" + } + }`)) + assert.Nil(err) + assert.Equal(ECharsSeriesData{ + Value: 12.1, + Name: "test", + ItemStyle: EChartStyle{ + Color: "#333", + }, + }, es) +} + +func TestEChartsPadding(t *testing.T) { + assert := assert.New(t) + + ep := EChartsPadding{} + err := ep.UnmarshalJSON([]byte(" ")) + assert.Nil(err) + assert.Equal(EChartsPadding{}, ep) + + ep = EChartsPadding{} + err = ep.UnmarshalJSON([]byte("1")) + assert.Nil(err) + assert.Equal(EChartsPadding{ + box: chart.Box{ + Top: 1, + Left: 1, + Right: 1, + Bottom: 1, + }, + }, ep) + + ep = EChartsPadding{} + err = ep.UnmarshalJSON([]byte("[1, 2]")) + assert.Nil(err) + assert.Equal(EChartsPadding{ + box: chart.Box{ + Top: 1, + Left: 2, + Right: 2, + Bottom: 1, + }, + }, ep) + + ep = EChartsPadding{} + err = ep.UnmarshalJSON([]byte("[1, 2, 3]")) + assert.Nil(err) + assert.Equal(EChartsPadding{ + box: chart.Box{ + Top: 1, + Right: 2, + Bottom: 3, + Left: 2, + }, + }, ep) + + ep = EChartsPadding{} + err = ep.UnmarshalJSON([]byte("[1, 2, 3, 4]")) + assert.Nil(err) + assert.Equal(EChartsPadding{ + box: chart.Box{ + Top: 1, + Right: 2, + Bottom: 3, + Left: 4, + }, + }, ep) +} + +func TestConvertEChartsSeries(t *testing.T) { + assert := assert.New(t) + + seriesList, tickPosition := convertEChartsSeries(&ECharsOptions{}) + assert.Empty(seriesList) + assert.Equal(chart.TickPositionUnset, tickPosition) + + e := ECharsOptions{} + err := json.Unmarshal([]byte(`{ + "title": { + "text": "Referer of a Website" + }, + "series": [ + { + "name": "Access From", + "type": "pie", + "radius": "50%", + "data": [ + { + "value": 1048, + "name": "Search Engine" + }, + { + "value": 735, + "name": "Direct" + } + ] + } + ] + }`), &e) + assert.Nil(err) + seriesList, tickPosition = convertEChartsSeries(&e) + assert.Equal(chart.TickPositionUnset, tickPosition) + assert.Equal([]Series{ + { + Data: []SeriesData{ + { + Value: 1048, + }, + }, + Type: SeriesPie, + Name: "Search Engine", + }, + { + Data: []SeriesData{ + { + Value: 735, + }, + }, + Type: SeriesPie, + Name: "Direct", + }, + }, seriesList) + + err = json.Unmarshal([]byte(`{ + "series": [ + { + "name": "Evaporation", + "type": "bar", + "data": [2, { + "value": 4.9, + "itemStyle": { + "color": "#a90000" + } + }, 7, 23.2, 25.6, 76.7, 135.6] + }, + { + "name": "Precipitation", + "type": "bar", + "data": [2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6] + }, + { + "name": "Temperature", + "type": "line", + "yAxisIndex": 1, + "data": [2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3] + } + ] + }`), &e) + assert.Nil(err) + bar1Data := NewSeriesDataListFromFloat([]float64{ + 2, 4.9, 7, 23.2, 25.6, 76.7, 135.6, + }) + bar1Data[1].Style.FillColor = parseColor("#a90000") + bar1Data[1].Style.StrokeColor = bar1Data[1].Style.FillColor + + seriesList, tickPosition = convertEChartsSeries(&e) + assert.Equal(chart.TickPositionBetweenTicks, tickPosition) + assert.Equal([]Series{ + { + Data: bar1Data, + Type: SeriesBar, + }, + { + Data: NewSeriesDataListFromFloat([]float64{ + 2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6, + }), + Type: SeriesBar, + }, + { + Data: NewSeriesDataListFromFloat([]float64{ + 2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, + }), + Type: SeriesLine, + YAxisIndex: 1, + }, + }, seriesList) + +} + +func TestParseECharsOptions(t *testing.T) { + + assert := assert.New(t) + options, err := ParseECharsOptions(`{ + "theme": "dark", + "padding": [5, 10], + "title": { + "text": "Multi Line", + "textAlign": "left", + "textStyle": { + "color": "#333", + "fontSize": 24, + "height": 40 + } + }, + "legend": { + "align": "left", + "padding": [5, 0, 0, 50], + "data": ["Email", "Union Ads", "Video Ads", "Direct", "Search Engine"] + }, + "xAxis": { + "type": "category", + "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + "splitNumber": 10 + }, + "yAxis": [ + { + "min": 0, + "max": 250 + }, + { + "min": 0, + "max": 25 + } + ], + "series": [ + { + "name": "Evaporation", + "type": "bar", + "data": [2, { + "value": 4.9, + "itemStyle": { + "color": "#a90000" + } + }, 7, 23.2, 25.6, 76.7, 135.6] + }, + { + "name": "Precipitation", + "type": "bar", + "data": [2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6] + }, + { + "name": "Temperature", + "type": "line", + "yAxisIndex": 1, + "data": [2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3] + } + ] + }`) + + assert.Nil(err) + + min1 := float64(0) + max1 := float64(250) + min2 := float64(0) + max2 := float64(25) + + bar1Data := NewSeriesDataListFromFloat([]float64{ + 2, 4.9, 7, 23.2, 25.6, 76.7, 135.6, + }) + bar1Data[1].Style.FillColor = parseColor("#a90000") + bar1Data[1].Style.StrokeColor = bar1Data[1].Style.FillColor + + assert.Equal(Options{ + Theme: ThemeDark, + Padding: chart.Box{ + Top: 5, + Bottom: 5, + Left: 10, + Right: 10, + }, + Title: Title{ + Text: "Multi Line", + Style: chart.Style{ + FontColor: parseColor("#333"), + FontSize: 24, + Padding: chart.Box{ + Top: 8, + Bottom: 8, + }, + }, + }, + Legend: Legend{ + Data: []string{ + "Email", "Union Ads", "Video Ads", "Direct", "Search Engine", + }, + Align: "left", + Padding: chart.Box{ + Top: 5, + Right: 0, + Bottom: 0, + Left: 50, + }, + }, + XAxis: XAxis{ + Data: []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}, + SplitNumber: 10, + }, + TickPosition: chart.TickPositionBetweenTicks, + YAxisOptions: []*YAxisOption{ + { + Min: &min1, + Max: &max1, + }, + { + Min: &min2, + Max: &max2, + }, + }, + Series: []Series{ + { + Data: bar1Data, + Type: SeriesBar, + }, + { + Data: NewSeriesDataListFromFloat([]float64{ + 2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6, + }), + Type: SeriesBar, + }, + { + Data: NewSeriesDataListFromFloat([]float64{ + 2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, + }), + Type: SeriesLine, + YAxisIndex: 1, + }, + }, + }, options) +} diff --git a/legend.go b/legend.go index b519e3e..b019868 100644 --- a/legend.go +++ b/legend.go @@ -87,6 +87,7 @@ func LegendCustomize(series []chart.Series, opt LegendOption) chart.Renderable { var labels []string var lines []chart.Style + // 计算label和lines for _, s := range series { if !s.GetStyle().Hidden { if _, isAnnotationSeries := s.(chart.AnnotationSeries); !isAnnotationSeries { @@ -100,6 +101,7 @@ func LegendCustomize(series []chart.Series, opt LegendOption) chart.Renderable { var textWidth int var textBox chart.Box labelWidth := 0 + // 计算文本宽度与高度(取最大值) for x := 0; x < len(labels); x++ { if len(labels[x]) > 0 { textBox = r.MeasureText(labels[x]) diff --git a/legend_test.go b/legend_test.go index 6685243..d2af129 100644 --- a/legend_test.go +++ b/legend_test.go @@ -41,22 +41,39 @@ func TestLegendCustomize(t *testing.T) { Name: "edge", }, }, chart.TickPositionBetweenTicks, "") - r, err := chart.SVG(800, 600) - assert.Nil(err) - fn := LegendCustomize(series, LegendOption{ - TextPosition: LegendTextPositionRight, - IconDraw: DefaultLegendIconDraw, - Align: LegendAlignLeft, - Padding: chart.Box{ - Left: 100, - Top: 100, + + tests := []struct { + textPosition string + svg string + }{ + { + textPosition: LegendTextPositionRight, + svg: "\\nchromeedge", }, - }) - fn(r, chart.NewBox(11, 47, 784, 373), chart.Style{ - Font: chart.StyleTextDefaults().Font, - }) - buf := bytes.Buffer{} - err = r.Save(&buf) - assert.Nil(err) - assert.Equal("\\nchromeedge", buf.String()) + { + textPosition: LegendAlignLeft, + svg: "\\nchromeedge", + }, + } + + for _, tt := range tests { + r, err := chart.SVG(800, 600) + assert.Nil(err) + fn := LegendCustomize(series, LegendOption{ + TextPosition: tt.textPosition, + IconDraw: DefaultLegendIconDraw, + Align: LegendAlignLeft, + Padding: chart.Box{ + Left: 100, + Top: 100, + }, + }) + fn(r, chart.NewBox(11, 47, 784, 373), chart.Style{ + Font: chart.StyleTextDefaults().Font, + }) + buf := bytes.Buffer{} + err = r.Save(&buf) + assert.Nil(err) + assert.Equal(tt.svg, buf.String()) + } } diff --git a/line_series.go b/line_series.go index 5b7c9fd..f3686ad 100644 --- a/line_series.go +++ b/line_series.go @@ -30,11 +30,16 @@ type LineSeries struct { BaseSeries } -func (bs LineSeries) Render(r chart.Renderer, canvasBox chart.Box, xrange, yrange chart.Range, defaults chart.Style) { - style := bs.Style.InheritFrom(defaults) - // 如果是居中,画线时重新调整 - if bs.TickPosition == chart.TickPositionBetweenTicks { - xrange = wrapRange(xrange, bs.TickPosition) +func (ls LineSeries) getXRange(xrange chart.Range) chart.Range { + if ls.TickPosition != chart.TickPositionBetweenTicks { + return xrange } - chart.Draw.LineSeries(r, canvasBox, xrange, yrange, style, bs) + // 如果是居中,画线时重新调整 + return wrapRange(xrange, ls.TickPosition) +} + +func (ls LineSeries) Render(r chart.Renderer, canvasBox chart.Box, xrange, yrange chart.Range, defaults chart.Style) { + style := ls.Style.InheritFrom(defaults) + xrange = ls.getXRange(xrange) + chart.Draw.LineSeries(r, canvasBox, xrange, yrange, style, ls) } diff --git a/line_series_test.go b/line_series_test.go new file mode 100644 index 0000000..27c9371 --- /dev/null +++ b/line_series_test.go @@ -0,0 +1,46 @@ +// MIT License + +// Copyright (c) 2021 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2" +) + +func TestLineSeries(t *testing.T) { + assert := assert.New(t) + + ls := LineSeries{} + + originalRange := &chart.ContinuousRange{} + xrange := ls.getXRange(originalRange) + assert.Equal(originalRange, xrange) + + ls.TickPosition = chart.TickPositionBetweenTicks + xrange = ls.getXRange(originalRange) + value, ok := xrange.(*Range) + assert.True(ok) + assert.Equal(originalRange, &value.ContinuousRange) +} diff --git a/range_test.go b/range_test.go new file mode 100644 index 0000000..3e80568 --- /dev/null +++ b/range_test.go @@ -0,0 +1,54 @@ +// MIT License + +// Copyright (c) 2021 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2" +) + +func TestRange(t *testing.T) { + assert := assert.New(t) + + r := Range{ + ContinuousRange: chart.ContinuousRange{ + Min: 0, + Max: 5, + Domain: 500, + }, + } + + assert.Equal(100, r.Translate(1)) + + r.TickPosition = chart.TickPositionBetweenTicks + assert.Equal(50, r.Translate(1)) +} + +func TestHiddenRange(t *testing.T) { + assert := assert.New(t) + r := HiddenRange{} + + assert.Equal(float64(0), r.GetDelta()) +} diff --git a/series.go b/series.go index 67d8c4d..37e6c71 100644 --- a/series.go +++ b/series.go @@ -108,7 +108,6 @@ func GetSeries(series []Series, tickPosition chart.TickPosition, theme string) [ if item.YAxisIndex != 0 { baseSeries.YAxis = chart.YAxisPrimary } - // TODO 判断类型 switch item.Type { case SeriesBar: arr[index] = BarSeries{ diff --git a/series_test.go b/series_test.go new file mode 100644 index 0000000..5016aab --- /dev/null +++ b/series_test.go @@ -0,0 +1,125 @@ +// MIT License + +// Copyright (c) 2021 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2" +) + +func TestNewSeriesDataListFromFloat(t *testing.T) { + assert := assert.New(t) + + assert.Equal([]SeriesData{ + { + Value: 1, + }, + { + Value: 2, + }, + }, NewSeriesDataListFromFloat([]float64{ + 1, + 2, + })) +} + +func TestGetSeries(t *testing.T) { + assert := assert.New(t) + + xValues := []float64{ + 1, + 2, + 3, + 4, + 5, + } + + barData := NewSeriesDataListFromFloat([]float64{ + 10, + 20, + 30, + 40, + 50, + }) + barData[1].Style = chart.Style{ + FillColor: AxisColorDark, + } + seriesList := GetSeries([]Series{ + { + Type: SeriesBar, + Data: barData, + XValues: xValues, + YAxisIndex: 1, + }, + { + Data: NewSeriesDataListFromFloat([]float64{ + 11, + 21, + 31, + 41, + 51, + }), + XValues: xValues, + }, + }, chart.TickPositionBetweenTicks, "") + + assert.Equal(seriesList[0].GetYAxis(), chart.YAxisPrimary) + assert.Equal(seriesList[1].GetYAxis(), chart.YAxisSecondary) + + barSeries, ok := seriesList[0].(BarSeries) + assert.True(ok) + // 居中前置多插入一个点 + assert.Equal([]float64{ + 0, + 10, + 20, + 30, + 40, + 50, + }, barSeries.YValues) + assert.Equal(xValues, barSeries.XValues) + assert.Equal(1, barSeries.Count) + assert.Equal(0, barSeries.Index) + assert.Equal([]BarSeriesCustomStyle{ + { + PointIndex: 1, + Index: 0, + Style: barData[1].Style, + }, + }, barSeries.CustomStyles) + + lineSeries, ok := seriesList[1].(LineSeries) + assert.True(ok) + // 居中前置多插入一个点 + assert.Equal([]float64{ + 0, + 11, + 21, + 31, + 41, + 51, + }, lineSeries.YValues) + assert.Equal(xValues, lineSeries.XValues) +} diff --git a/theme.go b/theme.go index a86b282..051e099 100644 --- a/theme.go +++ b/theme.go @@ -23,6 +23,8 @@ package charts import ( + "regexp" + "strconv" "strings" "github.com/wcharczuk/go-chart/v2" @@ -44,6 +46,20 @@ var AxisColorDark = drawing.Color{ A: 255, } +var GridColorDark = drawing.Color{ + R: 72, + G: 71, + B: 83, + A: 255, +} + +var GridColorLight = drawing.Color{ + R: 224, + G: 230, + B: 241, + A: 255, +} + var BackgroundColorDark = drawing.Color{ R: 16, G: 12, @@ -67,19 +83,9 @@ func getAxisColor(theme string) drawing.Color { func getGridColor(theme string) drawing.Color { if theme == ThemeDark { - return drawing.Color{ - R: 72, - G: 71, - B: 83, - A: 255, - } - } - return drawing.Color{ - R: 224, - G: 230, - B: 241, - A: 255, + return GridColorDark } + return GridColorLight } var SeriesColorsLight = []drawing.Color{ @@ -180,12 +186,37 @@ func getSeriesColor(theme string, index int) drawing.Color { } func parseColor(color string) drawing.Color { + c := drawing.Color{} if color == "" { - return drawing.Color{} + return c } if strings.HasPrefix(color, "#") { return drawing.ColorFromHex(color[1:]) } - // TODO rgba - return drawing.Color{} + reg := regexp.MustCompile(`\((\S+)\)`) + result := reg.FindAllStringSubmatch(color, 1) + if len(result) == 0 || len(result[0]) != 2 { + return c + } + arr := strings.Split(result[0][1], ",") + if len(arr) < 3 { + return c + } + // 设置默认为255 + c.A = 255 + for index, v := range arr { + value, _ := strconv.Atoi(strings.TrimSpace(v)) + ui8 := uint8(value) + switch index { + case 0: + c.R = ui8 + case 1: + c.G = ui8 + case 2: + c.B = ui8 + default: + c.A = ui8 + } + } + return c } diff --git a/theme_test.go b/theme_test.go new file mode 100644 index 0000000..a25a2db --- /dev/null +++ b/theme_test.go @@ -0,0 +1,122 @@ +// MIT License + +// Copyright (c) 2021 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2" + "github.com/wcharczuk/go-chart/v2/drawing" +) + +func TestThemeColors(t *testing.T) { + assert := assert.New(t) + + assert.Equal(AxisColorDark, getAxisColor(ThemeDark)) + assert.Equal(AxisColorLight, getAxisColor("")) + + assert.Equal(GridColorDark, getGridColor(ThemeDark)) + assert.Equal(GridColorLight, getGridColor("")) + + assert.Equal(BackgroundColorDark, getBackgroundColor(ThemeDark)) + assert.Equal(chart.DefaultBackgroundColor, getBackgroundColor("")) + + assert.Equal(TextColorDark, getTextColor(ThemeDark)) + assert.Equal(chart.DefaultTextColor, getTextColor("")) +} + +func TestThemeColorPalette(t *testing.T) { + assert := assert.New(t) + + dark := ThemeColorPalette{ + Theme: ThemeDark, + } + assert.Equal(BackgroundColorDark, dark.BackgroundColor()) + assert.Equal(chart.DefaultBackgroundStrokeColor, dark.BackgroundStrokeColor()) + assert.Equal(BackgroundColorDark, dark.CanvasColor()) + assert.Equal(chart.DefaultCanvasStrokeColor, dark.CanvasStrokeColor()) + assert.Equal(BackgroundColorDark, dark.AxisStrokeColor()) + assert.Equal(TextColorDark, dark.TextColor()) + // series 使用统一的color + assert.Equal(SeriesColorsLight[0], dark.GetSeriesColor(0)) + + light := ThemeColorPalette{} + assert.Equal(chart.DefaultBackgroundColor, light.BackgroundColor()) + assert.Equal(chart.DefaultBackgroundStrokeColor, light.BackgroundStrokeColor()) + assert.Equal(chart.DefaultCanvasColor, light.CanvasColor()) + assert.Equal(chart.DefaultCanvasStrokeColor, light.CanvasStrokeColor()) + assert.Equal(chart.DefaultAxisColor, light.AxisStrokeColor()) + assert.Equal(chart.DefaultTextColor, light.TextColor()) + // series 使用统一的color + assert.Equal(SeriesColorsLight[0], light.GetSeriesColor(0)) +} + +func TestPieThemeColorPalette(t *testing.T) { + assert := assert.New(t) + p := PieThemeColorPalette{} + + // pie无认哪种theme,文本的颜色都一样 + assert.Equal(chart.DefaultTextColor, p.TextColor()) + p.Theme = ThemeDark + assert.Equal(chart.DefaultTextColor, p.TextColor()) +} + +func TestParseColor(t *testing.T) { + assert := assert.New(t) + + c := parseColor("") + assert.True(c.IsZero()) + + c = parseColor("#333") + assert.Equal(drawing.Color{ + R: 51, + G: 51, + B: 51, + A: 255, + }, c) + + c = parseColor("#313233") + assert.Equal(drawing.Color{ + R: 49, + G: 50, + B: 51, + A: 255, + }, c) + + c = parseColor("rgb(31,32,33)") + assert.Equal(drawing.Color{ + R: 31, + G: 32, + B: 33, + A: 255, + }, c) + + c = parseColor("rgba(50,51,52,250)") + assert.Equal(drawing.Color{ + R: 50, + G: 51, + B: 52, + A: 250, + }, c) +}