Module: RubyCurses::NewListSelectable

Included in:
List, TabularWidget
Defined in:
lib/rbcurse/core/include/listselectable.rb

selection related collapse

Instance Method Details

#add_selection_interval(ix0, ix1) ⇒ Object Also known as: add_row_selection_interval

add the following range to selected items, unless already present should only be used if multiple selection interval



121
122
123
124
125
126
127
128
129
130
# File 'lib/rbcurse/core/include/listselectable.rb', line 121

def add_selection_interval ix0, ix1
  return if @selection_mode != :multiple
  @widget_scrolled = true # FIXME we need a better name
  @anchor_selection_index = ix0
  @lead_selection_index = ix1
  ix0.upto(ix1) {|i| @selected_indices  << i unless @selected_indices.include? i }
  lse = ListSelectionEvent.new(ix0, ix1, self, :INSERT)
  fire_handler :LIST_SELECTION_EVENT, lse
  #$log.debug " DLSM firing LIST_SELECTION EVENT #{lse}"
end

#add_to_selection(crow = @current_index-@_header_adjustment) ⇒ Object

Only for multiple mode. add an item to selection, if selection mode is multiple if item already selected, it is deselected, else selected typically bound to Ctrl-Space

Examples:

bind_key(0) { add_to_selection }


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rbcurse/core/include/listselectable.rb', line 57

def add_to_selection crow=@current_index-@_header_adjustment
  @last_clicked ||= crow
  min = [@last_clicked, crow].min
  max = [@last_clicked, crow].max
  case @selection_mode 
  when :multiple
    @widget_scrolled = true # FIXME we need a better name
    if @selected_indices.include? crow
      # delete from last_clicked until this one in any direction
      min.upto(max){ |i| @selected_indices.delete i }
      lse = ListSelectionEvent.new(min, max, self, :DELETE)
      fire_handler :LIST_SELECTION_EVENT, lse
    else
      # add to selection from last_clicked until this one in any direction
      min.upto(max){ |i| @selected_indices << i unless @selected_indices.include?(i) }
      lse = ListSelectionEvent.new(min, max, self, :INSERT)
      fire_handler :LIST_SELECTION_EVENT, lse
    end
  else
  end
  @repaint_required = true
  self
end

#ask_select(prompt = "Enter selection pattern: ") ⇒ Object

please override this, this is just very basic and default Please implement get_matching_indices(String).



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/rbcurse/core/include/listselectable.rb', line 190

def ask_select prompt="Enter selection pattern: "
  ret = ask(prompt, String) {|q| yield q if block_given? }
  return if ret.nil? || ret ==  ""
  indices = get_matching_indices ret
  return if indices.nil? || indices.empty?
  indices.each { |e|
    # will not work if single select !! FIXME
    add_row_selection_interval e,e
  }
  @repaint_required = true
end

#clear_selectionObject

clears selected indices, typically called when multiple select Key binding is application specific



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rbcurse/core/include/listselectable.rb', line 82

def clear_selection
  return if @selected_indices.nil? || @selected_indices.empty?
  @selected_indices = []
  @selected_index = nil
  @old_selected_index = nil
  # Not sure what event type I should give, DELETE or a new one, user should
  #  understand that selection has been cleared, and ignore first two params
  lse = ListSelectionEvent.new(0, @list.size, self, :CLEAR)
  fire_handler :LIST_SELECTION_EVENT, lse
  @repaint_required = true
  @widget_scrolled = true # FIXME we need a better name
end

#get_matching_indices(pattern) ⇒ Object



201
202
203
204
# File 'lib/rbcurse/core/include/listselectable.rb', line 201

def get_matching_indices pattern
  alert "please implement this method get_matching_indices(pattern)->[] in your class  "
  return []
end

#goto_next_selectionObject

FIXME add adjustment and test



104
105
106
107
108
109
110
# File 'lib/rbcurse/core/include/listselectable.rb', line 104

def goto_next_selection
  return if selected_rows().length == 0 
  row = selected_rows().sort.find { |i| i > @current_index }
  row ||= @current_index
  @current_index = row
  @repaint_required = true # fire list_select XXX
end

#goto_prev_selectionObject

FIXME add adjustment and test



112
113
114
115
116
117
118
# File 'lib/rbcurse/core/include/listselectable.rb', line 112

def goto_prev_selection
  return if selected_rows().length == 0 
  row = selected_rows().sort{|a,b| b <=> a}.find { |i| i < @current_index }
  row ||= @current_index
  @current_index = row
  @repaint_required = true # fire list_select XXX
end

#insert_index_interval(ix0, len) ⇒ Object

convenience method to select next len rows



141
142
143
144
145
# File 'lib/rbcurse/core/include/listselectable.rb', line 141

def insert_index_interval ix0, len
  @anchor_selection_index = ix0
  @lead_selection_index = ix0+len
  add_selection_interval @anchor_selection_index, @lead_selection_index
end

#invert_row_selection(row = @current_index-@_header_adjustment) ⇒ Object



159
160
161
162
163
164
165
166
# File 'lib/rbcurse/core/include/listselectable.rb', line 159

def invert_row_selection row=@current_index-@_header_adjustment
  @repaint_required = true
  if is_selected? row
    remove_row_selection_interval(row, row)
  else
    add_row_selection_interval(row, row) 
  end
end

#invert_selection(start_row = 0) ⇒ Object

+@_header_adjustment



155
156
157
# File 'lib/rbcurse/core/include/listselectable.rb', line 155

def invert_selection start_row=0 #+@_header_adjustment
  start_row.upto(row_count()){|i| invert_row_selection i }
end

#is_row_selected(crow = @current_index-@_header_adjustment) ⇒ Object Also known as: is_selected?



94
95
96
97
98
99
100
101
# File 'lib/rbcurse/core/include/listselectable.rb', line 94

def is_row_selected crow=@current_index-@_header_adjustment
  case @selection_mode 
  when :multiple
    @selected_indices.include? crow
  else
    crow == @selected_index
  end
end

#list_bindingsObject

Applications may call this or just copy and modify



206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/rbcurse/core/include/listselectable.rb', line 206

def list_bindings
  # what about users wanting 32 and ENTER to also go to next row automatically
  # should make that optional, TODO
  bind_key($row_selector || 32, 'toggle selection') { toggle_row_selection }
  bind_key(0, 'range select') { add_to_selection }
  bind_key(?+, :ask_select) # --> calls select_values
  bind_key(?-, :ask_unselect) # please implement FIXME TODO
  bind_key(?a, :select_all)
  bind_key(?*, :invert_selection)
  bind_key(?u, :clear_selection)
  @_header_adjustment ||= 0 #  incase caller does not use
  @_events << :LIST_SELECTION_EVENT unless @_events.include? :LIST_SELECTION_EVENT
end

#list_init_varsObject



219
220
221
222
223
224
225
226
227
228
229
# File 'lib/rbcurse/core/include/listselectable.rb', line 219

def list_init_vars
  @selected_indices = []
  @selected_index = nil
  @old_selected_index = nil
  #@row_selected_symbol = ''
  if @show_selector
    @row_selected_symbol ||= '*'
    @row_unselected_symbol ||= ' '
    @left_margin ||= @row_selected_symbol.length
  end
end

#paint_selector(crow, r, c, acolor, attrib) ⇒ Object

paint the selector. Called from repaint, prior to printing data row remember to set left_margin at top of repaint method as:

@left_margin ||= @row_selected_symbol.length


233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/rbcurse/core/include/listselectable.rb', line 233

def paint_selector crow, r, c, acolor, attrib
  selected = is_row_selected crow
  selection_symbol = ''
  if @show_selector
    if selected
      selection_symbol = @row_selected_symbol
    else
      selection_symbol =  @row_unselected_symbol
    end
    @graphic.printstring r, c, selection_symbol, acolor,attrib
  end
end

#remove_selection_interval(ix0, ix1) ⇒ Object Also known as: remove_row_selection_interval



132
133
134
135
136
137
138
# File 'lib/rbcurse/core/include/listselectable.rb', line 132

def remove_selection_interval ix0, ix1
  @anchor_selection_index = ix0
  @lead_selection_index = ix1
  @selected_indices.delete_if {|x| x >= ix0 and x <= ix1}
  lse = ListSelectionEvent.new(ix0, ix1, self, :DELETE)
  fire_handler :LIST_SELECTION_EVENT, lse
end

#select_all(start_row = 0) ⇒ Object

select all rows, you may specify starting row. if header row, then 1 else should be 0. Actually we should have a way to determine this, and the default should be zero.



149
150
151
152
153
154
# File 'lib/rbcurse/core/include/listselectable.rb', line 149

def select_all start_row=0 #+@_header_adjustment
  @repaint_required = true
  # don't select header row - need to make sure this works for all cases. we may 
  # need a variable instead of hardoded value
  add_row_selection_interval start_row, row_count()
end

#select_values(values) ⇒ Object

selects all rows with the values given, leaving existing selections intact. Typically used after accepting search criteria, and getting a list of values to select (such as file names). Will not work with tables (array or array)



170
171
172
173
174
175
176
# File 'lib/rbcurse/core/include/listselectable.rb', line 170

def select_values values
  return unless values
  values.each do |val|
    row = @list.index val
    add_row_selection_interval row, row unless row.nil?
  end
end

#selected_rowsObject



245
246
247
# File 'lib/rbcurse/core/include/listselectable.rb', line 245

def selected_rows
  @selected_indices
end

#toggle_row_selection(crow = @current_index-@_header_adjustment) ⇒ Object

change selection of current row on pressing space bar If mode is multiple, then other selections are cleared and this is added current_index is not account for header_adjustment if current row is selected in mulitple we should deselect ?? FIXME

Examples:

bind_key(32) { toggle_row_selection }


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rbcurse/core/include/listselectable.rb', line 21

def toggle_row_selection crow=@current_index-@_header_adjustment
  @last_clicked = crow
  @repaint_required = true
  case @selection_mode 
  when :multiple
    @widget_scrolled = true # FIXME we need a better name
    if @selected_indices.include? crow
      @selected_indices.delete crow
      lse = ListSelectionEvent.new(crow, crow, self, :DELETE)
      fire_handler :LIST_SELECTION_EVENT, lse
    else
      @selected_indices << crow
      lse = ListSelectionEvent.new(crow, crow, self, :INSERT)
      fire_handler :LIST_SELECTION_EVENT, lse
    end
  else
    if @selected_index == crow 
      @old_selected_index = @selected_index # 2011-10-15 so we can unhighlight
      @selected_index = nil
      lse = ListSelectionEvent.new(crow, crow, self, :DELETE)
      fire_handler :LIST_SELECTION_EVENT, lse
    else
      @old_selected_index = @selected_index # 2011-10-15 so we can unhighlight
      @selected_index = crow 
      lse = ListSelectionEvent.new(crow, crow, self, :INSERT)
      fire_handler :LIST_SELECTION_EVENT, lse
    end
  end
end

#unselect_values(values) ⇒ Object

unselects all rows with the values given, leaving all other rows intact You can map “-” to ask_select and call this from there.

bind_key(?+, :ask_select) # --> calls select_values
bind_key(?-, :ask_unselect)


181
182
183
184
185
186
187
# File 'lib/rbcurse/core/include/listselectable.rb', line 181

def unselect_values values
  return unless values
  values.each do |val|
    row = @list.index val
    remove_row_selection_interval row, row unless row.nil?
  end
end