mirror of
https://shylinux.com/x/icebergs
synced 2025-04-25 17:18:05 +08:00
117 lines
3.8 KiB
Go
117 lines
3.8 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
|
|
gs *wiki.Group
|
|
Block
|
|
}
|
|
|
|
func (c *Chain) Init(m *ice.Message, arg ...string) wiki.Chart {
|
|
(&c.Block).Init(m)
|
|
|
|
m.Option(nfs.CAT_CONTENT, arg[0])
|
|
m.Option(lex.SPLIT_BLOCK, ice.SP)
|
|
max, stack := 0, kit.List(kit.Dict("_deep", -1, "width", "0"))
|
|
m.OptionCB(lex.SPLIT, func(deep int, ls []string, data ice.Map) []string {
|
|
for deep <= kit.Int(kit.Value(stack[len(stack)-1], "_deep")) {
|
|
stack = stack[:len(stack)-1]
|
|
}
|
|
width := kit.Int(kit.Value(stack[len(stack)-1], "width")) + c.GetWidths(ls[0])
|
|
stack = append(stack, kit.Dict("_deep", deep, "width", width))
|
|
if width > max {
|
|
max = width
|
|
}
|
|
return ls
|
|
})
|
|
c.data = lex.Split(m, "", mdb.TEXT)
|
|
|
|
c.Height, c.Width = c.size(m, c.data)*c.GetHeights(), max
|
|
return c
|
|
}
|
|
func (c *Chain) Draw(m *ice.Message, x, y int) wiki.Chart {
|
|
c.gs = wiki.NewGroup(m, SHIP, RECT, LINE, TEXT)
|
|
wiki.AddGroupOption(m, LINE, wiki.STROKE, c.gs.Option(SHIP, wiki.STROKE))
|
|
wiki.AddGroupOption(m, TEXT, wiki.FILL, m.Option(wiki.STROKE), wiki.STROKE_WIDTH, "1")
|
|
defer func() { c.gs.Dump(m, SHIP).Dump(m, RECT).Dump(m, LINE).Dump(m, TEXT) }()
|
|
|
|
c.Height, c.Width = 0, 0
|
|
c.draw(m, c.data, x, y, &c.Block)
|
|
return c
|
|
}
|
|
|
|
func (c *Chain) size(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.Fetch(root[mdb.LIST], func(index int, value ice.Map) { height += c.size(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) int {
|
|
meta := kit.GetMeta(root)
|
|
|
|
item := &Block{FontSize: p.FontSize, Padding: p.Padding, MarginX: p.MarginX, MarginY: p.MarginY}
|
|
item.x, item.y = x, y+(kit.Int(meta[wiki.HEIGHT])-1)*c.GetHeights()/2
|
|
item.Text = kit.Format(meta[mdb.TEXT])
|
|
if m.Option(SHOW_BLOCK) == ice.TRUE { // 方框
|
|
c.gs.EchoRect(RECT, item.GetHeight(), item.GetWidth(), item.x+item.MarginX/2, item.y+item.MarginY/2)
|
|
} else { // 横线
|
|
c.gs.EchoLine(LINE, item.x+item.MarginX/2, item.y+item.GetHeight()+item.Padding/2, item.x+item.GetWidths()-item.MarginX/2, item.y+item.GetHeight()+item.Padding/2)
|
|
}
|
|
|
|
// 文本
|
|
c.gs.EchoTexts(TEXT, item.x+item.GetWidths()/2, item.y+item.GetHeights()/2, kit.Format(meta[mdb.TEXT]))
|
|
|
|
if p != nil && p.y != 0 { // 连线
|
|
if m.Option(SHOW_BLOCK) == ice.TRUE {
|
|
x1, y1 := p.x+p.GetWidths()-(p.MarginX+item.MarginX)/4, p.y+p.GetHeights()/2
|
|
x4, y4 := item.x+(p.MarginX+item.MarginX)/4, item.y+item.GetHeights()/2
|
|
c.gs.Echo(SHIP, `<path d="M %d,%d Q %d,%d %d,%d T %d %d"></path>`, x1, y1, x1+(x4-x1)/4, y1, x1+(x4-x1)/2, y1+(y4-y1)/2, x4, y4)
|
|
} else {
|
|
x1, y1 := p.x+p.GetWidths()-(p.MarginX+item.MarginX)/4, p.y+p.GetHeight()+item.Padding/2
|
|
x4, y4 := item.x+(p.MarginX+item.MarginX)/4, item.y+item.GetHeight()+item.Padding/2
|
|
c.gs.Echo(SHIP, `<path d="M %d,%d Q %d,%d %d,%d T %d %d"></path>`, x1, y1, x1+(x4-x1)/4, y1, x1+(x4-x1)/2, y1+(y4-y1)/2, x4, y4)
|
|
}
|
|
}
|
|
|
|
// 递归
|
|
h, x := 0, x+item.GetWidths()
|
|
if kit.Fetch(root[mdb.LIST], func(index int, value ice.Map) {
|
|
h += c.draw(m, value, x, y+h, item)
|
|
}); h == 0 {
|
|
return item.GetHeights()
|
|
}
|
|
return h
|
|
}
|
|
|
|
const (
|
|
SHIP = "ship"
|
|
)
|
|
const CHAIN = "chain"
|
|
|
|
func init() {
|
|
wiki.AddChart(CHAIN, func(m *ice.Message) wiki.Chart {
|
|
m.Option(wiki.FILL, "")
|
|
m.Option(wiki.STROKE, "")
|
|
m.Option(wiki.FONT_SIZE, "16")
|
|
m.Option(wiki.STROKE_WIDTH, "2")
|
|
m.Option(wiki.PADDING, "6")
|
|
m.Option(wiki.MARGINY, "4")
|
|
m.Option(wiki.MARGINX, "40")
|
|
wiki.AddGroupOption(m, SHIP, wiki.FILL, cli.GLASS)
|
|
return &Chain{}
|
|
})
|
|
}
|