rbhex-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG +2000 -0
- data/LICENSE +56 -0
- data/README.md +44 -0
- data/examples/abasiclist.rb +179 -0
- data/examples/alpmenu.rb +50 -0
- data/examples/app.sample +19 -0
- data/examples/atree.rb +100 -0
- data/examples/bline.rb +136 -0
- data/examples/common/file.rb +45 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +60 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todo.txt.bak +10 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +502 -0
- data/examples/dirtree.rb +94 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +146 -0
- data/examples/tasks.rb +178 -0
- data/examples/term2.rb +84 -0
- data/examples/testbuttons.rb +296 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testfields.rb +195 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +170 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +128 -0
- data/lib/rbhex.rb +6 -0
- data/lib/rbhex/core/docs/index.txt +73 -0
- data/lib/rbhex/core/include/action.rb +80 -0
- data/lib/rbhex/core/include/actionmanager.rb +49 -0
- data/lib/rbhex/core/include/appmethods.rb +214 -0
- data/lib/rbhex/core/include/bordertitle.rb +48 -0
- data/lib/rbhex/core/include/chunk.rb +203 -0
- data/lib/rbhex/core/include/io.rb +553 -0
- data/lib/rbhex/core/include/listbindings.rb +74 -0
- data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
- data/lib/rbhex/core/include/listeditable.rb +317 -0
- data/lib/rbhex/core/include/listscrollable.rb +663 -0
- data/lib/rbhex/core/include/listselectable.rb +271 -0
- data/lib/rbhex/core/include/multibuffer.rb +83 -0
- data/lib/rbhex/core/include/orderedhash.rb +77 -0
- data/lib/rbhex/core/include/ractionevent.rb +73 -0
- data/lib/rbhex/core/include/rchangeevent.rb +27 -0
- data/lib/rbhex/core/include/rhistory.rb +95 -0
- data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
- data/lib/rbhex/core/include/vieditable.rb +172 -0
- data/lib/rbhex/core/include/widgetmenu.rb +66 -0
- data/lib/rbhex/core/system/colormap.rb +165 -0
- data/lib/rbhex/core/system/keyboard.rb +150 -0
- data/lib/rbhex/core/system/keydefs.rb +30 -0
- data/lib/rbhex/core/system/ncurses.rb +236 -0
- data/lib/rbhex/core/system/panel.rb +162 -0
- data/lib/rbhex/core/system/window.rb +913 -0
- data/lib/rbhex/core/util/ansiparser.rb +119 -0
- data/lib/rbhex/core/util/app.rb +1228 -0
- data/lib/rbhex/core/util/basestack.rb +410 -0
- data/lib/rbhex/core/util/bottomline.rb +1859 -0
- data/lib/rbhex/core/util/colorparser.rb +77 -0
- data/lib/rbhex/core/util/focusmanager.rb +31 -0
- data/lib/rbhex/core/util/padreader.rb +192 -0
- data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
- data/lib/rbhex/core/util/rdialogs.rb +574 -0
- data/lib/rbhex/core/util/viewer.rb +149 -0
- data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
- data/lib/rbhex/core/version.rb +5 -0
- data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
- data/lib/rbhex/core/widgets/box.rb +58 -0
- data/lib/rbhex/core/widgets/divider.rb +310 -0
- data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
- data/lib/rbhex/core/widgets/rcombo.rb +253 -0
- data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
- data/lib/rbhex/core/widgets/rlink.rb +30 -0
- data/lib/rbhex/core/widgets/rlist.rb +696 -0
- data/lib/rbhex/core/widgets/rmenu.rb +958 -0
- data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
- data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
- data/lib/rbhex/core/widgets/rprogress.rb +118 -0
- data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
- data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
- data/lib/rbhex/core/widgets/rtextview.rb +739 -0
- data/lib/rbhex/core/widgets/rtree.rb +768 -0
- data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
- data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
- data/lib/rbhex/core/widgets/statusline.rb +113 -0
- data/lib/rbhex/core/widgets/tabular.rb +264 -0
- data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
- data/lib/rbhex/core/widgets/textpad.rb +995 -0
- data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
- data/rbhex-core.gemspec +32 -0
- metadata +172 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'rbhex'
|
|
2
|
+
##
|
|
3
|
+
module RubyCurses
|
|
4
|
+
class Link < Button
|
|
5
|
+
dsl_property :description
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def initialize form, config={}, &block
|
|
9
|
+
super
|
|
10
|
+
@text_offset = 0
|
|
11
|
+
# haha we've never done this, pin the cursor up on 0,0
|
|
12
|
+
@col_offset = -1
|
|
13
|
+
# this won't be triggered since the shortcut does not set menmo
|
|
14
|
+
# unless form is there.
|
|
15
|
+
# Sometimes the mnemonic is not in text, such as '?'
|
|
16
|
+
if @mnemonic
|
|
17
|
+
form.bind_key(@mnemonic.downcase, self){ self.fire }
|
|
18
|
+
end
|
|
19
|
+
@display_length = config[:width]
|
|
20
|
+
end
|
|
21
|
+
def fire
|
|
22
|
+
super
|
|
23
|
+
self.focus
|
|
24
|
+
end
|
|
25
|
+
def getvalue_for_paint
|
|
26
|
+
getvalue()
|
|
27
|
+
end
|
|
28
|
+
##
|
|
29
|
+
end # class
|
|
30
|
+
end # module
|
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
* Name: rlistbox: basic scrollable lists - no editing, see editablelistbox of more
|
|
3
|
+
* Description
|
|
4
|
+
* Author: rkumar (arunachalesha)
|
|
5
|
+
* Date: 2010-09-26 16:00
|
|
6
|
+
* License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
7
|
+
*
|
|
8
|
+
TODO
|
|
9
|
+
[x] removed Popup, ListDataEvent and ListDataModel !
|
|
10
|
+
[x] XXX Can we separate editing out. Make a ReadonlyList, and extend it as EditableList. This way the usual
|
|
11
|
+
use case remains cleaner.
|
|
12
|
+
|
|
13
|
+
CHANGES
|
|
14
|
+
- 2011-11-18 changed name to list
|
|
15
|
+
|
|
16
|
+
=end
|
|
17
|
+
require 'rbhex'
|
|
18
|
+
require 'rbhex/core/include/listcellrenderer'
|
|
19
|
+
require 'rbhex/core/include/bordertitle'
|
|
20
|
+
#require 'rbhex/extras/include/listkeys'
|
|
21
|
+
require 'forwardable'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
module RubyCurses
|
|
25
|
+
extend self
|
|
26
|
+
##
|
|
27
|
+
##
|
|
28
|
+
# scrollable, selectable list of items
|
|
29
|
+
# - @selected contains indices of selected objects.
|
|
30
|
+
##
|
|
31
|
+
##
|
|
32
|
+
# A readonly control for displaying a list of data or values.
|
|
33
|
+
# Although user editing is not allowed, but the list may be repopulated
|
|
34
|
+
# as in a directory listing, or a list dependent on some other control's value.
|
|
35
|
+
# This is not a drop-in replacement for Listbox as it drops many methods that are redundant.
|
|
36
|
+
# Default selection is single, as opposed to Listbox.
|
|
37
|
+
#
|
|
38
|
+
class List < Widget
|
|
39
|
+
|
|
40
|
+
require 'rbhex/core/include/listscrollable'
|
|
41
|
+
require 'rbhex/core/include/listselectable' # added 2011-10-8
|
|
42
|
+
include ListScrollable
|
|
43
|
+
include NewListSelectable # added 2011-10-8
|
|
44
|
+
extend Forwardable
|
|
45
|
+
#dsl_accessor :height # << widget already has this
|
|
46
|
+
#dsl_accessor :title
|
|
47
|
+
#dsl_property :title_attrib # bold, reverse, normal
|
|
48
|
+
# dsl_accessor :list # the array of data to be sent by user
|
|
49
|
+
attr_reader :toprow
|
|
50
|
+
#dsl_accessor :default_values # array of default values
|
|
51
|
+
#dsl_accessor :is_popup # if it is in a popup and single select, selection closes
|
|
52
|
+
attr_accessor :current_index
|
|
53
|
+
# selection mode multiple, single and none (none added 2011-12-26)
|
|
54
|
+
dsl_accessor :selection_mode
|
|
55
|
+
dsl_accessor :selected_color, :selected_bgcolor, :selected_attr
|
|
56
|
+
dsl_accessor :max_visible_items # how many to display 2009-01-11 16:15
|
|
57
|
+
#dsl_accessor :cell_editing_allowed
|
|
58
|
+
dsl_property :show_selector # boolean
|
|
59
|
+
dsl_property :row_selected_symbol # 2009-01-12 12:01 changed from selector to selected
|
|
60
|
+
dsl_property :row_unselected_symbol # added 2009-01-12 12:00
|
|
61
|
+
dsl_property :left_margin
|
|
62
|
+
# please set these in he constructor block. Settin them later will have no effect
|
|
63
|
+
# since i would have bound them to actions
|
|
64
|
+
attr_accessor :one_key_selection # will pressing a single key select or not
|
|
65
|
+
# set to true if data could have newlines, tabs, and other stuff, def true
|
|
66
|
+
dsl_accessor :sanitization_required
|
|
67
|
+
# set to true if cell-renderer data can exceed width of listbox, default true
|
|
68
|
+
# if you are absolutely sure that data is constant width, set to false.
|
|
69
|
+
dsl_accessor :truncation_required
|
|
70
|
+
#dsl_accessor :suppress_borders #to_print_borders
|
|
71
|
+
dsl_accessor :justify # will be picked up by renderer
|
|
72
|
+
# index of selected row
|
|
73
|
+
attr_accessor :selected_index
|
|
74
|
+
# index of selected rows, if multiple selection asked for
|
|
75
|
+
dsl_accessor :selected_indices
|
|
76
|
+
|
|
77
|
+
dsl_accessor :should_show_focus
|
|
78
|
+
|
|
79
|
+
# basic listbox constructor
|
|
80
|
+
#
|
|
81
|
+
def initialize form=nil, config={}, &block
|
|
82
|
+
@focusable = true
|
|
83
|
+
@editable = false
|
|
84
|
+
@sanitization_required = true # cleanup control and non print chars
|
|
85
|
+
@truncation_required = true
|
|
86
|
+
@suppress_borders = false #to_print_borders = 1
|
|
87
|
+
#@row_selected_symbol = '' # thi sprevents default value from being set
|
|
88
|
+
@row = 0
|
|
89
|
+
@col = 0
|
|
90
|
+
# data of listbox this is not an array, its a pointer to the listdatamodel
|
|
91
|
+
@list = nil
|
|
92
|
+
# any special attribs such as status to be printed in col1, or color (selection)
|
|
93
|
+
@list_attribs = {}
|
|
94
|
+
@current_index = 0
|
|
95
|
+
@selected_indices = []
|
|
96
|
+
@selected_index = nil
|
|
97
|
+
@row_offset = @col_offset = 1
|
|
98
|
+
@should_show_focus = true # Here's its on since the cellrenderer will show it on repaint
|
|
99
|
+
@one_key_selection = false # use vim keys
|
|
100
|
+
@selection_mode = :multiple # default is multiple, anything else given becomes single
|
|
101
|
+
super
|
|
102
|
+
@_events.push(*[:ENTER_ROW, :LEAVE_ROW, :LIST_SELECTION_EVENT, :PRESS])
|
|
103
|
+
# I have moved this here so user can override keys.
|
|
104
|
+
map_keys unless @keys_mapped
|
|
105
|
+
@win = @graphic # 2010-01-04 12:36 BUFFERED replace form.window with graphic
|
|
106
|
+
@win_left = 0
|
|
107
|
+
@win_top = 0
|
|
108
|
+
|
|
109
|
+
init_vars
|
|
110
|
+
@internal_width = 2
|
|
111
|
+
#@internal_width = 0 if @suppress_borders # NOTE it is 1 in bordertitle
|
|
112
|
+
bordertitle_init
|
|
113
|
+
|
|
114
|
+
if @list && !@selected_index.nil? # XXX
|
|
115
|
+
set_focus_on @selected_index # the new version
|
|
116
|
+
end
|
|
117
|
+
init_actions
|
|
118
|
+
end
|
|
119
|
+
# this is called several times, from constructor
|
|
120
|
+
# and when list data changed, so only put relevant resets here.
|
|
121
|
+
def init_vars
|
|
122
|
+
@repaint_required = true
|
|
123
|
+
@widget_scrolled = true # 2011-10-15
|
|
124
|
+
@toprow = @pcol = 0
|
|
125
|
+
if @show_selector
|
|
126
|
+
@row_selected_symbol ||= '>'
|
|
127
|
+
@row_unselected_symbol ||= ' '
|
|
128
|
+
@left_margin ||= @row_selected_symbol.length
|
|
129
|
+
end
|
|
130
|
+
@row_selected_symbol ||= ''
|
|
131
|
+
#@left_margin ||= 0
|
|
132
|
+
@one_key_selection = false if @one_key_selection.nil?
|
|
133
|
+
@row_offset = @col_offset = 0 if @suppress_borders
|
|
134
|
+
|
|
135
|
+
end
|
|
136
|
+
def map_keys
|
|
137
|
+
return if @keys_mapped
|
|
138
|
+
require 'rbhex/core/include/listbindings'
|
|
139
|
+
bindings()
|
|
140
|
+
bind_key(?f, 'next row starting with char'){ ask_selection_for_char() }
|
|
141
|
+
bind_key(?\M-v, 'toggle one_key_selection'){ @one_key_selection = !@one_key_selection }
|
|
142
|
+
bind_key(13, 'fire action event'){ fire_action_event }
|
|
143
|
+
list_bindings unless @selection_mode == :none # listselectable
|
|
144
|
+
@keys_mapped = true
|
|
145
|
+
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
## returns count of row, needed by scrollbar and others.
|
|
149
|
+
def row_count
|
|
150
|
+
return 0 if @list.nil?
|
|
151
|
+
@list.length
|
|
152
|
+
end
|
|
153
|
+
# start scrolling when user reaches this row
|
|
154
|
+
def scrollatrow #:nodoc:
|
|
155
|
+
if @suppress_borders
|
|
156
|
+
return @height - 1
|
|
157
|
+
else
|
|
158
|
+
return @height - 3
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
# provide data to List in the form of an Array or Variable or
|
|
162
|
+
# ListDataModel. This will create a default ListSelectionModel.
|
|
163
|
+
#
|
|
164
|
+
# CHANGE as on 2010-09-21 12:53:
|
|
165
|
+
# If explicit nil passed then dummy datamodel and selection model created
|
|
166
|
+
# From now on, constructor will call this, so this can always
|
|
167
|
+
# happen.
|
|
168
|
+
#
|
|
169
|
+
# NOTE: sometimes this can be added much after its painted.
|
|
170
|
+
# Do not expect this to be called from constructor, although that
|
|
171
|
+
# is the usual case. it can be dependent on some other list or tree.
|
|
172
|
+
# @param [Array, Variable, ListDataModel] data to populate list with
|
|
173
|
+
# @return [ListDataModel] just created or assigned
|
|
174
|
+
|
|
175
|
+
def list *val
|
|
176
|
+
return @list if val.empty?
|
|
177
|
+
alist = val[0]
|
|
178
|
+
case alist
|
|
179
|
+
when Array
|
|
180
|
+
@list = alist
|
|
181
|
+
# I possibly should call init_vars in these 3 cases but am doing the minimal 2013-04-10 - 18:27
|
|
182
|
+
# Based no issue: https://github.com/rkumar/rbcurse/issues/15
|
|
183
|
+
@current_index = @toprow = @pcol = 0
|
|
184
|
+
when NilClass
|
|
185
|
+
@list = [] # or nil ?
|
|
186
|
+
@current_index = @toprow = @pcol = 0
|
|
187
|
+
when Variable
|
|
188
|
+
@list = alist.value
|
|
189
|
+
@current_index = @toprow = @pcol = 0
|
|
190
|
+
else
|
|
191
|
+
raise ArgumentError, "Listbox list(): do not know how to handle #{alist.class} "
|
|
192
|
+
end
|
|
193
|
+
clear_selection
|
|
194
|
+
|
|
195
|
+
@repaint_required = true
|
|
196
|
+
@widget_scrolled = true # 2011-10-15
|
|
197
|
+
@list
|
|
198
|
+
end
|
|
199
|
+
def list_data_model; @list; end
|
|
200
|
+
# conv method to insert data, trying to keep names same across along with Tabular, TextView,
|
|
201
|
+
# TextArea and listbox. Don;t use this till i am certain.
|
|
202
|
+
def data=(val)
|
|
203
|
+
list(val)
|
|
204
|
+
end
|
|
205
|
+
# get element at
|
|
206
|
+
# @param [Fixnum] index for element
|
|
207
|
+
# @return [Object] element
|
|
208
|
+
# @since 1.2.0 2010-09-06 14:33 making life easier for others.
|
|
209
|
+
def [](off0)
|
|
210
|
+
@list[off0]
|
|
211
|
+
end
|
|
212
|
+
# return object under cursor
|
|
213
|
+
# Note: this should not be confused with selected row/s. User may not have selected this.
|
|
214
|
+
# This is only useful since in some demos we like to change a status bar as a user scrolls down
|
|
215
|
+
# @since 1.2.0 2010-09-06 14:33 making life easier for others.
|
|
216
|
+
def current_value
|
|
217
|
+
@list[@current_index]
|
|
218
|
+
end
|
|
219
|
+
def remove_all
|
|
220
|
+
return if @list.nil? || @list.empty?
|
|
221
|
+
@list = []
|
|
222
|
+
init_vars
|
|
223
|
+
end
|
|
224
|
+
def_delegators :@list, :include?, :each, :values, :size
|
|
225
|
+
%w[ insert clear delete_at []= << ].each { |e|
|
|
226
|
+
eval %{
|
|
227
|
+
def #{e}(*args)
|
|
228
|
+
@list.send(:#{e}, *args)
|
|
229
|
+
@widget_scrolled = true
|
|
230
|
+
@repaint_required = true
|
|
231
|
+
end
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
def append text
|
|
235
|
+
@list.push text
|
|
236
|
+
@widget_scrolled = true
|
|
237
|
+
@repaint_required = true
|
|
238
|
+
end
|
|
239
|
+
# avoid using "row", i'd rather stick with "index" and "value".
|
|
240
|
+
alias :current_row :current_value
|
|
241
|
+
alias :text :current_value # thanks to shoes, not sure how this will impact since widget has text.
|
|
242
|
+
|
|
243
|
+
### START FOR scrollable ###
|
|
244
|
+
def get_content
|
|
245
|
+
@list
|
|
246
|
+
end
|
|
247
|
+
def get_window #:nodoc:
|
|
248
|
+
@graphic
|
|
249
|
+
end
|
|
250
|
+
### END FOR scrollable ###
|
|
251
|
+
# override widgets text
|
|
252
|
+
# returns indices of selected rows
|
|
253
|
+
def getvalue
|
|
254
|
+
selected_rows
|
|
255
|
+
end
|
|
256
|
+
# Listbox
|
|
257
|
+
def handle_key(ch) #:nodoc:
|
|
258
|
+
#map_keys unless @keys_mapped
|
|
259
|
+
@current_index ||= 0
|
|
260
|
+
@toprow ||= 0
|
|
261
|
+
#h = scrollatrow()
|
|
262
|
+
#rc = row_count
|
|
263
|
+
#$log.debug " basiclistbox got ch #{ch}"
|
|
264
|
+
#$log.debug " when kps #{@KEY_PREV_SELECTION} "
|
|
265
|
+
case ch
|
|
266
|
+
#when 32
|
|
267
|
+
#return if is_popup and @selection_mode == 'single' # not allowing select this way since there will be a difference
|
|
268
|
+
#toggle_row_selection @current_index #, @current_index
|
|
269
|
+
#@repaint_required = true
|
|
270
|
+
#when 0 # c-space
|
|
271
|
+
#add_to_selection
|
|
272
|
+
#when @KEY_NEXT_SELECTION # ?'
|
|
273
|
+
#$log.debug "insdie next selection"
|
|
274
|
+
#@oldrow = @current_index
|
|
275
|
+
#do_next_selection
|
|
276
|
+
#bounds_check
|
|
277
|
+
#when @KEY_PREV_SELECTION # ?"
|
|
278
|
+
#@oldrow = @current_index
|
|
279
|
+
#$log.debug "insdie prev selection"
|
|
280
|
+
#do_prev_selection
|
|
281
|
+
#bounds_check
|
|
282
|
+
#when @KEY_CLEAR_SELECTION
|
|
283
|
+
#clear_selection
|
|
284
|
+
#@repaint_required = true
|
|
285
|
+
when 27, ?\C-c.getbyte(0)
|
|
286
|
+
$multiplier = 0
|
|
287
|
+
when @KEY_BLOCK_SELECTOR
|
|
288
|
+
mark_block #selection
|
|
289
|
+
#when ?\C-u.getbyte(0)
|
|
290
|
+
# multiplier. Series is 4 16 64
|
|
291
|
+
# TESTING @multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
|
|
292
|
+
# return 0
|
|
293
|
+
#when ?\C-c.getbyte(0)
|
|
294
|
+
#@multiplier = 0
|
|
295
|
+
#return 0
|
|
296
|
+
else
|
|
297
|
+
# this has to be fixed, if compo does not handle key it has to continue into next part FIXME
|
|
298
|
+
ret = :UNHANDLED # changed on 2009-01-27 13:14 not going into unhandled, tab not released
|
|
299
|
+
if ret == :UNHANDLED
|
|
300
|
+
# beware one-key eats up numbers. we'll be wondering why
|
|
301
|
+
if @one_key_selection
|
|
302
|
+
case ch
|
|
303
|
+
#when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0), ?0.getbyte(0)..?9.getbyte(0)
|
|
304
|
+
when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0)
|
|
305
|
+
# simple motion, key press defines motion
|
|
306
|
+
ret = set_selection_for_char ch.chr
|
|
307
|
+
else
|
|
308
|
+
ret = process_key ch, self
|
|
309
|
+
@multiplier = 0
|
|
310
|
+
# if no block associated with :PRESS (KEY_ENTER) lets allow the form to use ENTER
|
|
311
|
+
# This is for default buttons. Added NO_BLOCK 2011-12-2
|
|
312
|
+
# 2011-12-2 11:54 PM this was resulting in no repaint even
|
|
313
|
+
# when symbols were being executed??
|
|
314
|
+
# Its risky since symbol can call something which returns
|
|
315
|
+
# UNHNDLED or NO_BLOCK even tho' it executed.
|
|
316
|
+
return :UNHANDLED if ret == :UNHANDLED #|| ret == :NO_BLOCK
|
|
317
|
+
end
|
|
318
|
+
else
|
|
319
|
+
# no motion on single key, we can freak out like in vim, pref f <char> for set_selection
|
|
320
|
+
case ch
|
|
321
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
|
322
|
+
$multiplier *= 10 ; $multiplier += (ch-48)
|
|
323
|
+
#$log.debug " setting mult to #{$multiplier} in list "
|
|
324
|
+
return 0
|
|
325
|
+
end
|
|
326
|
+
ret = process_key ch, self
|
|
327
|
+
# if no block associated with :PRESS (KEY_ENTER) lets allow the form to use ENTER
|
|
328
|
+
# This is for default buttons. Added NO_BLOCK 2011-12-2
|
|
329
|
+
return :UNHANDLED if ret == :UNHANDLED #|| ret == :NO_BLOCK1
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
$multiplier = 0
|
|
334
|
+
end
|
|
335
|
+
#
|
|
336
|
+
# triggered on hitting ENTER button
|
|
337
|
+
#
|
|
338
|
+
def fire_action_event
|
|
339
|
+
require 'rbhex/core/include/ractionevent'
|
|
340
|
+
fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
|
|
341
|
+
end
|
|
342
|
+
# get a keystroke from user and go to first item starting with that key
|
|
343
|
+
def ask_selection_for_char
|
|
344
|
+
ch = @graphic.getch
|
|
345
|
+
if ch < 0 || ch > 255
|
|
346
|
+
return :UNHANDLED
|
|
347
|
+
end
|
|
348
|
+
ret = set_selection_for_char ch.chr
|
|
349
|
+
end
|
|
350
|
+
def ask_search_forward
|
|
351
|
+
regex = get_string("Enter regex to search")
|
|
352
|
+
ix = @list.find_match regex
|
|
353
|
+
if ix.nil?
|
|
354
|
+
alert("No matching data for: #{regex}")
|
|
355
|
+
else
|
|
356
|
+
set_focus_on(ix)
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
# gets string to search and calls data models find prev
|
|
360
|
+
def ask_search_backward
|
|
361
|
+
regex = get_string("Enter regex to search (backward)")
|
|
362
|
+
@last_regex = regex
|
|
363
|
+
ix = @list.find_prev regex, @current_index
|
|
364
|
+
if ix.nil?
|
|
365
|
+
alert("No matching data for: #{regex}")
|
|
366
|
+
else
|
|
367
|
+
set_focus_on(ix)
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
# please check for error before proceeding
|
|
371
|
+
# @return [Boolean] false if no data
|
|
372
|
+
def on_enter
|
|
373
|
+
if @list.nil? || @list.size == 0
|
|
374
|
+
Ncurses.beep
|
|
375
|
+
return :UNHANDLED
|
|
376
|
+
end
|
|
377
|
+
super # forgot this 2011-10-9 that's why events not firign
|
|
378
|
+
on_enter_row @current_index
|
|
379
|
+
set_form_row # added 2009-01-11 23:41
|
|
380
|
+
true
|
|
381
|
+
end
|
|
382
|
+
def on_enter_row arow
|
|
383
|
+
# copied from resultsettextview, can this not be in one place like listscrollable ? FIXME
|
|
384
|
+
if @should_show_focus
|
|
385
|
+
highlight_focussed_row :FOCUSSED
|
|
386
|
+
unless @oldrow == @selected_index
|
|
387
|
+
highlight_focussed_row :UNFOCUSSED
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
fire_handler :ENTER_ROW, self
|
|
391
|
+
@repaint_required = true
|
|
392
|
+
end
|
|
393
|
+
def on_leave_row arow
|
|
394
|
+
fire_handler :LEAVE_ROW, self
|
|
395
|
+
end
|
|
396
|
+
# getter and setter for cell_renderer
|
|
397
|
+
# NOTE: due to our optimization of not repainting unless data has changed
|
|
398
|
+
# or scrolling has happened, highlighting focus will repaint the row if you've
|
|
399
|
+
# colored it. In that case, set <tt>show_show_focus</tt> to false
|
|
400
|
+
def cell_renderer(*val)
|
|
401
|
+
if val.empty?
|
|
402
|
+
@cell_renderer ||= create_default_cell_renderer
|
|
403
|
+
else
|
|
404
|
+
@cell_renderer = val[0]
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
def create_default_cell_renderer
|
|
408
|
+
return ListCellRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => self, "display_length"=> @width-@internal_width-@left_margin}
|
|
409
|
+
#return BasicListCellRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => self, "display_length"=> @width-2-@left_margin}
|
|
410
|
+
end
|
|
411
|
+
##
|
|
412
|
+
# this method chops the data to length before giving it to the
|
|
413
|
+
# renderer, this can cause problems if the renderer does some
|
|
414
|
+
# processing. also, it pans the data horizontally giving the renderer
|
|
415
|
+
# a section of it.
|
|
416
|
+
def repaint #:nodoc:
|
|
417
|
+
return unless @repaint_required
|
|
418
|
+
#
|
|
419
|
+
# TRYING OUT dangerous 2011-10-15
|
|
420
|
+
@repaint_required = false
|
|
421
|
+
@repaint_required = true if @widget_scrolled || @pcol != @old_pcol || @record_changed || @property_changed
|
|
422
|
+
|
|
423
|
+
unless @repaint_required
|
|
424
|
+
unhighlight_row @old_selected_index
|
|
425
|
+
highlight_selected_row
|
|
426
|
+
end
|
|
427
|
+
return unless @repaint_required
|
|
428
|
+
$log.debug "BASICLIST REPAINT WILL HAPPEN #{current_index} "
|
|
429
|
+
# not sure where to put this, once for all or repeat 2010-02-17 23:07 RFED16
|
|
430
|
+
my_win = @form ? @form.window : @target_window
|
|
431
|
+
@graphic = my_win unless @graphic
|
|
432
|
+
raise " #{@name} neither form, nor target window given LB paint " unless my_win
|
|
433
|
+
raise " #{@name} NO GRAPHIC set as yet LB paint " unless @graphic
|
|
434
|
+
raise "width or height not given w:#{@width} , h:#{@height} " if @width.nil? || @height.nil?
|
|
435
|
+
@win_left = my_win.left
|
|
436
|
+
@win_top = my_win.top
|
|
437
|
+
@left_margin ||= @row_selected_symbol.length
|
|
438
|
+
# we are making sure display len does not exceed width XXX hope this does not wreak havoc elsewhere
|
|
439
|
+
_dl = [@display_length || 100, @width-@internal_width-@left_margin].min # 2011-09-17 RK overwriting when we move grabbar in vimsplit
|
|
440
|
+
|
|
441
|
+
$log.debug "basiclistbox repaint #{@name} graphic #{@graphic}"
|
|
442
|
+
#$log.debug "XXX repaint to_print #{@to_print_borders} "
|
|
443
|
+
print_borders unless @suppress_borders # do this once only, unless everything changes
|
|
444
|
+
#maxlen = @maxlen || @width-2
|
|
445
|
+
tm = list()
|
|
446
|
+
rc = row_count
|
|
447
|
+
@longest_line = @width
|
|
448
|
+
$log.debug " rbasiclistbox #{row_count}, w:#{@width} , maxlen:#{@maxlen} "
|
|
449
|
+
if rc > 0 # just added in case no data passed
|
|
450
|
+
tr = @toprow
|
|
451
|
+
acolor = get_color $datacolor
|
|
452
|
+
h = scrollatrow()
|
|
453
|
+
r,c = rowcol
|
|
454
|
+
0.upto(h) do |hh|
|
|
455
|
+
crow = tr+hh
|
|
456
|
+
if crow < rc
|
|
457
|
+
_focussed = @current_index == crow ? true : false # row focussed ?
|
|
458
|
+
focus_type = _focussed
|
|
459
|
+
focus_type = :SOFT_FOCUS if _focussed && !@focussed
|
|
460
|
+
selected = is_row_selected crow
|
|
461
|
+
content = tm[crow] # 2009-01-17 18:37 chomp giving error in some cases says frozen
|
|
462
|
+
content = convert_value_to_text content, crow # 2010-09-23 20:12
|
|
463
|
+
# by now it has to be a String
|
|
464
|
+
if content.is_a? String
|
|
465
|
+
content = content.dup
|
|
466
|
+
sanitize content if @sanitization_required
|
|
467
|
+
truncate content if @truncation_required
|
|
468
|
+
end
|
|
469
|
+
## set the selector symbol if requested
|
|
470
|
+
selection_symbol = ''
|
|
471
|
+
if @show_selector
|
|
472
|
+
if selected
|
|
473
|
+
selection_symbol = @row_selected_symbol
|
|
474
|
+
else
|
|
475
|
+
selection_symbol = @row_unselected_symbol
|
|
476
|
+
end
|
|
477
|
+
@graphic.printstring r+hh, c, selection_symbol, acolor,@attr
|
|
478
|
+
end
|
|
479
|
+
#renderer = get_default_cell_renderer_for_class content.class.to_s
|
|
480
|
+
renderer = cell_renderer()
|
|
481
|
+
renderer.display_length = _dl # 2011-09-17 RK overwriting when we move grabbar in vimsplit
|
|
482
|
+
renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focus_type, selected
|
|
483
|
+
else
|
|
484
|
+
# clear rows
|
|
485
|
+
@graphic.printstring r+hh, c, " " * (@width-@internal_width), acolor,@attr
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
end # rc == 0
|
|
489
|
+
@repaint_required = false
|
|
490
|
+
# 2011-10-13
|
|
491
|
+
@widget_scrolled = false
|
|
492
|
+
@record_changed = false
|
|
493
|
+
@property_changed = false
|
|
494
|
+
@old_pcol = @pcol
|
|
495
|
+
end
|
|
496
|
+
def highlight_selected_row r=nil, c=nil, acolor=nil
|
|
497
|
+
return unless @selected_index # no selection
|
|
498
|
+
r = _convert_index_to_printable_row(@selected_index) unless r
|
|
499
|
+
return unless r # not on screen
|
|
500
|
+
unless c
|
|
501
|
+
_r, c = rowcol
|
|
502
|
+
end
|
|
503
|
+
acolor ||= get_color $promptcolor, @selected_color, @selected_bgcolor
|
|
504
|
+
att = FFI::NCurses::A_REVERSE
|
|
505
|
+
att = get_attrib(@selected_attrib) if @selected_attrib
|
|
506
|
+
@graphic.mvchgat(y=r, x=c, @width-@internal_width-@left_margin, att , acolor , nil)
|
|
507
|
+
end
|
|
508
|
+
def unhighlight_row index, r=nil, c=nil, acolor=nil
|
|
509
|
+
return unless index # no selection
|
|
510
|
+
r = _convert_index_to_printable_row(index) unless r
|
|
511
|
+
return unless r # not on screen
|
|
512
|
+
unless c
|
|
513
|
+
_r, c = rowcol
|
|
514
|
+
end
|
|
515
|
+
acolor ||= get_color $datacolor
|
|
516
|
+
att = FFI::NCurses::A_NORMAL
|
|
517
|
+
att = get_attrib(@normal_attrib) if @normal_attrib
|
|
518
|
+
@graphic.mvchgat(y=r, x=c, @width-@internal_width-@left_margin, att , acolor , nil)
|
|
519
|
+
end
|
|
520
|
+
# the idea here is to allow users who subclass Listbox to easily override parts of the cumbersome repaint
|
|
521
|
+
# method. This assumes your List has some data, but you print a lot more. Now you don't need to
|
|
522
|
+
# change the data in the renderer, or keep formatted data in the list itself.
|
|
523
|
+
# e.g. @list contains file names, or File objects, and this converts to a long listing.
|
|
524
|
+
# If the renderer did that, the truncation would be on wrong data.
|
|
525
|
+
# @since 1.2.0
|
|
526
|
+
def convert_value_to_text value, crow
|
|
527
|
+
case value
|
|
528
|
+
when TrueClass, FalseClass
|
|
529
|
+
value
|
|
530
|
+
else
|
|
531
|
+
value.to_s if value
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
# takes a block, this way anyone extending this klass can just pass a block to do his job
|
|
535
|
+
# This modifies the string
|
|
536
|
+
def sanitize content #:nodoc:
|
|
537
|
+
if content.is_a? String
|
|
538
|
+
content.chomp!
|
|
539
|
+
content.gsub!(/\t/, ' ') # don't display tab
|
|
540
|
+
content.gsub!(/[^[:print:]]/, '') # don't display non print characters
|
|
541
|
+
else
|
|
542
|
+
content
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
# returns only the visible portion of string taking into account display length
|
|
546
|
+
# and horizontal scrolling. MODIFIES STRING
|
|
547
|
+
def truncate content # :nodoc:
|
|
548
|
+
maxlen = @maxlen || @width-@internal_width
|
|
549
|
+
maxlen = @width-@internal_width if maxlen > @width-@internal_width
|
|
550
|
+
if maxlen == 0 # (otherwise it becoems -1 below)
|
|
551
|
+
content.replace ""
|
|
552
|
+
return
|
|
553
|
+
end
|
|
554
|
+
if !content.nil?
|
|
555
|
+
cl = content.length
|
|
556
|
+
if cl > maxlen # only show maxlen
|
|
557
|
+
@longest_line = cl if cl > @longest_line
|
|
558
|
+
#content = content[@pcol..@pcol+maxlen-1]
|
|
559
|
+
## taking care of when scrolling is needed but longest_line is misreported
|
|
560
|
+
# So we scroll always and need to check 2013-03-06 - 00:09
|
|
561
|
+
content.replace(content[@pcol..@pcol+maxlen-1] || " ")
|
|
562
|
+
else
|
|
563
|
+
## taking care of when scrolling is needed but longest_line is misreported
|
|
564
|
+
# So we scroll always and need to check 2013-03-06 - 00:09
|
|
565
|
+
content.replace(content[@pcol..-1]||" ") if @pcol > 0
|
|
566
|
+
end
|
|
567
|
+
end
|
|
568
|
+
content
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
# be informed when data has changed. required here, was being called by listdatamodel earlier
|
|
572
|
+
def list_data_changed
|
|
573
|
+
if row_count == 0 # added on 2009-02-02 17:13 so cursor not hanging on last row which could be empty
|
|
574
|
+
init_vars
|
|
575
|
+
@current_index = 0
|
|
576
|
+
set_form_row
|
|
577
|
+
end
|
|
578
|
+
@widget_scrolled = true # 2011-10-15
|
|
579
|
+
@repaint_required = true
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
# set cursor column position
|
|
583
|
+
# if i set col1 to @curpos, i can move around left right if key mapped
|
|
584
|
+
def set_form_col col1=0 #:nodoc:
|
|
585
|
+
@cols_panned ||= 0
|
|
586
|
+
# editable listboxes will involve changing cursor and the form issue
|
|
587
|
+
win_col = 0
|
|
588
|
+
col2 = win_col + @col + @col_offset + col1 + @cols_panned + @left_margin
|
|
589
|
+
$log.debug " set_form_col in rlistbox #{@col}+ left_margin #{@left_margin} ( #{col2} ) "
|
|
590
|
+
setrowcol nil, col2
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
# @group selection related
|
|
594
|
+
|
|
595
|
+
# change selection of current row on pressing space bar
|
|
596
|
+
# If mode is multiple, then other selections are cleared and this is added
|
|
597
|
+
# NOTE: 2011-10-8 allow multiple select on spacebar. Using C-Space was quite unfriendly
|
|
598
|
+
# although it will still work
|
|
599
|
+
def OLDtoggle_row_selection crow=@current_index
|
|
600
|
+
@repaint_required = true
|
|
601
|
+
row = crow
|
|
602
|
+
case @selection_mode
|
|
603
|
+
when :multiple
|
|
604
|
+
add_to_selection
|
|
605
|
+
#clear_selection
|
|
606
|
+
#@selected_indices[0] = crow #@current_index
|
|
607
|
+
else
|
|
608
|
+
if @selected_index == crow #@current_index
|
|
609
|
+
@selected_index = nil
|
|
610
|
+
lse = ListSelectionEvent.new(crow, crow, self, :DELETE)
|
|
611
|
+
fire_handler :LIST_SELECTION_EVENT, lse
|
|
612
|
+
else
|
|
613
|
+
@selected_index = crow #@current_index
|
|
614
|
+
lse = ListSelectionEvent.new(crow, crow, self, :INSERT)
|
|
615
|
+
fire_handler :LIST_SELECTION_EVENT, lse
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
#
|
|
620
|
+
# Only for multiple mode.
|
|
621
|
+
# add an item to selection, if selection mode is multiple
|
|
622
|
+
# if item already selected, it is deselected, else selected
|
|
623
|
+
# typically bound to Ctrl-Space
|
|
624
|
+
def OLDadd_to_selection
|
|
625
|
+
crow = @current_index
|
|
626
|
+
case @selection_mode
|
|
627
|
+
when :multiple
|
|
628
|
+
if @selected_indices.include? @current_index
|
|
629
|
+
@selected_indices.delete @current_index
|
|
630
|
+
lse = ListSelectionEvent.new(crow, crow, self, :DELETE)
|
|
631
|
+
fire_handler :LIST_SELECTION_EVENT, lse
|
|
632
|
+
else
|
|
633
|
+
@selected_indices << @current_index
|
|
634
|
+
lse = ListSelectionEvent.new(crow, crow, self, :INSERT)
|
|
635
|
+
fire_handler :LIST_SELECTION_EVENT, lse
|
|
636
|
+
end
|
|
637
|
+
else
|
|
638
|
+
end
|
|
639
|
+
@repaint_required = true
|
|
640
|
+
end
|
|
641
|
+
# clears selected indices
|
|
642
|
+
def OLDclear_selection
|
|
643
|
+
@selected_indices = []
|
|
644
|
+
@repaint_required = true
|
|
645
|
+
end
|
|
646
|
+
def OLDis_row_selected crow=@current_index
|
|
647
|
+
case @selection_mode
|
|
648
|
+
when :multiple
|
|
649
|
+
@selected_indices.include? crow
|
|
650
|
+
else
|
|
651
|
+
crow == @selected_index
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
alias :is_selected? is_row_selected
|
|
655
|
+
def goto_next_selection
|
|
656
|
+
return if selected_rows().length == 0
|
|
657
|
+
row = selected_rows().sort.find { |i| i > @current_index }
|
|
658
|
+
row ||= @current_index
|
|
659
|
+
@current_index = row
|
|
660
|
+
@repaint_required = true # fire list_select XXX
|
|
661
|
+
end
|
|
662
|
+
def goto_prev_selection
|
|
663
|
+
return if selected_rows().length == 0
|
|
664
|
+
row = selected_rows().sort{|a,b| b <=> a}.find { |i| i < @current_index }
|
|
665
|
+
row ||= @current_index
|
|
666
|
+
@current_index = row
|
|
667
|
+
@repaint_required = true # fire list_select XXX
|
|
668
|
+
end
|
|
669
|
+
# Returns selected indices
|
|
670
|
+
# Indices are often required since the renderer may modify the values displayed
|
|
671
|
+
#
|
|
672
|
+
def get_selected_indices; @selected_indices; end
|
|
673
|
+
|
|
674
|
+
# Returns selected values
|
|
675
|
+
#
|
|
676
|
+
def get_selected_values
|
|
677
|
+
selected = []
|
|
678
|
+
@selected_indices.each { |i| selected << @list[i] }
|
|
679
|
+
return selected
|
|
680
|
+
end
|
|
681
|
+
alias :selected_values :get_selected_values
|
|
682
|
+
|
|
683
|
+
# Define actions that can be popped up by PromptMenu or other menubar
|
|
684
|
+
# Currently, only PromptMenu, but we can start contextually appending to Menubar or others
|
|
685
|
+
def init_actions
|
|
686
|
+
am = action_manager()
|
|
687
|
+
am.add_action(Action.new("&Disable selection") { @selection_mode = :none; unbind_key(32); bind_key(32, :scroll_forward); } )
|
|
688
|
+
am.add_action(Action.new("&Edit Toggle") { @edit_toggle = !@edit_toggle; $status_message.value = "Edit toggle is #{@edit_toggle}" })
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
# ADD HERE
|
|
693
|
+
end # class listb
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
end # module
|