Class: RubyTUI::Widgets::Sparkline

Inherits:
Object
  • Object
show all
Includes:
RubyTUI::Widget
Defined in:
lib/rubytui/widgets/sparkline.rb

Overview

Sparkline renders a mini bar chart from an array of numeric data. Each data point maps to a single column using Unicode block characters.

Examples:

spark = RubyTUI::Widgets::Sparkline.new(data: [1, 4, 2, 8, 5], max: 10)
frame.render_widget(spark, area)

Constant Summary collapse

BARS =

Bar characters from empty to full (8 levels)

[" ", "\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"].freeze

Instance Method Summary collapse

Constructor Details

#initialize(data: [], style: Style::DEFAULT, bar_style: nil, max: nil, block: nil) ⇒ Sparkline

Returns a new instance of Sparkline.

Parameters:

  • data (Array<Numeric>) (defaults to: []) —

    values; the most recent values that fit the width are drawn, right-aligned (default: [])

  • style (Style) (defaults to: Style::DEFAULT) —

    style of the empty cells above the bars (default: Style::DEFAULT)

  • bar_style (Style, nil) (defaults to: nil) —

    bar style (default: green foreground)

  • max (Numeric, nil) (defaults to: nil) —

    value drawn at full height; larger values are clamped to full height (default: nil, the largest visible value, or 1 if that is 0)

  • block (Widgets::Block, nil) (defaults to: nil) —

    optional wrapping block



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/rubytui/widgets/sparkline.rb', line 24

def initialize(
  data: [],
  style: Style::DEFAULT,
  bar_style: nil,
  max: nil,
  block: nil
)
  @data = data
  @style = style
  @bar_style = bar_style || Style.new.fg(Color::GREEN)
  @max = max
  @block = block
end

Instance Method Details

#render(area, buf) ⇒ void

This method returns an undefined value.

Draw one column per value, bottom-up, with eighth-cell height precision.

Parameters:

  • area (Rect) —

    the rectangular area to render into

  • buf (Buffer) —

    the buffer to write cells into



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
# File 'lib/rubytui/widgets/sparkline.rb', line 43

def render(area, buf)
  return if area.empty?

  render_area = area
  if @block
    @block.render(area, buf)
    render_area = @block.inner(area)
  end

  return if render_area.empty? || @data.empty?

  width = render_area.width
  height = render_area.height

  # Use the most recent data points that fit
  visible_data = @data.last(width)
  max_val = @max || visible_data.max || 1
  max_val = 1 if max_val == 0

  visible_data.each_with_index do |val, i|
    x = render_area.x + (width - visible_data.length) + i
    next if x < render_area.x

    # Scale value to available height * 8 (for sub-character precision)
    scaled = ((val.to_f / max_val) * height * 8).round.clamp(0, height * 8)

    # Render from bottom to top
    (0...height).each do |row|
      y = render_area.bottom - 1 - row
      row_value = scaled - (row * 8)

      if row_value >= 8
        buf[x, y]&.set(BARS[8], @bar_style)
      elsif row_value > 0
        buf[x, y]&.set(BARS[row_value], @bar_style)
      else
        buf[x, y]&.set(" ", @style)
      end
    end
  end
end