Class: Canis::DefaultListSelectionModel
- Defined in:
- lib/canis/core/include/listselectionmodel.rb
Overview
Object that takes care of selection of rows. This may be replace with a custom object at time of instantiation of list Note that there are only two selection modes: single and multiple. Multiple refers to multiple intervals. There is also a multiple row selection mode, single interval, which only allows one range to be selected, much like a text object, i.e. any text editor.
I am copying this from listselectable. that was a module so was included and shared variables but now this is a class, and cannot access state as directly
Instance Method Summary collapse
-
#add_row_selection_interval(ix0, ix1) ⇒ Object
add the following range to selected items, unless already present should only be used if multiple selection interval.
-
#ask_select(prompt = "Enter selection pattern: ") ⇒ Object
Asks user to enter a string or pattern for selecting rows Selects rows based on pattern, leaving other selections as-is.
-
#ask_unselect(prompt = "Enter selection pattern: ") ⇒ Object
Asks user to enter a string or pattern for UNselecting rows UNSelects rows based on pattern, leaving other selections as-is.
-
#clear_selection ⇒ Object
clears selected indices, typically called when multiple select Key binding is application specific.
-
#get_matching_indices(pattern) ⇒ Object
returns a list of matching indices using a simple regex match on given pattern returns an empty list if no match.
-
#goto_next_selection ⇒ Object
after selecting, traverse selections forward.
-
#goto_prev_selection ⇒ Object
after selecting, traverse selections backward.
-
#initialize(component) ⇒ DefaultListSelectionModel
constructor
A new instance of DefaultListSelectionModel.
-
#insert_index_interval(ix0, len) ⇒ Object
convenience method to select next len rows.
-
#invert_row_selection(row = @obj.current_index) ⇒ Object
toggles selection for given row Typically called by invert_selection.
-
#invert_selection(start_row = 0) ⇒ Object
toggle selection of entire list Requires application specific key binding.
-
#is_row_selected?(crow) ⇒ Boolean
(also: #is_selected?)
returns
true
if given row has been selected Now that we use only the array, the multiple check is good enough. -
#list_bindings ⇒ Object
bindings related to selection.
- #list_init_vars ⇒ Object
-
#range_select(crow = @obj.current_index) ⇒ Object
Range select.
-
#remove_row_selection_interval(ix0, ix1) ⇒ Object
remove selected indices between given indices inclusive.
-
#select_all(start_row = 0) ⇒ Object
select all rows, you may specify starting row.
-
#select_values(values) ⇒ Object
selects all rows with the values given, leaving existing selections intact.
-
#selected_rows ⇒ Object
return the indices selected.
-
#selected_value ⇒ Object
returns first selection, meant for convenience of single select listboxes earlier called selected_item.
-
#selected_values ⇒ Object
return the values selected.
-
#toggle_row_selection(crow = @obj.current_index) ⇒ Object
change selection of current row on pressing space bar (or keybinding) If mode is multiple, then this row is added to previous selections.
-
#unselect_values(values) ⇒ Object
TODO is this even needed, scrap unselects all rows with the values given, leaving all other rows intact You can map “-” to ask_select and call this from there.
Constructor Details
#initialize(component) ⇒ DefaultListSelectionModel
Returns a new instance of DefaultListSelectionModel.
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 83 def initialize component raise "Components passed to DefaultListSelectionModel is nil" unless component @obj = component @selected_indices = @obj.selected_indices # in this case since it is called immediately upon extend, user cannot change this # Need a method to let user change after extending @selection_mode = @obj.selection_mode list_bindings end |
Instance Method Details
#add_row_selection_interval(ix0, ix1) ⇒ Object
add the following range to selected items, unless already present should only be used if multiple selection interval
220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 220 def add_row_selection_interval ix0, ix1 return if @obj.selection_mode != :multiple @anchor_selection_index = ix0 @lead_selection_index = ix1 ix0.upto(ix1) {|i| @selected_indices << i unless @selected_indices.include? i @obj.fire_row_changed i } lse = ListSelectionEvent.new(ix0, ix1, @obj, :INSERT) @obj.fire_handler :LIST_SELECTION_EVENT, lse #$log.debug " DLSM firing LIST_SELECTION EVENT #{lse}" end |
#ask_select(prompt = "Enter selection pattern: ") ⇒ Object
Asks user to enter a string or pattern for selecting rows Selects rows based on pattern, leaving other selections as-is
300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 300 def ask_select prompt="Enter selection pattern: " ret = get_string prompt return if ret.nil? || ret == "" indices = get_matching_indices ret #$log.debug "listselectionmodel: ask_select got matches#{@indices} " return if indices.nil? || indices.empty? indices.each { |e| # will not work if single select !! FIXME add_row_selection_interval e,e } end |
#ask_unselect(prompt = "Enter selection pattern: ") ⇒ Object
Asks user to enter a string or pattern for UNselecting rows UNSelects rows based on pattern, leaving other selections as-is
326 327 328 329 330 331 332 333 334 335 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 326 def ask_unselect prompt="Enter selection pattern: " ret = get_string prompt 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 remove_row_selection_interval e,e } end |
#clear_selection ⇒ Object
clears selected indices, typically called when multiple select Key binding is application specific
175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 175 def clear_selection return if @selected_indices.nil? || @selected_indices.empty? arr = @selected_indices.dup # to un highlight @selected_indices.clear arr.each {|i| @obj.fire_row_changed(i) } @selected_index = nil @old_selected_index = nil # User should ignore first two params lse = ListSelectionEvent.new(0, arr.size, @obj, :CLEAR) @obj.fire_handler :LIST_SELECTION_EVENT, lse arr = nil end |
#get_matching_indices(pattern) ⇒ Object
returns a list of matching indices using a simple regex match on given pattern returns an empty list if no match
313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 313 def get_matching_indices pattern matches = [] @obj.content.each_with_index { |e,i| # convert to string for tables e = e.to_s unless e.is_a? String if e =~ /#{pattern}/ matches << i end } return matches end |
#goto_next_selection ⇒ Object
after selecting, traverse selections forward
202 203 204 205 206 207 208 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 202 def goto_next_selection return if selected_rows().length == 0 row = selected_rows().sort.find { |i| i > @obj.current_index } row ||= @obj.current_index #@obj.current_index = row @obj.goto_line row end |
#goto_prev_selection ⇒ Object
after selecting, traverse selections backward
211 212 213 214 215 216 217 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 211 def goto_prev_selection return if selected_rows().length == 0 row = selected_rows().sort{|a,b| b <=> a}.find { |i| i < @obj.current_index } row ||= @obj.current_index #@obj.current_index = row @obj.goto_line row end |
#insert_index_interval(ix0, len) ⇒ Object
convenience method to select next len rows
244 245 246 247 248 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 244 def insert_index_interval ix0, len @anchor_selection_index = ix0 @lead_selection_index = ix0+len add_row_selection_interval @anchor_selection_index, @lead_selection_index end |
#invert_row_selection(row = @obj.current_index) ⇒ Object
toggles selection for given row Typically called by invert_selection
266 267 268 269 270 271 272 273 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 266 def invert_row_selection row=@obj.current_index @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
toggle selection of entire list Requires application specific key binding
260 261 262 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 260 def invert_selection start_row=0 #+@_header_adjustment start_row.upto(@obj.list.count()-1){|i| invert_row_selection i } end |
#is_row_selected?(crow) ⇒ Boolean Also known as: is_selected?
returns true
if given row has been selected Now that we use only the array, the multiple check is good enough
190 191 192 193 194 195 196 197 198 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 190 def is_row_selected? crow case @obj.selection_mode when :multiple @selected_indices.include? crow else @selected_index = @selected_indices[0] crow == @selected_index end end |
#list_bindings ⇒ Object
bindings related to selection
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 340 def list_bindings # freeing space for paging, now trying out 'v' as selector. 2014-04-14 - 18:57 @obj.bind_key($row_selector || 'v'.ord, 'toggle selection') { toggle_row_selection } # the mode may be set to single after the constructor, so this would have taken effect. if @obj.selection_mode == :multiple # freeing ctrl_space for back paging, now trying out 'V' as selector. 2014-04-14 - 18:57 @obj.bind_key($range_selector || 'V'.ord, 'range select') { range_select } @obj.bind_key(?+, 'ask_select') { ask_select } @obj.bind_key(?-, 'ask_unselect') { ask_unselect } @obj.bind_key(?a, 'select_all') {select_all} @obj.bind_key(?*, 'invert_selection') { invert_selection } @obj.bind_key(?u, 'clear_selection') { clear_selection } @obj.bind_key([?g,?n], 'goto next selection'){ goto_next_selection } # mapping double keys like vim @obj.bind_key([?g,?p], 'goto prev selection'){ goto_prev_selection } # mapping double keys like vim end @_header_adjustment ||= 0 # incase caller does not use #@obj._events << :LIST_SELECTION_EVENT unless @obj._events.include? :LIST_SELECTION_EVENT end |
#list_init_vars ⇒ Object
359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 359 def list_init_vars # uncommenting since link with obj will be broken #@selected_indices = [] @selected_index = nil @old_selected_index = nil #@row_selected_symbol = '' ## FIXME we are not doing selectors at present. should we, else remove this if @show_selector @row_selected_symbol ||= '*' @row_unselected_symbol ||= ' ' @left_margin ||= @row_selected_symbol.length end end |
#range_select(crow = @obj.current_index) ⇒ Object
Range select. Only for multiple mode. Uses the last row clicked on, till the current one. If user clicks inside a selcted range, then deselect from last click till current (remove from earlier) If user clicks outside selected range, then select from last click till current (add to earlier) typically bound to Ctrl-Space (0)
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 146 def range_select crow=@obj.current_index #alert "add to selection fired #{@last_clicked}" @last_clicked ||= crow min = [@last_clicked, crow].min max = [@last_clicked, crow].max case @obj.selection_mode when :multiple if @selected_indices.include? crow # delete from last_clicked until this one in any direction min.upto(max){ |i| @selected_indices.delete i @obj.fire_row_changed i } lse = ListSelectionEvent.new(min, max, @obj, :DELETE) @obj.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) @obj.fire_row_changed i } lse = ListSelectionEvent.new(min, max, @obj, :INSERT) @obj.fire_handler :LIST_SELECTION_EVENT, lse end else end @last_clicked = crow # 2014-04-08 - 01:21 this was missing, i think it is required self end |
#remove_row_selection_interval(ix0, ix1) ⇒ Object
remove selected indices between given indices inclusive
234 235 236 237 238 239 240 241 242 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 234 def remove_row_selection_interval ix0, ix1 @anchor_selection_index = ix0 @lead_selection_index = ix1 arr = @selected_indices.dup # to un highlight @selected_indices.delete_if {|x| x >= ix0 and x <= ix1 } arr.each {|i| @obj.fire_row_changed(i) } lse = ListSelectionEvent.new(ix0, ix1, @obj, :DELETE) @obj.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.
252 253 254 255 256 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 252 def select_all start_row=0 #+@_header_adjustment # 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, @obj.list.count()-1 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) TODO is this even needed, scrap
278 279 280 281 282 283 284 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 278 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_rows ⇒ Object
return the indices selected
373 374 375 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 373 def selected_rows @selected_indices end |
#selected_value ⇒ Object
returns first selection, meant for convenience of single select listboxes earlier called selected_item
382 383 384 385 386 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 382 def selected_value return nil if @selected_indices.empty? @obj[@selected_indices.first] #selected_values.first end |
#selected_values ⇒ Object
return the values selected
377 378 379 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 377 def selected_values @obj.values_at(*@selected_indices) end |
#toggle_row_selection(crow = @obj.current_index) ⇒ Object
change selection of current row on pressing space bar (or keybinding) If mode is multiple, then this row is added to previous selections
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 100 def toggle_row_selection crow=@obj.current_index @last_clicked = crow @repaint_required = true case @obj.selection_mode when :multiple if @selected_indices.include? crow @selected_indices.delete crow lse = ListSelectionEvent.new(crow, crow, @obj, :DELETE) @obj.fire_handler :LIST_SELECTION_EVENT, lse else @selected_indices << crow lse = ListSelectionEvent.new(crow, crow, @obj, :INSERT) @obj.fire_handler :LIST_SELECTION_EVENT, lse end else # single - now change to use array only @selected_index = @selected_indices[0] if @selected_index == crow @old_selected_index = @selected_index # 2011-10-15 so we can unhighlight @selected_index = nil @selected_indices.clear lse = ListSelectionEvent.new(crow, crow, @obj, :DELETE) @obj.fire_handler :LIST_SELECTION_EVENT, lse else @selected_indices[0] = crow @obj.fire_row_changed(@old_selected_index) if @old_selected_index @old_selected_index = crow # 2011-10-15 so we can unhighlight lse = ListSelectionEvent.new(crow, crow, @obj, :INSERT) @obj.fire_handler :LIST_SELECTION_EVENT, lse end end @obj.fire_row_changed crow #alert "toggling #{@selected_indices.join(',')}" end |
#unselect_values(values) ⇒ Object
290 291 292 293 294 295 296 |
# File 'lib/canis/core/include/listselectionmodel.rb', line 290 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 |