gizak / termui

Golang terminal dashboard
MIT License
13.11k stars 786 forks source link

How can I dynamically add new bars to mbarchart over time? #176

Closed deinspanjer closed 5 years ago

deinspanjer commented 6 years ago

This is killing me because I'm so close. The examples for mbarchart are all static. The example in the source code header doesn't work at all, but the one in the _example dir works, it is just a bit confusing since it has the same number of bars and bar colors.

I'm trying to add new elements to mb.Data[n] where n is the color group, but what I get is always just n bars instead.

Any chance you could provide a simple code snippit that just adds a new random value per second so I can figure out what I'm doing wrong?

raff commented 5 years ago

What you can do is to keep your data in your own list, and whenever you add a new value, assign the slice to the Data[x] and refresh.

At the beginning you may want to assign a slice that is at least as big as the number of bars in the widget.

If you want to show the bars scrolling, you can just point to the tail of your slice. I do something like this:

case <-ticker.C:
                    if curr > bars {
                            p := curr - bars
                            sbc.Data[0] = data[p:]
                    }

In this case "curr" is len(data) and bars is the number of visible bars in the widget (sbc.Width / sbc.BarWidth)

cjbassi commented 5 years ago

Hi, I slightly modified the stacked_barchart example (mbarchart has been renamed to stacked_barchart) to demonstrate adding bars over time:

package main

import (
    "log"
    "time"

    ui "github.com/gizak/termui"
    "github.com/gizak/termui/widgets"
)

func main() {
    if err := ui.Init(); err != nil {
        log.Fatalf("failed to initialize termui: %v", err)
    }
    defer ui.Close()

    sbc := widgets.NewStackedBarChart()
    sbc.Title = "Student's Marks: X-Axis=Name, Y-Axis=Grade% (Math, English, Science, Computer Science)"
    sbc.Labels = []string{"Ken", "Rob", "Dennis", "Linus"}

    sbc.Data = make([][]float64, 4)
    sbc.Data[0] = []float64{90, 85, 90, 80}
    sbc.Data[1] = []float64{70, 85, 75, 60}
    sbc.Data[2] = []float64{75, 60, 80, 85}
    sbc.Data[3] = []float64{100, 100, 100, 100}
    sbc.SetRect(5, 5, 100, 30)
    sbc.BarWidth = 5

    ui.Render(sbc)

    uiEvents := ui.PollEvents()
    ticker := time.NewTicker(time.Second).C
    for {
        select {
        case e := <-uiEvents:
            switch e.ID {
            case "q", "<C-c>":
                return
            }
        case <-ticker:
            sbc.Data = append(sbc.Data, []float64{100})
            ui.Render(sbc)
        }
    }
}

This adds a new bar every second. The only changes are the extra import and the lines past ticker := time.NewTicker(time.Second).C. You could also append data to an individual bar to change those too.

Also note that termui has undergone a lot of changes recently, so some of this may look different. Hope this helps!