Add LineChart and BarChart
This commit is contained in:
		
							parent
							
								
									8351d8f305
								
							
						
					
					
						commit
						92a301a247
					
				
							
								
								
									
										96
									
								
								bar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								bar.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | package termui | ||||||
|  | 
 | ||||||
|  | import "fmt" | ||||||
|  | 
 | ||||||
|  | type BarChart struct { | ||||||
|  | 	Block | ||||||
|  | 	BarColor   Attribute | ||||||
|  | 	TextColor  Attribute | ||||||
|  | 	NumColor   Attribute | ||||||
|  | 	Data       []int | ||||||
|  | 	DataLabels []string | ||||||
|  | 	BarWidth   int | ||||||
|  | 	BarGap     int | ||||||
|  | 	labels     [][]rune | ||||||
|  | 	dataNum    [][]rune | ||||||
|  | 	numBar     int | ||||||
|  | 	scale      float64 | ||||||
|  | 	max        int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewBarChart() *BarChart { | ||||||
|  | 	bc := &BarChart{Block: *NewBlock()} | ||||||
|  | 	bc.BarColor = ColorCyan | ||||||
|  | 	bc.NumColor = ColorWhite | ||||||
|  | 	bc.TextColor = ColorWhite | ||||||
|  | 	bc.BarGap = 1 | ||||||
|  | 	bc.BarWidth = 3 | ||||||
|  | 	return bc | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (bc *BarChart) layout() { | ||||||
|  | 	bc.numBar = bc.innerWidth / (bc.BarGap + bc.BarWidth) | ||||||
|  | 	bc.labels = make([][]rune, bc.numBar) | ||||||
|  | 	bc.dataNum = make([][]rune, len(bc.Data)) | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < bc.numBar && i < len(bc.DataLabels) && i < len(bc.Data); i++ { | ||||||
|  | 		bc.labels[i] = trimStr2Runes(bc.DataLabels[i], bc.BarWidth) | ||||||
|  | 		n := bc.Data[i] | ||||||
|  | 		s := fmt.Sprint(n) | ||||||
|  | 		bc.dataNum[i] = trimStr2Runes(s, bc.BarWidth) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bc.max = bc.Data[0] //  what if Data is nil? | ||||||
|  | 	for i := 0; i < len(bc.Data); i++ { | ||||||
|  | 		if bc.max < bc.Data[i] { | ||||||
|  | 			bc.max = bc.Data[i] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	bc.scale = float64(bc.max) / float64(bc.innerHeight-1) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (bc *BarChart) Buffer() []Point { | ||||||
|  | 	ps := bc.Block.Buffer() | ||||||
|  | 	bc.layout() | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < bc.numBar && i < len(bc.Data) && i < len(bc.DataLabels); i++ { | ||||||
|  | 		h := int(float64(bc.Data[i]) / bc.scale) | ||||||
|  | 		oftX := i * (bc.BarWidth + bc.BarGap) | ||||||
|  | 		// plot bar | ||||||
|  | 		for j := 0; j < bc.BarWidth; j++ { | ||||||
|  | 			for k := 0; k < h; k++ { | ||||||
|  | 				p := Point{} | ||||||
|  | 				p.Code.Ch = ' ' | ||||||
|  | 				p.Code.Bg = toTmAttr(bc.BarColor) | ||||||
|  | 				p.X = bc.innerX + i*(bc.BarWidth+bc.BarGap) + j | ||||||
|  | 				p.Y = bc.innerY + bc.innerHeight - 2 - k | ||||||
|  | 				ps = append(ps, p) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// plot text | ||||||
|  | 		for j := 0; j < len(bc.labels[i]); j++ { | ||||||
|  | 			p := Point{} | ||||||
|  | 			p.Code.Ch = bc.labels[i][j] | ||||||
|  | 			p.Code.Bg = toTmAttr(bc.BgColor) | ||||||
|  | 			p.Code.Fg = toTmAttr(bc.TextColor) | ||||||
|  | 			p.Y = bc.innerY + bc.innerHeight - 1 | ||||||
|  | 			p.X = bc.innerX + oftX + j | ||||||
|  | 			ps = append(ps, p) | ||||||
|  | 		} | ||||||
|  | 		// plot num | ||||||
|  | 		for j := 0; j < len(bc.dataNum[i]); j++ { | ||||||
|  | 			p := Point{} | ||||||
|  | 			p.Code.Ch = bc.dataNum[i][j] | ||||||
|  | 			p.Code.Fg = toTmAttr(bc.NumColor) | ||||||
|  | 			p.Code.Bg = toTmAttr(bc.BarColor) | ||||||
|  | 			if h == 0 { | ||||||
|  | 				p.Code.Bg = toTmAttr(bc.BgColor) | ||||||
|  | 			} | ||||||
|  | 			p.X = bc.innerX + oftX + (bc.BarWidth-len(bc.dataNum[i]))/2 + j | ||||||
|  | 			p.Y = bc.innerY + bc.innerHeight - 2 | ||||||
|  | 			ps = append(ps, p) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ps | ||||||
|  | } | ||||||
							
								
								
									
										279
									
								
								chart.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								chart.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,279 @@ | |||||||
|  | package termui | ||||||
|  | 
 | ||||||
|  | import "fmt" | ||||||
|  | import tm "github.com/nsf/termbox-go" | ||||||
|  | 
 | ||||||
|  | const VDASH = '┊' | ||||||
|  | const HDASH = '┈' | ||||||
|  | const ORIGIN = '└' | ||||||
|  | 
 | ||||||
|  | // only 16 possible combinations, why bother | ||||||
|  | var braillePatterns = map[[2]int]rune{ | ||||||
|  | 	[2]int{0, 0}: '⣀', | ||||||
|  | 	[2]int{0, 1}: '⡠', | ||||||
|  | 	[2]int{0, 2}: '⡐', | ||||||
|  | 	[2]int{0, 3}: '⡈', | ||||||
|  | 
 | ||||||
|  | 	[2]int{1, 0}: '⢄', | ||||||
|  | 	[2]int{1, 1}: '⠤', | ||||||
|  | 	[2]int{1, 2}: '⠔', | ||||||
|  | 	[2]int{1, 3}: '⠌', | ||||||
|  | 
 | ||||||
|  | 	[2]int{2, 0}: '⢂', | ||||||
|  | 	[2]int{2, 1}: '⠢', | ||||||
|  | 	[2]int{2, 2}: '⠒', | ||||||
|  | 	[2]int{2, 3}: '⠊', | ||||||
|  | 
 | ||||||
|  | 	[2]int{3, 0}: '⢁', | ||||||
|  | 	[2]int{3, 1}: '⠡', | ||||||
|  | 	[2]int{3, 2}: '⠑', | ||||||
|  | 	[2]int{3, 3}: '⠉', | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type LineChart struct { | ||||||
|  | 	Block | ||||||
|  | 	Data          []float64 | ||||||
|  | 	DataLabels    []string | ||||||
|  | 	Mode          string // braille | dot | ||||||
|  | 	DotStyle      rune | ||||||
|  | 	LineColor     Attribute | ||||||
|  | 	scale         float64 | ||||||
|  | 	AxesColor     Attribute | ||||||
|  | 	drawingX      int | ||||||
|  | 	drawingY      int | ||||||
|  | 	axisYHeight   int | ||||||
|  | 	axisXWidth    int | ||||||
|  | 	axisYLebelGap int | ||||||
|  | 	axisXLebelGap int | ||||||
|  | 	topValue      float64 | ||||||
|  | 	bottomValue   float64 | ||||||
|  | 	labelX        [][]rune | ||||||
|  | 	labelY        [][]rune | ||||||
|  | 	labelYSpace   int | ||||||
|  | 	maxY          float64 | ||||||
|  | 	minY          float64 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewLineChart() *LineChart { | ||||||
|  | 	lc := &LineChart{Block: *NewBlock()} | ||||||
|  | 	lc.Mode = "braille" | ||||||
|  | 	lc.DotStyle = '•' | ||||||
|  | 	lc.axisXLebelGap = 2 | ||||||
|  | 	lc.axisYLebelGap = 1 | ||||||
|  | 	return lc | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // one cell contains two data points | ||||||
|  | func (lc *LineChart) renderBraille() []Point { | ||||||
|  | 	ps := []Point{} | ||||||
|  | 	getBaseMod := func(d float64) (b, m int) { | ||||||
|  | 		b = int((d - lc.minY) / lc.scale) | ||||||
|  | 		m = int(((d-lc.minY)-float64(b)*lc.scale)/0.25 + 0.5) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i+1 < len(lc.Data) && i/2 < lc.axisXWidth; i += 2 { | ||||||
|  | 		b0, m0 := getBaseMod(lc.Data[i]) | ||||||
|  | 		b1, m1 := getBaseMod(lc.Data[i+1]) | ||||||
|  | 
 | ||||||
|  | 		if b0 > b1 { | ||||||
|  | 			m1 = 0 | ||||||
|  | 		} | ||||||
|  | 		if b0 < b1 { | ||||||
|  | 			m1 = 3 | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		p := Point{} | ||||||
|  | 		p.Code.Ch = braillePatterns[[2]int{m0, m1}] | ||||||
|  | 		p.Code.Bg = toTmAttr(lc.BgColor) | ||||||
|  | 		p.Code.Fg = toTmAttr(lc.LineColor) | ||||||
|  | 		p.Y = lc.innerY + lc.innerHeight - 3 - b0 | ||||||
|  | 		p.X = lc.innerX + lc.labelYSpace + 1 + i/2 | ||||||
|  | 		ps = append(ps, p) | ||||||
|  | 	} | ||||||
|  | 	return ps | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lc *LineChart) renderDot() []Point { | ||||||
|  | 	ps := []Point{} | ||||||
|  | 	for i := 0; i < len(lc.Data) && i < lc.axisXWidth; i++ { | ||||||
|  | 		p := Point{} | ||||||
|  | 		p.Code.Ch = lc.DotStyle | ||||||
|  | 		p.Code.Fg = toTmAttr(lc.LineColor) | ||||||
|  | 		p.Code.Bg = toTmAttr(lc.BgColor) | ||||||
|  | 		p.X = lc.innerX + lc.labelYSpace + 1 + i | ||||||
|  | 		p.Y = lc.innerY + lc.innerHeight - 3 - int((lc.Data[i]-lc.minY)/lc.scale+0.5) | ||||||
|  | 		ps = append(ps, p) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ps | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lc *LineChart) calcLabelX() { | ||||||
|  | 	lc.labelX = [][]rune{} | ||||||
|  | 
 | ||||||
|  | 	for i, l := 0, 0; i < len(lc.DataLabels) && l < lc.axisXWidth; i++ { | ||||||
|  | 		if lc.Mode == "dot" { | ||||||
|  | 			if l >= len(lc.DataLabels) { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			s := str2runes(lc.DataLabels[l]) | ||||||
|  | 			if l+len(s) <= lc.axisXWidth { | ||||||
|  | 				lc.labelX = append(lc.labelX, s) | ||||||
|  | 			} | ||||||
|  | 			l += (len(s) + lc.axisXLebelGap) // -1 needed | ||||||
|  | 		} else { | ||||||
|  | 			if 2*l >= len(lc.DataLabels) { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			s := str2runes(lc.DataLabels[2*l]) | ||||||
|  | 			if l+len(s) <= lc.axisXWidth { | ||||||
|  | 				lc.labelX = append(lc.labelX, s) | ||||||
|  | 			} | ||||||
|  | 			l += (len(s) + lc.axisXLebelGap) // -1 needed | ||||||
|  | 
 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func shortenFloatVal(x float64) string { | ||||||
|  | 	s := fmt.Sprintf("%.2f", x) | ||||||
|  | 	if len(s)-3 > 3 { | ||||||
|  | 		s = fmt.Sprintf("%.2e", x) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if x < 0 { | ||||||
|  | 		s = fmt.Sprintf("%.2f", x) | ||||||
|  | 	} | ||||||
|  | 	return s | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lc *LineChart) calcLabelY() { | ||||||
|  | 	span := lc.topValue - lc.bottomValue | ||||||
|  | 	lc.scale = span / float64(lc.axisYHeight) | ||||||
|  | 
 | ||||||
|  | 	n := (1 + lc.axisYHeight) / (lc.axisYLebelGap + 1) | ||||||
|  | 	lc.labelY = make([][]rune, n) | ||||||
|  | 	maxLen := 0 | ||||||
|  | 	for i := 0; i < n; i++ { | ||||||
|  | 		s := str2runes(shortenFloatVal(lc.bottomValue + float64(i)*span/float64(n))) | ||||||
|  | 		if len(s) > maxLen { | ||||||
|  | 			maxLen = len(s) | ||||||
|  | 		} | ||||||
|  | 		lc.labelY[i] = s | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lc.labelYSpace = maxLen | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lc *LineChart) calcLayout() { | ||||||
|  | 	if lc.DataLabels == nil || len(lc.DataLabels) == 0 { | ||||||
|  | 		lc.DataLabels = make([]string, len(lc.Data)) | ||||||
|  | 		for i := range lc.Data { | ||||||
|  | 			lc.DataLabels[i] = fmt.Sprint(i) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lc.minY = lc.Data[0] | ||||||
|  | 	lc.maxY = lc.Data[0] | ||||||
|  | 	for _, v := range lc.Data { | ||||||
|  | 		if v > lc.maxY { | ||||||
|  | 			lc.maxY = v | ||||||
|  | 		} | ||||||
|  | 		if v < lc.minY { | ||||||
|  | 			lc.minY = v | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lc.topValue = lc.maxY * 1.2 | ||||||
|  | 	lc.bottomValue = lc.minY * 0.8 //- 0.05*(lc.maxY-lc.minY) | ||||||
|  | 	if lc.minY < 0 { | ||||||
|  | 		lc.bottomValue = lc.minY * 1.2 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lc.axisYHeight = lc.innerHeight - 2 | ||||||
|  | 	lc.calcLabelY() | ||||||
|  | 
 | ||||||
|  | 	lc.axisXWidth = lc.innerWidth - 1 - lc.labelYSpace | ||||||
|  | 	lc.calcLabelX() | ||||||
|  | 
 | ||||||
|  | 	lc.drawingX = lc.innerX + 1 + lc.labelYSpace | ||||||
|  | 	lc.drawingY = lc.innerY | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lc *LineChart) plotAxes() []Point { | ||||||
|  | 	origY := lc.innerY + lc.innerHeight - 2 | ||||||
|  | 	origX := lc.innerX + lc.labelYSpace | ||||||
|  | 
 | ||||||
|  | 	ps := []Point{Point{Code: tm.Cell{Ch: ORIGIN, Bg: toTmAttr(lc.BgColor), Fg: toTmAttr(lc.AxesColor)}, | ||||||
|  | 		X: origX, | ||||||
|  | 		Y: origY}} | ||||||
|  | 
 | ||||||
|  | 	for x := origX + 1; x < origX+lc.axisXWidth; x++ { | ||||||
|  | 		p := Point{} | ||||||
|  | 		p.X = x | ||||||
|  | 		p.Y = origY | ||||||
|  | 		p.Code.Bg = toTmAttr(lc.BgColor) | ||||||
|  | 		p.Code.Fg = toTmAttr(lc.AxesColor) | ||||||
|  | 		p.Code.Ch = HDASH | ||||||
|  | 		ps = append(ps, p) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for dy := 1; dy <= lc.axisYHeight; dy++ { | ||||||
|  | 		p := Point{} | ||||||
|  | 		p.X = origX | ||||||
|  | 		p.Y = origY - dy | ||||||
|  | 		p.Code.Bg = toTmAttr(lc.BgColor) | ||||||
|  | 		p.Code.Fg = toTmAttr(lc.AxesColor) | ||||||
|  | 		p.Code.Ch = VDASH | ||||||
|  | 		ps = append(ps, p) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// x label | ||||||
|  | 	oft := 0 | ||||||
|  | 	for _, rs := range lc.labelX { | ||||||
|  | 		if oft+len(rs) > lc.axisXWidth { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		for j, r := range rs { | ||||||
|  | 			p := Point{} | ||||||
|  | 			p.Code.Ch = r | ||||||
|  | 			p.Code.Fg = toTmAttr(lc.AxesColor) | ||||||
|  | 			p.Code.Bg = toTmAttr(lc.BgColor) | ||||||
|  | 			p.X = origX + oft + j | ||||||
|  | 			p.Y = lc.innerY + lc.innerHeight - 1 | ||||||
|  | 			ps = append(ps, p) | ||||||
|  | 		} | ||||||
|  | 		oft += len(rs) + lc.axisXLebelGap | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// y labels | ||||||
|  | 	for i, rs := range lc.labelY { | ||||||
|  | 		for j, r := range rs { | ||||||
|  | 			p := Point{} | ||||||
|  | 			p.Code.Ch = r | ||||||
|  | 			p.Code.Fg = toTmAttr(lc.AxesColor) | ||||||
|  | 			p.Code.Bg = toTmAttr(lc.BgColor) | ||||||
|  | 			p.X = lc.innerX + j | ||||||
|  | 			p.Y = origY - i*(lc.axisYLebelGap+1) | ||||||
|  | 			ps = append(ps, p) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ps | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lc *LineChart) Buffer() []Point { | ||||||
|  | 	ps := lc.Block.Buffer() | ||||||
|  | 	lc.calcLayout() | ||||||
|  | 	ps = append(ps, lc.plotAxes()...) | ||||||
|  | 
 | ||||||
|  | 	if lc.Mode == "dot" { | ||||||
|  | 		ps = append(ps, lc.renderDot()...) | ||||||
|  | 	} else { | ||||||
|  | 		ps = append(ps, lc.renderBraille()...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ps | ||||||
|  | } | ||||||
| @ -2,6 +2,8 @@ package main | |||||||
| 
 | 
 | ||||||
| import ui "github.com/gizak/termui" | import ui "github.com/gizak/termui" | ||||||
| import tm "github.com/nsf/termbox-go" | import tm "github.com/nsf/termbox-go" | ||||||
|  | import "math" | ||||||
|  | 
 | ||||||
| import "time" | import "time" | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| @ -11,11 +13,11 @@ func main() { | |||||||
| 	} | 	} | ||||||
| 	defer ui.Close() | 	defer ui.Close() | ||||||
| 
 | 
 | ||||||
| 	p := ui.NewP(":PRESS q TO QUIT DEMO\nThis is an example of termui package rendering.") | 	p := ui.NewP(":PRESS q TO QUIT DEMO") | ||||||
| 	p.Height = 4 | 	p.Height = 3 | ||||||
| 	p.Width = 59 | 	p.Width = 50 | ||||||
| 	p.TextFgColor = ui.ColorWhite | 	p.TextFgColor = ui.ColorWhite | ||||||
| 	p.Border.Label = "Text" | 	p.Border.Label = "Text Box" | ||||||
| 	p.Border.FgColor = ui.ColorCyan | 	p.Border.FgColor = ui.ColorCyan | ||||||
| 
 | 
 | ||||||
| 	strs := []string{"[0] gizak/termui", "[1] editbox.go", "[2] iterrupt.go", "[3] keyboard.go", "[4] output.go", "[5] random_out.go", "[6] dashboard.go", "[7] nsf/termbox-go"} | 	strs := []string{"[0] gizak/termui", "[1] editbox.go", "[2] iterrupt.go", "[3] keyboard.go", "[4] output.go", "[5] random_out.go", "[6] dashboard.go", "[7] nsf/termbox-go"} | ||||||
| @ -29,7 +31,7 @@ func main() { | |||||||
| 
 | 
 | ||||||
| 	g := ui.NewGauge() | 	g := ui.NewGauge() | ||||||
| 	g.Percent = 50 | 	g.Percent = 50 | ||||||
| 	g.Width = 52 | 	g.Width = 50 | ||||||
| 	g.Height = 3 | 	g.Height = 3 | ||||||
| 	g.Y = 11 | 	g.Y = 11 | ||||||
| 	g.Border.Label = "Gauge" | 	g.Border.Label = "Gauge" | ||||||
| @ -53,16 +55,84 @@ func main() { | |||||||
| 	spark1.LineColor = ui.ColorRed | 	spark1.LineColor = ui.ColorRed | ||||||
| 
 | 
 | ||||||
| 	sp := ui.NewSparklines(spark, spark1) | 	sp := ui.NewSparklines(spark, spark1) | ||||||
| 	sp.Width = 20 | 	sp.Width = 25 | ||||||
| 	sp.Height = 6 | 	sp.Height = 7 | ||||||
| 	sp.Border.Label = "Sparkline" | 	sp.Border.Label = "Sparkline" | ||||||
| 	sp.Y = 14 | 	sp.Y = 4 | ||||||
|  | 	sp.X = 25 | ||||||
|  | 
 | ||||||
|  | 	lc := ui.NewLineChart() | ||||||
|  | 	sinps := (func() []float64 { | ||||||
|  | 		n := 100 | ||||||
|  | 		ps := make([]float64, n) | ||||||
|  | 		for i := range ps { | ||||||
|  | 			ps[i] = 1 + math.Sin(float64(i)/4) | ||||||
|  | 		} | ||||||
|  | 		return ps | ||||||
|  | 	})() | ||||||
|  | 
 | ||||||
|  | 	lc.Border.Label = "Line Chart" | ||||||
|  | 	lc.Data = sinps | ||||||
|  | 	lc.Width = 50 | ||||||
|  | 	lc.Height = 11 | ||||||
|  | 	lc.X = 0 | ||||||
|  | 	lc.Y = 14 | ||||||
|  | 	lc.AxesColor = ui.ColorWhite | ||||||
|  | 	lc.LineColor = ui.ColorRed | ui.AttrBold | ||||||
|  | 	lc.Mode = "dot" | ||||||
|  | 
 | ||||||
|  | 	bc := ui.NewBarChart() | ||||||
|  | 	bcdata := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6} | ||||||
|  | 	bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"} | ||||||
|  | 	bc.Border.Label = "Bar Chart" | ||||||
|  | 	bc.Width = 26 | ||||||
|  | 	bc.Height = 10 | ||||||
|  | 	bc.X = 51 | ||||||
|  | 	bc.Y = 0 | ||||||
|  | 	bc.DataLabels = bclabels | ||||||
|  | 	bc.BarColor = ui.ColorGreen | ||||||
|  | 	bc.NumColor = ui.ColorBlack | ||||||
|  | 
 | ||||||
|  | 	lc1 := ui.NewLineChart() | ||||||
|  | 	lc1.Border.Label = "Line Chart" | ||||||
|  | 	rndwalk := (func() []float64 { | ||||||
|  | 		n := 100 | ||||||
|  | 		d := make([]float64, n) | ||||||
|  | 		for i := 1; i < n; i++ { | ||||||
|  | 			if i < 20 { | ||||||
|  | 				d[i] = d[i-1] + 0.01 | ||||||
|  | 			} | ||||||
|  | 			if i > 20 { | ||||||
|  | 				d[i] = d[i-1] - 0.05 | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return d | ||||||
|  | 	})() | ||||||
|  | 	lc1.Data = rndwalk | ||||||
|  | 	lc1.Width = 26 | ||||||
|  | 	lc1.Height = 11 | ||||||
|  | 	lc1.X = 51 | ||||||
|  | 	lc1.Y = 14 | ||||||
|  | 	lc1.AxesColor = ui.ColorWhite | ||||||
|  | 	lc1.LineColor = ui.ColorYellow | ui.AttrBold | ||||||
|  | 
 | ||||||
|  | 	p1 := ui.NewP("Hey!\nI am a borderless block!") | ||||||
|  | 	p1.HasBorder = false | ||||||
|  | 	p1.Width = 26 | ||||||
|  | 	p1.Height = 2 | ||||||
|  | 	p1.TextFgColor = ui.ColorMagenta | ||||||
|  | 	p1.X = 52 | ||||||
|  | 	p1.Y = 11 | ||||||
| 
 | 
 | ||||||
| 	draw := func(t int) { | 	draw := func(t int) { | ||||||
| 		g.Percent = t % 101 | 		g.Percent = t % 101 | ||||||
| 		list.Items = strs[t%9:] | 		list.Items = strs[t%9:] | ||||||
| 		sp.Lines[0].Data = spdata[t%10:] | 		sp.Lines[0].Data = spdata[t%10:] | ||||||
| 		ui.Render(p, list, g, sp) | 		sp.Lines[1].Data = spdata[t/2%10:] | ||||||
|  | 		lc.Data = sinps[t/2:] | ||||||
|  | 		lc1.Data = rndwalk[t:] | ||||||
|  | 		bc.Data = bcdata[t/2%10:] | ||||||
|  | 		ui.Render(p, list, g, sp, lc, bc, lc1, p1) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	evt := make(chan tm.Event) | 	evt := make(chan tm.Event) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user