mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-25 16:58:06 +08:00
add chart.go
This commit is contained in:
parent
8646b4071f
commit
89024c6f30
271
src/examples/wiki/chart.go
Normal file
271
src/examples/wiki/chart.go
Normal file
@ -0,0 +1,271 @@
|
||||
package wiki
|
||||
|
||||
import (
|
||||
"contexts/ctx"
|
||||
mis "github.com/shylinux/toolkits"
|
||||
"strings"
|
||||
"toolkit"
|
||||
)
|
||||
|
||||
// 图形接口
|
||||
type Chart interface {
|
||||
Init(*ctx.Message, ...string) Chart
|
||||
Draw(*ctx.Message, int, int) Chart
|
||||
|
||||
GetWidth(...string) int
|
||||
GetHeight(...string) int
|
||||
}
|
||||
|
||||
// 图形基类
|
||||
type Block struct {
|
||||
Text string
|
||||
FontColor string
|
||||
BackGround string
|
||||
|
||||
FontSize int
|
||||
LineSize int
|
||||
Padding int
|
||||
Margin int
|
||||
|
||||
Width, Height int
|
||||
|
||||
TextData string
|
||||
RectData string
|
||||
}
|
||||
|
||||
func (b *Block) GetWidth(str ...string) int {
|
||||
if b.Width != 0 {
|
||||
return b.Width
|
||||
}
|
||||
return len(kit.Select(b.Text, str, 0))*b.FontSize/2 + b.Padding
|
||||
}
|
||||
func (b *Block) GetHeight(str ...string) int {
|
||||
if b.Height != 0 {
|
||||
return b.Height
|
||||
}
|
||||
return b.FontSize*b.LineSize/10 + b.Padding
|
||||
}
|
||||
func (b *Block) GetWidths(str ...string) int {
|
||||
return b.GetWidth(str...) + b.Margin
|
||||
}
|
||||
func (b *Block) GetHeights(str ...string) int {
|
||||
return b.GetHeight() + b.Margin
|
||||
}
|
||||
func (b *Block) Init(m *ctx.Message, arg ...string) Chart {
|
||||
b.Text = kit.Select(b.Text, arg, 0)
|
||||
b.FontColor = kit.Select("white", kit.Select(b.FontColor, arg, 1))
|
||||
b.BackGround = kit.Select("red", kit.Select(b.BackGround, arg, 2))
|
||||
b.FontSize = kit.Int(kit.Select("24", kit.Select(kit.Format(b.FontSize), arg, 3)))
|
||||
b.LineSize = kit.Int(kit.Select("12", kit.Select(kit.Format(b.LineSize), arg, 4)))
|
||||
return b
|
||||
}
|
||||
func (b *Block) Draw(m *ctx.Message, x, y int) Chart {
|
||||
m.Echo(`<rect x="%d" y="%d" width="%d" height="%d" fill="%s" %v/>`,
|
||||
x+b.Margin/2, y+b.Margin/2, b.GetWidth(), b.GetHeight(), b.BackGround, b.RectData)
|
||||
m.Echo(`<text x="%d" y="%d" font-size="%d" style="dominant-baseline:middle;text-anchor:middle;" fill="%s" %v>%v</text>`,
|
||||
x+b.GetWidths()/2, y+b.GetHeights()/2, b.FontSize, b.FontColor, b.TextData, b.Text)
|
||||
return b
|
||||
}
|
||||
func (b *Block) Data(root interface{}) {
|
||||
mis.Table(mis.Value(root, "data"), 0, 100, func(key string, value string) {
|
||||
b.TextData += key + "='" + value + "' "
|
||||
})
|
||||
mis.Table(mis.Value(root, "rect"), 0, 100, func(key string, value string) {
|
||||
b.RectData += key + "='" + value + "' "
|
||||
})
|
||||
b.FontColor = kit.Select(b.FontColor, mis.Value(root, "fg"))
|
||||
b.BackGround = kit.Select(b.BackGround, mis.Value(root, "bg"))
|
||||
}
|
||||
|
||||
type Chain struct {
|
||||
data map[string]interface{}
|
||||
max map[int]int
|
||||
Block
|
||||
}
|
||||
|
||||
func (b *Chain) Init(m *ctx.Message, arg ...string) Chart {
|
||||
// 解析数据
|
||||
b.data = mis.Parse(nil, "", b.show(m, arg[0])...).(map[string]interface{})
|
||||
b.FontColor = kit.Select("white", arg, 1)
|
||||
b.BackGround = kit.Select("red", arg, 2)
|
||||
b.FontSize = kit.Int(kit.Select("24", arg, 3))
|
||||
b.LineSize = kit.Int(kit.Select("12", arg, 4))
|
||||
b.Padding = kit.Int(kit.Select("8", arg, 5))
|
||||
b.Margin = kit.Int(kit.Select("8", arg, 6))
|
||||
|
||||
// 计算尺寸
|
||||
b.max = map[int]int{}
|
||||
b.Height = b.size(m, b.data, 0, b.max) * b.GetHeights()
|
||||
width := 0
|
||||
for _, v := range b.max {
|
||||
width += b.GetWidths(strings.Repeat(" ", v))
|
||||
}
|
||||
b.Width = width
|
||||
m.Log("info", "data %v", kit.Formats(b.data))
|
||||
return b
|
||||
}
|
||||
func (b *Chain) show(m *ctx.Message, str string) (res []string) {
|
||||
miss := []int{}
|
||||
list := mis.Split(str, "\n")
|
||||
for _, line := range list {
|
||||
// 计算缩进
|
||||
dep := 0
|
||||
loop:
|
||||
for _, v := range []rune(line) {
|
||||
switch v {
|
||||
case ' ':
|
||||
dep++
|
||||
case '\t':
|
||||
dep += 4
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
// 计算层次
|
||||
if len(miss) > 0 {
|
||||
if miss[len(miss)-1] > dep {
|
||||
for i := len(miss) - 1; i >= 0; i-- {
|
||||
if miss[i] < dep {
|
||||
break
|
||||
}
|
||||
res = append(res, "]", "}")
|
||||
miss = miss[:i]
|
||||
}
|
||||
miss = append(miss, dep)
|
||||
} else if miss[len(miss)-1] < dep {
|
||||
miss = append(miss, dep)
|
||||
} else {
|
||||
res = append(res, "]", "}")
|
||||
}
|
||||
} else {
|
||||
miss = append(miss, dep)
|
||||
}
|
||||
|
||||
// 输出节点
|
||||
word := mis.Split(line)
|
||||
res = append(res, "{", "meta", "{", "text")
|
||||
res = append(res, word...)
|
||||
res = append(res, "}", "list", "[")
|
||||
}
|
||||
return
|
||||
}
|
||||
func (b *Chain) size(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int) int {
|
||||
meta := root["meta"].(map[string]interface{})
|
||||
|
||||
// 最大宽度
|
||||
text := kit.Format(meta["text"])
|
||||
if len(text) > width[depth] {
|
||||
width[depth] = len(text)
|
||||
}
|
||||
|
||||
// 计算高度
|
||||
height := 0
|
||||
if list, ok := root["list"].([]interface{}); ok && len(list) > 0 {
|
||||
kit.Map(root["list"], "", func(index int, value map[string]interface{}) {
|
||||
height += b.size(m, value, depth+1, width)
|
||||
})
|
||||
} else {
|
||||
height = 1
|
||||
}
|
||||
|
||||
meta["height"] = height
|
||||
return height
|
||||
}
|
||||
func (b *Chain) draw(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int, x int, y int) Chart {
|
||||
meta := root["meta"].(map[string]interface{})
|
||||
b.Width, b.Height = 0, 0
|
||||
|
||||
// 当前节点
|
||||
block := &Block{
|
||||
BackGround: kit.Select(b.BackGround, meta["bg"]),
|
||||
FontColor: kit.Select(b.FontColor, meta["fg"]),
|
||||
FontSize: b.FontSize,
|
||||
LineSize: b.LineSize,
|
||||
Padding: b.Padding,
|
||||
Margin: b.Margin,
|
||||
Width: b.GetWidth(strings.Repeat(" ", width[depth])),
|
||||
}
|
||||
|
||||
block.Data(root["meta"])
|
||||
block.Init(m, kit.Format(meta["text"])).Draw(m, x, y+(kit.Int(meta["height"])-1)*b.GetHeights()/2)
|
||||
|
||||
// 递归节点
|
||||
kit.Map(root["list"], "", func(index int, value map[string]interface{}) {
|
||||
b.draw(m, value, depth+1, width, x+b.GetWidths(strings.Repeat(" ", width[depth])), y)
|
||||
y += kit.Int(kit.Chain(value, "meta.height")) * b.GetHeights()
|
||||
})
|
||||
return b
|
||||
}
|
||||
func (b *Chain) Draw(m *ctx.Message, x, y int) Chart {
|
||||
return b.draw(m, b.data, 0, b.max, x, y)
|
||||
}
|
||||
|
||||
type Table struct {
|
||||
data [][]string
|
||||
max map[int]int
|
||||
Block
|
||||
}
|
||||
|
||||
func (b *Table) Init(m *ctx.Message, arg ...string) Chart {
|
||||
// 解析数据
|
||||
b.max = map[int]int{}
|
||||
for _, v := range mis.Split(arg[0], "\n") {
|
||||
l := mis.Split(v)
|
||||
for i, v := range l {
|
||||
switch data := mis.Parse(nil, "", mis.Split(v)...).(type) {
|
||||
case map[string]interface{}:
|
||||
v = kit.Select("", data["text"])
|
||||
}
|
||||
if len(v) > b.max[i] {
|
||||
b.max[i] = len(v)
|
||||
}
|
||||
}
|
||||
b.data = append(b.data, l)
|
||||
}
|
||||
b.FontColor = kit.Select("white", arg, 1)
|
||||
b.BackGround = kit.Select("red", arg, 2)
|
||||
b.FontSize = kit.Int(kit.Select("24", arg, 3))
|
||||
b.LineSize = kit.Int(kit.Select("12", arg, 4))
|
||||
b.Padding = kit.Int(kit.Select("8", arg, 5))
|
||||
b.Margin = kit.Int(kit.Select("8", arg, 6))
|
||||
|
||||
// 计算尺寸
|
||||
width := 0
|
||||
for _, v := range b.max {
|
||||
width += b.GetWidths(strings.Repeat(" ", v))
|
||||
}
|
||||
b.Width = width
|
||||
b.Height = len(b.data) * b.GetHeights()
|
||||
|
||||
m.Log("info", "data %v", kit.Formats(b.data))
|
||||
return b
|
||||
}
|
||||
func (b *Table) Draw(m *ctx.Message, x, y int) Chart {
|
||||
b.Width, b.Height = 0, 0
|
||||
for n, line := range b.data {
|
||||
for i, text := range line {
|
||||
l := 0
|
||||
for j := 0; j < i; j++ {
|
||||
l += b.GetWidths(strings.Repeat(" ", b.max[i]))
|
||||
}
|
||||
block := &Block{
|
||||
BackGround: kit.Select(b.BackGround),
|
||||
FontColor: kit.Select(b.FontColor),
|
||||
FontSize: b.FontSize,
|
||||
LineSize: b.LineSize,
|
||||
Padding: b.Padding,
|
||||
Margin: b.Margin,
|
||||
Width: b.GetWidth(strings.Repeat(" ", b.max[i])),
|
||||
}
|
||||
|
||||
switch data := mis.Parse(nil, "", mis.Split(text)...).(type) {
|
||||
case map[string]interface{}:
|
||||
text = kit.Select(text, data["text"])
|
||||
block.Data(data)
|
||||
}
|
||||
block.Init(m, text).Draw(m, x+l, y+n*b.GetHeights())
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
@ -386,6 +386,26 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
|
||||
m.Cmdy("cli.system", "cmd_dir", arg[0], "bash", "-c", strings.Join(arg[1:], " "))
|
||||
return
|
||||
}},
|
||||
"chart": {Name: "chart type text", Help: "绘图", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Option("render", "raw")
|
||||
var chart Chart
|
||||
switch arg[0] {
|
||||
case "block":
|
||||
chart = &Block{}
|
||||
case "chain":
|
||||
chart = &Chain{}
|
||||
case "table":
|
||||
chart = &Table{}
|
||||
}
|
||||
arg[1] = strings.TrimSpace(arg[1])
|
||||
|
||||
chart.Init(m, arg[1:]...)
|
||||
m.Echo(`<svg vertion="1.1" xmlns="http://www.w3.org/2000/svg" width="%d", height="%d">`,
|
||||
chart.GetWidth(), chart.GetHeight())
|
||||
chart.Draw(m, 0, 0)
|
||||
m.Echo(`</svg>`)
|
||||
return
|
||||
}},
|
||||
|
||||
"title": {Name: "title text", Help: "一级标题", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) {
|
||||
ns := strings.Split(m.Conf("runtime", "node.name"), "-")
|
||||
@ -450,7 +470,6 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
|
||||
}
|
||||
if len(arg) > 3 {
|
||||
data = mis.Parse(nil, "", show(m, arg[3])...).(map[string]interface{})
|
||||
m.Log("what", "%v", mis.Formats(data))
|
||||
}
|
||||
|
||||
max := map[int]int{}
|
||||
|
@ -41,11 +41,11 @@ kit xls "表格" "index.js" "index.css" private "web.wiki.xls" \
|
||||
feature style "mind" \
|
||||
exports xls_id id
|
||||
|
||||
kit svg "" public "web.wiki.svg" \
|
||||
select "" name type values "16 30 48 60" action auto \
|
||||
kit chart "图表" public "web.wiki.chart" \
|
||||
select "" name type values "chain block" action auto \
|
||||
textarea "" name happy half 4 height "200px" \
|
||||
select "" name type values "white red yellow green blue black" action auto \
|
||||
select "" name type values "black blue green yellow red white" action auto \
|
||||
textarea "" name happy half 4 height "200px" \
|
||||
feature display svg \
|
||||
button "查看"
|
||||
|
||||
|
@ -79,13 +79,13 @@ func Select(value string, args ...interface{}) string {
|
||||
if len(args) > 1 {
|
||||
switch b := args[1].(type) {
|
||||
case bool:
|
||||
if b && arg != "" {
|
||||
if b && Right(arg) {
|
||||
return arg
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
if arg != "" {
|
||||
if Right(arg) {
|
||||
return arg
|
||||
}
|
||||
case []interface{}:
|
||||
|
@ -1,6 +1,35 @@
|
||||
# {{title "Hello World"}}
|
||||
|
||||
{{runs "help"}}
|
||||
{{chart "block" `hello 慕尼黑 world` "white" "red" "32"}}
|
||||
{{chart "block" `hello world` "red" "green"}}
|
||||
|
||||
{{chart "chain" `
|
||||
chat
|
||||
ocean
|
||||
river
|
||||
dream fg red bg white
|
||||
zsh
|
||||
auto.sh
|
||||
tmux
|
||||
docker
|
||||
git
|
||||
vim data { hi hello } rect { nice world }
|
||||
auto.vim
|
||||
storm
|
||||
steam
|
||||
`}}
|
||||
|
||||
{{chart "table" `
|
||||
'{ text 宇宙 fg white bg green }' '{ text 天文 fg red bg white }' 气象 地质
|
||||
'{ text 物理 fg white bg blue' 物质 '{ text 能量 fg red bg white }' 信息
|
||||
'{ text 数学 fg white bg green }' '{ text 代数 fg red bg white }' 函数 几何
|
||||
'{ text 生命 fg white bg blue' 基因 '{ text 组织 fg red bg white }' 系统
|
||||
`}}
|
||||
|
||||
{{chart "table" `
|
||||
'{ text 编程 fg white bg green }' '{ text 语言 fg red bg white }' 框架 平台
|
||||
'{ text 设计 fg white bg blue' 功能 '{ text 性能 fg red bg white }' 智能
|
||||
`}}
|
||||
|
||||
命令 参数 选项 配置
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user