summaryrefslogtreecommitdiff
path: root/BBB_GOFILES/zz_histogram.go
diff options
context:
space:
mode:
Diffstat (limited to 'BBB_GOFILES/zz_histogram.go')
-rw-r--r--BBB_GOFILES/zz_histogram.go253
1 files changed, 253 insertions, 0 deletions
diff --git a/BBB_GOFILES/zz_histogram.go b/BBB_GOFILES/zz_histogram.go
new file mode 100644
index 0000000..fae5aae
--- /dev/null
+++ b/BBB_GOFILES/zz_histogram.go
@@ -0,0 +1,253 @@
+// 12 august 2018
+
+// +build OMIT
+
+package main
+
+import (
+ "math/rand"
+ "time"
+
+ "github.com/andlabs/ui"
+)
+
+var (
+ histogram *ui.Area
+ datapoints [10]*ui.Spinbox
+ colorButton *ui.ColorButton
+
+ currentPoint = -1
+)
+
+// some metrics
+const (
+ xoffLeft = 20 // histogram margins
+ yoffTop = 20
+ xoffRight = 20
+ yoffBottom = 20
+ pointRadius = 5
+)
+
+// helper to quickly set a brush color
+func mkSolidBrush(color uint32, alpha float64) *ui.Brush {
+ brush := new(ui.Brush)
+ brush.Type = ui.BrushTypeSolid
+ component := uint8((color >> 16) & 0xFF)
+ brush.R = float64(component) / 255
+ component = uint8((color >> 8) & 0xFF)
+ brush.G = float64(component) / 255
+ component = uint8(color & 0xFF)
+ brush.B = float64(component) / 255
+ brush.A = alpha
+ return brush
+}
+
+// and some colors
+// names and values from https://msdn.microsoft.com/en-us/library/windows/desktop/dd370907%28v=vs.85%29.aspx
+const (
+ colorWhite = 0xFFFFFF
+ colorBlack = 0x000000
+ colorDodgerBlue = 0x1E90FF
+)
+
+func pointLocations(width, height float64) (xs, ys [10]float64) {
+ xincr := width / 9 // 10 - 1 to make the last point be at the end
+ yincr := height / 100
+ for i := 0; i < 10; i++ {
+ // get the value of the point
+ n := datapoints[i].Value()
+ // because y=0 is the top but n=0 is the bottom, we need to flip
+ n = 100 - n
+ xs[i] = xincr * float64(i)
+ ys[i] = yincr * float64(n)
+ }
+ return xs, ys
+}
+
+func constructGraph(width, height float64, extend bool) *ui.Path {
+ xs, ys := pointLocations(width, height)
+ path := ui.NewPath(ui.Winding)
+
+ path.NewFigure(xs[0], ys[0])
+ for i := 1; i < 10; i++ {
+ path.LineTo(xs[i], ys[i])
+ }
+
+ if extend {
+ path.LineTo(width, height)
+ path.LineTo(0, height)
+ path.CloseFigure()
+ }
+
+ path.End()
+ return path
+}
+
+func graphSize(clientWidth, clientHeight float64) (graphWidth, graphHeight float64) {
+ return clientWidth - xoffLeft - xoffRight,
+ clientHeight - yoffTop - yoffBottom
+}
+
+type areaHandler struct{}
+
+func (areaHandler) Draw(a *ui.Area, p *ui.AreaDrawParams) {
+ // fill the area with white
+ brush := mkSolidBrush(colorWhite, 1.0)
+ path := ui.NewPath(ui.Winding)
+ path.AddRectangle(0, 0, p.AreaWidth, p.AreaHeight)
+ path.End()
+ p.Context.Fill(path, brush)
+ path.Free()
+
+ graphWidth, graphHeight := graphSize(p.AreaWidth, p.AreaHeight)
+
+ sp := &ui.StrokeParams{
+ Cap: ui.FlatCap,
+ Join: ui.MiterJoin,
+ Thickness: 2,
+ MiterLimit: ui.DefaultMiterLimit,
+ }
+
+ // draw the axes
+ brush = mkSolidBrush(colorBlack, 1.0)
+ path = ui.NewPath(ui.Winding)
+ path.NewFigure(xoffLeft, yoffTop)
+ path.LineTo(xoffLeft, yoffTop + graphHeight)
+ path.LineTo(xoffLeft + graphWidth, yoffTop + graphHeight)
+ path.End()
+ p.Context.Stroke(path, brush, sp)
+ path.Free()
+
+ // now transform the coordinate space so (0, 0) is the top-left corner of the graph
+ m := ui.NewMatrix()
+ m.Translate(xoffLeft, yoffTop)
+ p.Context.Transform(m)
+
+ // now get the color for the graph itself and set up the brush
+ graphR, graphG, graphB, graphA := colorButton.Color()
+ brush.Type = ui.BrushTypeSolid
+ brush.R = graphR
+ brush.G = graphG
+ brush.B = graphB
+ // we set brush.A below to different values for the fill and stroke
+
+ // now create the fill for the graph below the graph line
+ path = constructGraph(graphWidth, graphHeight, true)
+ brush.A = graphA / 2
+ p.Context.Fill(path, brush)
+ path.Free()
+
+ // now draw the histogram line
+ path = constructGraph(graphWidth, graphHeight, false)
+ brush.A = graphA
+ p.Context.Stroke(path, brush, sp)
+ path.Free()
+
+ // now draw the point being hovered over
+ if currentPoint != -1 {
+ xs, ys := pointLocations(graphWidth, graphHeight)
+ path = ui.NewPath(ui.Winding)
+ path.NewFigureWithArc(
+ xs[currentPoint], ys[currentPoint],
+ pointRadius,
+ 0, 6.23, // TODO pi
+ false)
+ path.End()
+ // use the same brush as for the histogram lines
+ p.Context.Fill(path, brush)
+ path.Free()
+ }
+}
+
+func inPoint(x, y float64, xtest, ytest float64) bool {
+ // TODO switch to using a matrix
+ x -= xoffLeft
+ y -= yoffTop
+ return (x >= xtest - pointRadius) &&
+ (x <= xtest + pointRadius) &&
+ (y >= ytest - pointRadius) &&
+ (y <= ytest + pointRadius)
+}
+
+func (areaHandler) MouseEvent(a *ui.Area, me *ui.AreaMouseEvent) {
+ graphWidth, graphHeight := graphSize(me.AreaWidth, me.AreaHeight)
+ xs, ys := pointLocations(graphWidth, graphHeight)
+
+ currentPoint = -1
+ for i := 0; i < 10; i++ {
+ if inPoint(me.X, me.Y, xs[i], ys[i]) {
+ currentPoint = i
+ break
+ }
+ }
+
+ // TODO only redraw the relevant area
+ histogram.QueueRedrawAll()
+}
+
+func (areaHandler) MouseCrossed(a *ui.Area, left bool) {
+ // do nothing
+}
+
+func (areaHandler) DragBroken(a *ui.Area) {
+ // do nothing
+}
+
+func (areaHandler) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) {
+ // reject all keys
+ return false
+}
+
+func setupUI() {
+ mainwin := ui.NewWindow("libui Histogram Example", 640, 480, true)
+ mainwin.SetMargined(true)
+ mainwin.OnClosing(func(*ui.Window) bool {
+ mainwin.Destroy()
+ ui.Quit()
+ return false
+ })
+ ui.OnShouldQuit(func() bool {
+ mainwin.Destroy()
+ return true
+ })
+
+ hbox := ui.NewHorizontalBox()
+ hbox.SetPadded(true)
+ mainwin.SetChild(hbox)
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(true)
+ hbox.Append(vbox, false)
+
+ histogram = ui.NewArea(areaHandler{})
+
+ rand.Seed(time.Now().Unix())
+ for i := 0; i < 10; i++ {
+ datapoints[i] = ui.NewSpinbox(0, 100)
+ datapoints[i].SetValue(rand.Intn(101))
+ datapoints[i].OnChanged(func(*ui.Spinbox) {
+ histogram.QueueRedrawAll()
+ })
+ vbox.Append(datapoints[i], false)
+ }
+
+ colorButton = ui.NewColorButton()
+ // TODO inline these
+ brush := mkSolidBrush(colorDodgerBlue, 1.0)
+ colorButton.SetColor(brush.R,
+ brush.G,
+ brush.B,
+ brush.A)
+ colorButton.OnChanged(func(*ui.ColorButton) {
+ histogram.QueueRedrawAll()
+ })
+ vbox.Append(colorButton, false)
+
+ hbox.Append(histogram, true)
+
+ mainwin.Show()
+}
+
+func main() {
+ ui.Main(setupUI)
+}