File: asciigraph.go

package info (click to toggle)
golang-github-gcla-gowid 1.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,456 kB
  • sloc: makefile: 4
file content (119 lines) | stat: -rw-r--r-- 2,740 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2019-2022 Graham Clark. All rights reserved.  Use of this source
// code is governed by the MIT license that can be found in the LICENSE
// file.

// Package asciigraph provides a simple plotting widget.
package asciigraph

import (
	"strings"
	"unicode/utf8"

	"github.com/gcla/gowid"
	"github.com/gcla/gowid/gwutil"
	"github.com/gcla/gowid/widgets/fill"
	"github.com/guptarohit/asciigraph"
)

//======================================================================

type IAsciiGraph interface {
	GetData() []float64
	GetConf() []asciigraph.Option
}

type IWidget interface {
	gowid.IWidget
	IAsciiGraph
}

type Widget struct {
	Data []float64
	Conf []asciigraph.Option
	gowid.RejectUserInput
	gowid.NotSelectable
}

func New(series []float64, config []asciigraph.Option) *Widget {
	res := &Widget{}
	res.Data = series
	res.Conf = config
	var _ IWidget = res
	return res
}

func (w *Widget) String() string {
	return "asciigraph"
}

func (w *Widget) GetData() []float64 {
	return w.Data
}

func (w *Widget) SetData(data []float64, app gowid.IApp) {
	w.Data = data
}

func (w *Widget) GetConf() []asciigraph.Option {
	return w.Conf
}

func (w *Widget) SetConf(conf []asciigraph.Option, app gowid.IApp) {
	w.Conf = conf
}

func (w *Widget) RenderSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
	return RenderSize(w, size, focus, app)
}

func (w *Widget) Render(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
	return Render(w, size, focus, app)
}

//''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

// TODO: ILineWidget?
func RenderSize(w IWidget, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
	return gowid.CalculateRenderSizeFallback(w, size, focus, app)
}

func Render(w IAsciiGraph, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {

	grender := strings.Split(asciigraph.Plot(w.GetData(), w.GetConf()...), "\n")

	rows := len(grender)
	cols := 0
	if rows > 0 {
		cols = utf8.RuneCountInString(grender[0])
	}

	switch sz := size.(type) {
	case gowid.IRenderBox:
		cols = sz.BoxColumns()
		rows = sz.BoxRows()
	case gowid.IRenderFlowWith:
		panic(gowid.WidgetSizeError{Widget: w, Size: size})
	}

	blank := fill.NewEmpty()
	res := blank.Render(gowid.RenderBox{C: cols, R: rows}, gowid.NotSelected, app)

	for y := 0; y < gwutil.Min(len(grender), res.BoxRows()); y++ {
		x := 0
		for _, r := range grender[y] {
			if x >= res.BoxColumns() {
				break
			}
			res.SetCellAt(x, y, res.CellAt(x, y).WithRune(r))
			x++
		}
	}

	return res
}

//======================================================================
// Local Variables:
// mode: Go
// fill-column: 110
// End: