forked from x/icebergs
100 lines
3.4 KiB
Go
100 lines
3.4 KiB
Go
package chart
|
|
|
|
import (
|
|
ice "shylinux.com/x/icebergs"
|
|
"shylinux.com/x/icebergs/base/cli"
|
|
"shylinux.com/x/icebergs/base/lex"
|
|
"shylinux.com/x/icebergs/base/mdb"
|
|
"shylinux.com/x/icebergs/base/nfs"
|
|
"shylinux.com/x/icebergs/core/wiki"
|
|
kit "shylinux.com/x/toolkits"
|
|
)
|
|
|
|
type Chain struct {
|
|
data ice.Map
|
|
Block
|
|
}
|
|
|
|
func (c *Chain) Init(m *ice.Message, arg ...string) wiki.Chart {
|
|
(&c.Block).Init(m)
|
|
const _DEEP = "_deep"
|
|
stack, max := kit.List(kit.Dict(_DEEP, -1, wiki.WIDTH, "0")), 0
|
|
last := func(key string) int { return kit.Int(kit.Value(stack[len(stack)-1], key)) }
|
|
m.Cmd(lex.SPLIT, "", mdb.TEXT, kit.Dict(lex.SPLIT_BLOCK, lex.SP, nfs.CAT_CONTENT, arg[0]), func(deep int, ls []string, data, root ice.Map) {
|
|
for deep <= last(_DEEP) {
|
|
stack = stack[:len(stack)-1]
|
|
}
|
|
width := last(wiki.WIDTH) + c.GetWidths(ls[0])
|
|
if stack = append(stack, kit.Dict(_DEEP, deep, wiki.WIDTH, width)); width > max {
|
|
max = width
|
|
}
|
|
c.data = root
|
|
})
|
|
c.Height, c.Width = c.height(m, c.data)*c.GetHeights(), max
|
|
return c
|
|
}
|
|
func (c *Chain) Draw(m *ice.Message, x, y int) wiki.Chart {
|
|
gs := wiki.NewGroup(m, SHIP, LINE, RECT, TEXT)
|
|
wiki.AddGroupOption(m, LINE, wiki.STROKE, gs.Option(SHIP, wiki.STROKE))
|
|
wiki.AddGroupOption(m, TEXT, wiki.STROKE, m.Option(wiki.STROKE), wiki.FILL, m.Option(wiki.STROKE))
|
|
defer gs.DumpAll(m, SHIP, LINE, RECT, TEXT)
|
|
c.Height, c.Width = 0, 0
|
|
c.draw(m, c.data, x, y, &c.Block, gs)
|
|
return c
|
|
}
|
|
func (c *Chain) height(m *ice.Message, root ice.Map) (height int) {
|
|
meta := kit.GetMeta(root)
|
|
if list, ok := root[mdb.LIST].([]ice.Any); ok && len(list) > 0 {
|
|
kit.For(root[mdb.LIST], func(index int, value ice.Map) { height += c.height(m, value) })
|
|
} else {
|
|
height = 1
|
|
}
|
|
meta[wiki.HEIGHT] = height
|
|
return height
|
|
}
|
|
func (c *Chain) draw(m *ice.Message, root ice.Map, x, y int, p *Block, gs *wiki.Group) int {
|
|
meta := kit.GetMeta(root)
|
|
item := p.Fork(m, kit.Format(meta[mdb.TEXT]))
|
|
item.x, item.y = x, y+(kit.Int(meta[wiki.HEIGHT])-1)*c.GetHeights()/2
|
|
item.Data(m, meta)
|
|
if p != nil && p.y != 0 {
|
|
padding := item.GetHeight() / 2
|
|
kit.If(m.Option(SHOW_BLOCK) == ice.TRUE, func() { padding = 0 })
|
|
x4, y4 := item.x+(p.MarginX+item.MarginX)/4, item.y+item.GetHeights()/2+padding
|
|
x1, y1 := p.x+p.GetWidths()-(p.MarginX+item.MarginX)/4, p.y+p.GetHeights()/2+padding
|
|
gs.EchoPath(SHIP, "M %d,%d Q %d,%d %d,%d T %d %d", x1, y1, x1+(x4-x1)/4, y1, x1+(x4-x1)/2, y1+(y4-y1)/2, x4, y4)
|
|
}
|
|
if m.Option(SHOW_BLOCK) == ice.TRUE {
|
|
gs.EchoRect(RECT, item.GetHeight(), item.GetWidth(), item.x+item.MarginX/2, item.y+item.MarginY/2)
|
|
} else {
|
|
gs.EchoLine(LINE, item.x+item.MarginX/2, item.y+item.GetHeights()-item.MarginY/2, item.x+item.GetWidths()-item.MarginX/2, item.y+item.GetHeights()-item.MarginY/2)
|
|
}
|
|
gs.EchoText(TEXT, item.x+item.GetWidths()/2, item.y+item.GetHeights()/2, item.Text, item.TextData)
|
|
h, x := 0, x+item.GetWidths()
|
|
if kit.For(root[mdb.LIST], func(value ice.Map) { h += c.draw(m, value, x, y+h, item, gs) }); h == 0 {
|
|
return item.GetHeights()
|
|
}
|
|
return h
|
|
}
|
|
|
|
const (
|
|
SHOW_BLOCK = "show-block"
|
|
|
|
SHIP = "ship"
|
|
LINE = "line"
|
|
RECT = "rect"
|
|
TEXT = "text"
|
|
)
|
|
const CHAIN = "chain"
|
|
|
|
func init() {
|
|
wiki.AddChart(CHAIN, func(m *ice.Message) wiki.Chart {
|
|
m.OptionDefault(wiki.FONT_SIZE, "18")
|
|
m.OptionDefault(wiki.MARGINX, "60")
|
|
m.OptionDefault(wiki.MARGINY, "16")
|
|
m.OptionDefault(wiki.PADDING, "10")
|
|
wiki.AddGroupOption(m, SHIP, wiki.FILL, cli.TRANS)
|
|
return &Chain{}
|
|
})
|
|
}
|