Class: Potty::Widgets::Spinner

Inherits:
Base
  • Object
show all
Defined in:
lib/potty/widgets/spinner.rb

Overview

Single-line activity indicator: an animated braille spinner, a live mutable label, and a trailing state. While active the glyph is the spinner; complete!(result) freezes it to a fixed glyph and flips the color. Passive (no focus/input). Tick-driven via an internal Animator.

s = Spinner.new(app, label: "daemon - running")
s.label = "daemon - surrendering 16 children"   # live update
s.complete!(:success)   # glyph -> checkmark, color -> :success

Constant Summary collapse

STATE_GLYPHS =
{ success: "\u2713", failure: "\u2717", cancelled: "\u23F9" }.freeze
STATE_COLORS =
{ success: :success, failure: :error, cancelled: :dim }.freeze

Instance Attribute Summary collapse

Attributes inherited from Base

#app, #focused, #parent, #rect

Instance Method Summary collapse

Methods inherited from Base

#activate, #blur, #can_focus?, #deactivate, #focus, #handle_escape, #handle_key, #hide, #layout, #on_blur, #on_focus, #on_layout, #show, #theme, #visible=, #visible?

Methods included from Events

#emit, #listeners?, #off, #on

Constructor Details

#initialize(app, label: '', color: :info, prefix: ' ') ⇒ Spinner

Returns a new instance of Spinner.



24
25
26
27
28
29
30
31
32
# File 'lib/potty/widgets/spinner.rb', line 24

def initialize(app, label: '', color: :info, prefix: '  ')
  super(app)
  @label = label
  @color = color
  @prefix = prefix
  @state = :active
  @animator = Animator.new(app)
  @animator << Sprites::Sample.spinner
end

Instance Attribute Details

#colorObject (readonly)

Returns the value of attribute color.



22
23
24
# File 'lib/potty/widgets/spinner.rb', line 22

def color
  @color
end

#labelObject

Returns the value of attribute label.



21
22
23
# File 'lib/potty/widgets/spinner.rb', line 21

def label
  @label
end

#prefixObject

Returns the value of attribute prefix.



21
22
23
# File 'lib/potty/widgets/spinner.rb', line 21

def prefix
  @prefix
end

#stateObject (readonly)

Returns the value of attribute state.



22
23
24
# File 'lib/potty/widgets/spinner.rb', line 22

def state
  @state
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/potty/widgets/spinner.rb', line 34

def active?
  @state == :active
end

#complete!(result = :success) ⇒ Object

Freeze the spinner to a terminal state. Idempotent: only the first call takes effect, so repeated lifecycle events are harmless.



40
41
42
43
44
45
46
47
48
# File 'lib/potty/widgets/spinner.rb', line 40

def complete!(result = :success)
  return self unless active?

  @state = result
  @color = STATE_COLORS.fetch(result, @color)
  @animator.stop
  emit(:complete, result)
  self
end

#preferred_height(_width) ⇒ Object



50
51
52
# File 'lib/potty/widgets/spinner.rb', line 50

def preferred_height(_width)
  1
end

#render(window) ⇒ Object



58
59
60
61
62
63
64
65
66
67
# File 'lib/potty/widgets/spinner.rb', line 58

def render(window)
  return unless @visible && @rect

  glyph = active? ? current_frame : STATE_GLYPHS.fetch(@state, '?')
  text = truncate("#{@prefix}#{glyph} #{@label}", @rect.width)
  window.setpos(@rect.y, @rect.x)
  # theme.style (not theme[]) so we render in colour on either surface —
  # curses resolves the Style to a pair, inline to ANSI SGR.
  window.attron(theme.style(@color)) { window.addstr(text) }
end

#tick(now) ⇒ Object



54
55
56
# File 'lib/potty/widgets/spinner.rb', line 54

def tick(now)
  @animator.tick(now) if active?
end