Skip to content

Commit

Permalink
feat: implement legend type with fixed length line on the left side
Browse files Browse the repository at this point in the history
  • Loading branch information
d-Rickyy-b committed Feb 5, 2022
1 parent c1468e8 commit f87c256
Showing 1 changed file with 118 additions and 0 deletions.
118 changes: 118 additions & 0 deletions legend.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,124 @@ func Legend(c *Chart, userDefaults ...Style) Renderable {
}
}

// LegendLineLeft is a legend with the line drawn left to the legend text.
func LegendLineLeft(c *Chart, userDefaults ...Style) Renderable {
return func(r Renderer, cb Box, chartDefaults Style) {
legendDefaults := Style{
FillColor: drawing.ColorWhite,
FontColor: DefaultTextColor,
FontSize: 8.0,
StrokeColor: DefaultAxisColor,
StrokeWidth: DefaultAxisLineWidth,
}

var legendStyle Style
if len(userDefaults) > 0 {
legendStyle = userDefaults[0].InheritFrom(chartDefaults.InheritFrom(legendDefaults))
} else {
legendStyle = chartDefaults.InheritFrom(legendDefaults)
}

// DEFAULTS
legendPadding := Box{
Top: 5,
Left: 5,
Right: 5,
Bottom: 5,
}
lineTextGap := 5
lineLengthMinimum := 25

var labels []string
var lines []Style
for index, s := range c.Series {
if !s.GetStyle().Hidden {
if _, isAnnotationSeries := s.(AnnotationSeries); !isAnnotationSeries {
labels = append(labels, s.GetName())
lines = append(lines, s.GetStyle().InheritFrom(c.styleDefaultsSeries(index)))
}
}
}

legend := Box{
Top: cb.Top,
Left: cb.Left,
// bottom and right will be sized by the legend content + relevant padding.
}

legendContent := Box{
Top: legend.Top + legendPadding.Top,
Left: legend.Left + legendPadding.Left,
Right: legend.Left + legendPadding.Left,
Bottom: legend.Top + legendPadding.Top,
}

legendStyle.GetTextOptions().WriteToRenderer(r)

// measure
labelCount := 0
for x := 0; x < len(labels); x++ {
if len(labels[x]) > 0 {
tb := r.MeasureText(labels[x])
if labelCount > 0 {
legendContent.Bottom += DefaultMinimumTickVerticalSpacing
}
legendContent.Bottom += tb.Height()
right := legendContent.Left + tb.Width() + lineTextGap + lineLengthMinimum
legendContent.Right = MaxInt(legendContent.Right, right)
labelCount++
}
}

legend = legend.Grow(legendContent)
legend.Right = legendContent.Right + legendPadding.Right
legend.Bottom = legendContent.Bottom + legendPadding.Bottom

Draw.Box(r, legend, legendStyle)

legendStyle.GetTextOptions().WriteToRenderer(r)

ycursor := legendContent.Top
lx := legendContent.Left
legendCount := 0
var label string
for x := 0; x < len(labels); x++ {
label = labels[x]
if len(label) > 0 {
if legendCount > 0 {
ycursor += DefaultMinimumTickVerticalSpacing
}

// Calculate text dimensions
tb := r.MeasureText(label)
ty := ycursor + tb.Height()
th2 := tb.Height() >> 1

// Calculate line x and y coordinates
ly := ty - th2

// Calculate line ending x coordinate
lx2 := lx + lineLengthMinimum

r.SetStrokeColor(lines[x].GetStrokeColor())
r.SetStrokeWidth(lines[x].GetStrokeWidth())
r.SetStrokeDashArray(lines[x].GetStrokeDashArray())

r.MoveTo(lx, ly)
r.LineTo(lx2, ly)
r.Stroke()

// Calculate Text starting coordinates
textX := lx2 + lineTextGap
r.Text(label, textX, ty)

ycursor += tb.Height()
legendCount++
}
}
}
}

// LegendThin is a legend that doesn't obscure the chart area.
func LegendThin(c *Chart, userDefaults ...Style) Renderable {
return func(r Renderer, cb Box, chartDefaults Style) {
Expand Down

0 comments on commit f87c256

Please sign in to comment.