Class: Plushie::Selection

Inherits:
Object
  • Object
show all
Defined in:
lib/plushie/selection.rb,
sig/plushie/selection.rbs

Overview

Selection state for lists and tables. Pure data structure supporting single, multi, and range selection modes.

Modes

  • :single: at most one item selected at a time.
  • :multi: multiple items selectable; extend: true adds to the set.
  • :range: like multi, but range_select selects a contiguous slice of the order list between the anchor and the target.

Examples:

sel = Plushie::Selection.new(mode: :multi, order: ["a", "b", "c", "d"])
sel = Plushie::Selection.select(sel, "b")
sel = Plushie::Selection.select(sel, "d", extend: true)
Plushie::Selection.selected(sel) #=> Set["b", "d"]

Defined Under Namespace

Classes: State

Class Method Summary collapse

Class Method Details

.clear(sel) ⇒ State

Clears all selected items and resets the anchor.

Parameters:

Returns:



89
90
91
# File 'lib/plushie/selection.rb', line 89

def self.clear(sel)
  sel.with(selected: Set.new, anchor: nil)
end

.deselect(sel, id) ⇒ State

Removes id from the selection.

Parameters:

  • sel (State)
  • id (Object)

Returns:



81
82
83
# File 'lib/plushie/selection.rb', line 81

def self.deselect(sel, id)
  sel.with(selected: sel.selected - Set[id])
end

.new(mode: :single, order: []) ⇒ State

Creates a new selection state.

Parameters:

  • mode (Symbol) (defaults to: :single)

    selection mode: :single (default), :multi, or :range

  • order (Array) (defaults to: [])

    ordered list of item IDs for range selection

  • mode: (Symbol) (defaults to: :single)
  • order: (Array[untyped]) (defaults to: [])

Returns:



31
32
33
# File 'lib/plushie/selection.rb', line 31

def self.new(mode: :single, order: [])
  State.new(mode: mode, selected: Set.new, anchor: nil, order: order)
end

.range_select(sel, id) ⇒ State

Selects all items in order between the current anchor and id (inclusive). If there is no anchor, selects only id.

Requires order to have been set at creation time.

Parameters:

  • sel (State)
  • id (Object)

Returns:



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/plushie/selection.rb', line 101

def self.range_select(sel, id)
  if sel.anchor.nil?
    return sel.with(selected: Set[id], anchor: id)
  end

  anchor_idx = sel.order.index(sel.anchor)
  id_idx = sel.order.index(id)

  if anchor_idx.nil? || id_idx.nil?
    return sel.with(selected: Set[id], anchor: id)
  end

  lo, hi = [anchor_idx, id_idx].sort
  range_ids = sel.order[lo..hi] #: Array[untyped]
  sel.with(selected: Set.new(range_ids))
end

.select(sel, id, extend: false) ⇒ State

Selects id. In :single mode, replaces the selection. In :multi and :range modes, replaces unless extend: true is passed, in which case id is added to the existing selection.

Sets the anchor to id for subsequent range selections.

Parameters:

  • sel (State)
  • id (Object)
  • extend (Boolean) (defaults to: false)

    add to existing selection (multi/range only)

  • extend: (Boolean) (defaults to: false)

Returns:



45
46
47
48
49
50
51
52
53
# File 'lib/plushie/selection.rb', line 45

def self.select(sel, id, extend: false)
  if sel.mode == :single
    sel.with(selected: Set[id], anchor: id)
  elsif extend
    sel.with(selected: sel.selected | Set[id], anchor: id)
  else
    sel.with(selected: Set[id], anchor: id)
  end
end

.selected(sel) ⇒ Set

Returns the Set of currently selected item IDs.

Parameters:

Returns:

  • (Set)


122
123
124
# File 'lib/plushie/selection.rb', line 122

def self.selected(sel)
  sel.selected
end

.selected?(sel, id) ⇒ Boolean

Returns true if id is currently selected.

Parameters:

  • sel (State)
  • id (Object)

Returns:

  • (Boolean)


131
132
133
# File 'lib/plushie/selection.rb', line 131

def self.selected?(sel, id)
  sel.selected.include?(id)
end

.toggle(sel, id) ⇒ State

Toggles id in the selection. If already selected, removes it; otherwise adds it. In :single mode, toggling a selected item clears the selection entirely.

Parameters:

  • sel (State)
  • id (Object)

Returns:



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/plushie/selection.rb', line 62

def self.toggle(sel, id)
  if sel.mode == :single
    if sel.selected.include?(id)
      sel.with(selected: Set.new, anchor: nil)
    else
      sel.with(selected: Set[id], anchor: id)
    end
  elsif sel.selected.include?(id)
    sel.with(selected: sel.selected - Set[id])
  else
    sel.with(selected: sel.selected | Set[id], anchor: id)
  end
end