build: 254ms
run: 39ms
Sometimes you may want something more sophisticated than builtin cells. For that, you can use a custom cell.
Suppose you want a cell that shows a bar chart. Let’s start by making a type for it:
type chartCell struct {
devcard.CustomCell
data []datum
tempDir string
}
type datum struct {
name string
value int
}
Note the embedded devcard.CustomCell
in chartCell
. It implements all three methods of the Cell
interface: Type
, Append
, and Erase
. The implementations of Append
and Erase
do nothing but panic when called; you need to provide your own implementations if you want to use dc.Append
or dc.Erase
. For this chart cell, this is not required—we’re going to implement our own appending function:
// addBar adds a bar to the right of the chart cell.
func (c *chartCell) addBar(name string, value int) {
c.data = append(c.data, datum{name, value})
}
To render a custom cell, it first needs to be casted it into one of the builtin cells: HTMLCell
, MarkdownCell
, MonospaceCell
, ValueCell
, AnnotatedValueCell
, ImageCell
, or ErrorCell
. For that, we need to implement Cast
method:
func (cc *chartCell2) Cast() devcard.Cell {
f, err := os.CreateTemp(cc.tempDir, "*.png")
if err != nil {
return devcard.NewErrorCell("chartCell error", err)
}
defer f.Close()
err = cc.graph().Render(chart.PNG, f)
if err != nil {
return devcard.NewErrorCell("chartCell error", err)
}
img := devcard.NewImageCell(cc.tempDir)
img.Append(f.Name())
return img
}
Now the chart cell is ready. Let’s add it to the devcard:
chart := &chartCell{
tempDir: dc.TempDir,
data: []datum{
{"Monday", 17},
{"Tuesday", 56},
{"Wednesday", 37},
{"Thursday", 39},
{"Friday", 29},
},
}
dc.Custom(chart)
Since we opted out of imlementing Append
method, we need to let the devcards app know when we’re altering our cell. It’s done by calling dc.Update
:
chart.add("Saturday", 38)
chart.add("Sunday", 30)
dc.Update(chart)