Class: Potty::Widgets::Countdown

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

Overview

Passive display that counts down from N seconds and fires on_expire once when it reaches zero. Time-driven: it advances off the ‘now` passed to tick(now), so drive it via the Application tick loop (set Application#tick_interval).

The clock starts on the first tick (not at construction), so a Countdown built well before the loop spins up still gets its full N.

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, seconds:, on_expire: nil, format: nil) ⇒ Countdown

Returns a new instance of Countdown.



17
18
19
20
21
22
23
24
25
26
# File 'lib/potty/widgets/countdown.rb', line 17

def initialize(app, seconds:, on_expire: nil, format: nil)
  super(app)
  @seconds = seconds.to_f
  @on_expire = on_expire
  @format = format || ->(remaining) { "Auto-launching in #{remaining}s\u2026" }
  @started_at = nil
  @last_now = nil
  @running = true
  @expired = false
end

Instance Attribute Details

#on_expireObject

Returns the value of attribute on_expire.



15
16
17
# File 'lib/potty/widgets/countdown.rb', line 15

def on_expire
  @on_expire
end

Instance Method Details

#expired?Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/potty/widgets/countdown.rb', line 42

def expired?
  @expired
end

#preferred_height(_width) ⇒ Object



53
54
55
# File 'lib/potty/widgets/countdown.rb', line 53

def preferred_height(_width)
  1
end

#remainingObject

Whole seconds left (ceil), clamped at 0.



47
48
49
50
51
# File 'lib/potty/widgets/countdown.rb', line 47

def remaining
  return @seconds.ceil if @started_at.nil? || @last_now.nil?

  [@seconds - (@last_now - @started_at), 0].max.ceil
end

#render(window) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/potty/widgets/countdown.rb', line 72

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

  text = @format.call(remaining).to_s[0, @rect.width]
  window.setpos(@rect.y, @rect.x)
  window.attron(theme[:warning]) { window.addstr(text) }
end

#startObject

(Re)start the countdown from the top.



29
30
31
32
33
34
35
# File 'lib/potty/widgets/countdown.rb', line 29

def start
  @started_at = nil
  @last_now = nil
  @running = true
  @expired = false
  self
end

#stopObject



37
38
39
40
# File 'lib/potty/widgets/countdown.rb', line 37

def stop
  @running = false
  self
end

#tick(now) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/potty/widgets/countdown.rb', line 57

def tick(now)
  @last_now = now
  return unless @running

  @started_at ||= now
  return if @expired

  return unless now - @started_at >= @seconds

  @expired = true
  @running = false
  @on_expire&.call(self)
  emit(:expire, self)
end