1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-26 01:24:05 +08:00
icebergs/core/wiki/chart/chain.go
2023-11-02 23:25:31 +08:00

99 lines
3.3 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.MARGINX, "60")
m.OptionDefault(wiki.MARGINY, "16")
m.OptionDefault(wiki.PADDING, "10")
wiki.AddGroupOption(m, SHIP, wiki.FILL, cli.TRANS)
return &Chain{}
})
}