Class: Potty::Widgets::RadioGroup

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

Overview

N mutually exclusive options, one row each. Up/down move the cursor; Space/Enter selects the option under the cursor. Renders “(u25CF) label” for the chosen option and “(u25CB) label” for the rest.

Note the two distinct positions: the cursor (highlight, moved by arrows) and the selection (the committed value). They diverge while the user is navigating and reconverge on select.

Instance Attribute Summary collapse

Attributes inherited from Base

#app, #focused, #parent, #rect

Instance Method Summary collapse

Methods inherited from Base

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

Methods included from Events

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

Constructor Details

#initialize(app, options: [], selected: nil, on_change: nil) ⇒ RadioGroup

Returns a new instance of RadioGroup.



19
20
21
22
23
24
25
# File 'lib/potty/widgets/radio_group.rb', line 19

def initialize(app, options: [], selected: nil, on_change: nil)
  super(app)
  @options = normalize(options)
  @on_change = on_change
  @selected = selected.nil? ? @options.first&.fetch(:value) : selected
  @cursor = index_of(@selected) || 0
end

Instance Attribute Details

#on_changeObject

Returns the value of attribute on_change.



17
18
19
# File 'lib/potty/widgets/radio_group.rb', line 17

def on_change
  @on_change
end

Instance Method Details

#can_focus?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/potty/widgets/radio_group.rb', line 27

def can_focus?
  true
end

#handle_key(ch) ⇒ Object



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

def handle_key(ch)
  case ch
  when Keys::UP
    move(-1)
  when Keys::DOWN
    move(1)
  when Keys::SPACE, *Keys::ENTERS
    choose(@cursor)
  else
    return false
  end
  true
end

#optionsObject



31
32
33
# File 'lib/potty/widgets/radio_group.rb', line 31

def options
  @options
end

#options=(opts) ⇒ Object



35
36
37
38
# File 'lib/potty/widgets/radio_group.rb', line 35

def options=(opts)
  @options = normalize(opts)
  @cursor = @cursor.clamp(0, [@options.size - 1, 0].max)
end

#preferred_height(_width) ⇒ Object



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

def preferred_height(_width)
  @options.size
end

#render(window) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/potty/widgets/radio_group.rb', line 72

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

  @options.each_with_index do |opt, i|
    break if i >= @rect.height

    marker = opt[:value] == @selected ? "(\u25CF)" : "(\u25CB)"
    on_cursor = @focused && i == @cursor
    attr = on_cursor ? theme.attr(:selected, bold: true) : theme[:normal]
    text = "#{marker} #{opt[:label]}"[0, @rect.width]

    window.setpos(@rect.y + i, @rect.x)
    window.attron(attr) { window.addstr(text) }
  end
end

#selectedObject



40
41
42
# File 'lib/potty/widgets/radio_group.rb', line 40

def selected
  @selected
end

#selected=(value) ⇒ Object



44
45
46
47
48
49
50
51
52
# File 'lib/potty/widgets/radio_group.rb', line 44

def selected=(value)
  idx = index_of(value)
  return unless idx

  @selected = value
  @cursor = idx
  @on_change&.call(@selected)
  emit(:change, @selected)
end