rbcurse-extras 0.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.
Files changed (38) hide show
  1. data/README.md +75 -0
  2. data/VERSION +1 -0
  3. data/examples/data/list.txt +300 -0
  4. data/examples/data/lotr.txt +12 -0
  5. data/examples/data/table.txt +36 -0
  6. data/examples/data/tasks.txt +27 -0
  7. data/examples/data/unix1.txt +21 -0
  8. data/examples/inc/qdfilechooser.rb +70 -0
  9. data/examples/inc/rfe_renderer.rb +121 -0
  10. data/examples/newtabbedwindow.rb +100 -0
  11. data/examples/rfe.rb +1236 -0
  12. data/examples/test2.rb +670 -0
  13. data/examples/testeditlist.rb +78 -0
  14. data/examples/testtable.rb +270 -0
  15. data/examples/testvimsplit.rb +141 -0
  16. data/lib/rbcurse/extras/include/celleditor.rb +112 -0
  17. data/lib/rbcurse/extras/include/checkboxcellrenderer.rb +57 -0
  18. data/lib/rbcurse/extras/include/comboboxcellrenderer.rb +30 -0
  19. data/lib/rbcurse/extras/include/defaultlistselectionmodel.rb +79 -0
  20. data/lib/rbcurse/extras/include/listkeys.rb +37 -0
  21. data/lib/rbcurse/extras/include/listselectable.rb +144 -0
  22. data/lib/rbcurse/extras/include/tableextended.rb +40 -0
  23. data/lib/rbcurse/extras/widgets/horizlist.rb +203 -0
  24. data/lib/rbcurse/extras/widgets/menutree.rb +63 -0
  25. data/lib/rbcurse/extras/widgets/multilinelabel.rb +142 -0
  26. data/lib/rbcurse/extras/widgets/rcomboedit.rb +256 -0
  27. data/lib/rbcurse/extras/widgets/rlink.rb.moved +27 -0
  28. data/lib/rbcurse/extras/widgets/rlistbox.rb +1247 -0
  29. data/lib/rbcurse/extras/widgets/rmenulink.rb.moved +21 -0
  30. data/lib/rbcurse/extras/widgets/rmulticontainer.rb +304 -0
  31. data/lib/rbcurse/extras/widgets/rmultisplit.rb +722 -0
  32. data/lib/rbcurse/extras/widgets/rmultitextview.rb +306 -0
  33. data/lib/rbcurse/extras/widgets/rpopupmenu.rb +755 -0
  34. data/lib/rbcurse/extras/widgets/rtable.rb +1758 -0
  35. data/lib/rbcurse/extras/widgets/rvimsplit.rb +800 -0
  36. data/lib/rbcurse/extras/widgets/table/tablecellrenderer.rb +86 -0
  37. data/lib/rbcurse/extras/widgets/table/tabledatecellrenderer.rb +98 -0
  38. metadata +94 -0
@@ -0,0 +1,40 @@
1
+ # Provides extended abilities to a table
2
+ # so user does not need to code it into his app.
3
+ # At the same time, i don't want to weigh down Table with too much functionality/
4
+ # I am putting in some stuff, so that table columns can be resized, using multipliers.
5
+ # That allows us to redistribute the space taken or released across rows.
6
+ # Other options: dd, C, . (repeat) and how about range operations
7
+ #
8
+ module TableExtended
9
+
10
+ ##
11
+ # increase the focused column
12
+ # If no size passed, then use numeric multiplier, else 1
13
+ # Typically, one would bind a key such as + to this method
14
+ # e.g. atable.bind_key(?+) { atable.increase_column ; }
15
+ # See examples/viewtodo.rb for usage
16
+ def increase_column num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
17
+
18
+ acolumn = column focussed_col()
19
+ #num = $multiplier || 1
20
+ $multiplier = 0
21
+ w = acolumn.width + num
22
+ acolumn.width w
23
+ #atable.table_structure_changed
24
+ end
25
+ # decrease the focused column
26
+ # If no size passed, then use numeric multiplier, else 1
27
+ # Typically, one would bind a key such as - to this method
28
+ def decrease_column num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
29
+ acolumn = column focussed_col()
30
+ w = acolumn.width - num
31
+ $multiplier = 0
32
+ if w > 3
33
+ acolumn.width w
34
+ #atable.table_structure_changed
35
+ end
36
+ end
37
+
38
+
39
+
40
+ end
@@ -0,0 +1,203 @@
1
+ require 'rbcurse'
2
+
3
+ # This is a horizontal scroller, to scroll a list of options much like
4
+ # vim often does on the statusline. I'd like to use it for scrolling
5
+ # menus or buttons like on TabbedPanes to avoid another Form.
6
+
7
+ # You may bind to the ENTER_ROW event to chagne some data elsewhere,
8
+ # or the PRESS event. In this case, PRESS will refer to pressing the
9
+ # space bar or ENTER. There is <em>no</em> LIST_SELECTION event for that.
10
+
11
+
12
+
13
+ module RubyCurses
14
+
15
+ # Horizontal list scrolling and selection.
16
+ #
17
+ # == Example
18
+ # require 'rbcurse/extras/widgets/horizlist'
19
+ # require 'fileutils'
20
+ # l = HorizList.new @form, :row => 5, :col => 5, :width => 80
21
+ # list = Dir.glob("*")
22
+ # l.list(list)
23
+
24
+ class HorizList < Widget
25
+
26
+ def initialize form, config={}, &block
27
+ super
28
+ @_events.push(*[:ENTER_ROW, :LEAVE_ROW, :PRESS])
29
+ @focusable = true
30
+ init_vars
31
+ @list = []
32
+ @toprow = 0
33
+
34
+ # last printed index
35
+ @last_index = 0
36
+
37
+ # item on which cursor is
38
+ @current_index = 0
39
+ end
40
+ def init_vars
41
+ end
42
+ # alias :text :getvalue # NEXT VERSION
43
+
44
+ def map_keys
45
+ @keys_mapped = true
46
+ bind_keys([KEY_RIGHT, ?l, ?.], :next_item)
47
+ bind_keys([KEY_LEFT, ?h,?,], :previous_item)
48
+ bind_keys([10,13,32]){ fire_action_event }
49
+ bind_keys([?\M-l,?>, KEY_DOWN], :scroll_right)
50
+ bind_keys([?\M-h,?<, KEY_UP], :scroll_left)
51
+ end
52
+ def list(strings)
53
+ @list = strings
54
+ end
55
+ def add item
56
+ @list << item
57
+ end
58
+ def repaint
59
+ return unless @repaint_required
60
+ @window ||= @form.window
61
+ $log.debug "XXX:HORIZ REPAINT Ci #{@current_index}, TR #{@toprow} "
62
+ $status_message.value = " #{@current_index}, TR #{@toprow} "
63
+ @window.printstring @row, @col, " "* @width, @color_pair || $reversecolor
64
+ c = @col + 1
65
+ t = @toprow
66
+ @list.each_with_index { |e, i|
67
+ next if i < t # sucks for large lists
68
+ break if c + e.length >= @width + @col
69
+ att = @attrib || FFI::NCurses::A_NORMAL
70
+ if i == @current_index
71
+ att = FFI::NCurses::A_REVERSE if i == @current_index
72
+ acolor = @focussed_color_pair || get_color($datacolor,'green', 'white')
73
+ else
74
+ acolor = @color_pair
75
+ end
76
+ @window.printstring @row, c, e, acolor || $reversecolor, att
77
+ c += e.length + 2
78
+ @last_index = i
79
+ break if c >= @width + @col
80
+ }
81
+ @repaint_required = false
82
+ end
83
+ def handle_key ch
84
+ map_keys unless @keys_mapped
85
+ ret = process_key ch, self
86
+ @multiplier = 0
87
+ return :UNHANDLED if ret == :UNHANDLED
88
+ end
89
+ def previous_item num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
90
+
91
+ return :NO_PREVIOUS_ROW if @current_index == 0
92
+ @old_toprow = @toprow
93
+ @oldrow = @current_index
94
+ @current_index -= num
95
+ @current_index = 0 if @current_index < 0
96
+ bounds_check
97
+ $multiplier = 0
98
+ if @current_index < @toprow
99
+ @toprow = @current_index
100
+ end
101
+ @toprow = 0 if @toprow < 0
102
+ @repaint_required = true
103
+ end
104
+ def next_item num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
105
+ rc = row_count
106
+ return :NO_NEXT_ROW if @current_index == rc-1 # changed 2011-10-5 so process can do something
107
+ @old_toprow = @toprow
108
+ @oldrow = @current_index
109
+ @current_index += num
110
+ @current_index = rc - 1 if @current_index >= rc
111
+ @toprow = @current_index if @current_index > @last_index
112
+ bounds_check
113
+ $multiplier = 0
114
+ @repaint_required = true
115
+ end
116
+ def scroll_right
117
+ rc = row_count
118
+ return :NO_NEXT_ROW if @current_index == rc-1 # changed 2011-10-5 so process can do something
119
+ @old_toprow = @toprow
120
+ @oldrow = @current_index
121
+
122
+ @current_index = @last_index + 1
123
+
124
+ @current_index = rc - 1 if @current_index >= rc
125
+ @toprow = @current_index if @current_index > @last_index
126
+ bounds_check
127
+ $multiplier = 0
128
+ @repaint_required = true
129
+ end
130
+ def scroll_left
131
+ return :NO_PREVIOUS_ROW if @current_index == 0
132
+ @old_toprow = @toprow
133
+ @oldrow = @current_index
134
+ @current_index = @toprow - 4
135
+ @current_index = 0 if @current_index < 0
136
+ bounds_check
137
+ $multiplier = 0
138
+ if @current_index < @toprow
139
+ @toprow = @current_index
140
+ end
141
+ @toprow = 0 if @toprow < 0
142
+ @repaint_required = true
143
+ end
144
+ def row_count; @list.size; end
145
+ def bounds_check
146
+ @row_changed = false
147
+ if @oldrow != @current_index
148
+ on_leave_row @oldrow if respond_to? :on_leave_row # to be defined by widget that has included this
149
+ on_enter_row @current_index if respond_to? :on_enter_row # to be defined by widget that has included this
150
+ set_form_row
151
+ @row_changed = true
152
+ end
153
+ if @old_toprow != @toprow # only if scrolling has happened should we repaint
154
+ @repaint_required = true
155
+ @widget_scrolled = true
156
+ end
157
+ end
158
+ def on_enter
159
+ if @list.nil? || @list.size == 0
160
+ Ncurses.beep
161
+ return :UNHANDLED
162
+ end
163
+ super
164
+ on_enter_row @current_index
165
+ set_form_row
166
+ true
167
+ end
168
+ def on_enter_row arow
169
+ fire_handler :ENTER_ROW, self
170
+ @repaint_required = true
171
+ end
172
+ def on_leave_row arow
173
+ fire_handler :LEAVE_ROW, self
174
+ end
175
+ def fire_action_event
176
+ require 'rbcurse/core/include/ractionevent'
177
+ fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
178
+ end
179
+ def current_value
180
+ @list[@current_index]
181
+ end
182
+ alias :text :current_value
183
+ ##
184
+ end # class
185
+ end # module
186
+ if __FILE__ == $PROGRAM_NAME
187
+ require 'rbcurse/core/util/app'
188
+
189
+ App.new do
190
+ require 'rbcurse/extras/widgets/horizlist'
191
+ require 'fileutils'
192
+ l = HorizList.new @form, :row => 5, :col => 5, :width => 80
193
+ list = Dir.glob("*")
194
+ l.list(list)
195
+ l.bind(:PRESS){ |eve| alert "You pressed #{eve.text} " }
196
+ sl = status_line
197
+ sl.command do
198
+ " Status: #{$status_message} "
199
+ end
200
+ end
201
+
202
+
203
+ end
@@ -0,0 +1,63 @@
1
+ module RubyCurses
2
+ # Create a simple tree-ish structure.
3
+ # Each node is not a tree, only submenus are trees
4
+ # Others contain a hash with menu character and code
5
+ # Typically the code is not a method symbol, it is to be
6
+ # used to decode a description or method symbol from anoterh hash
7
+ # @usage
8
+ # menu = MenuTree.new "Main", { c: :goprev, d: :gonext, e: :gonext, s: :submenu }
9
+ # menu.submenu :s, "submenu", {a: :next1, b: :next2, f: :next3 }
10
+ # puts menu.hash
11
+ # puts "each ..."
12
+ # menu.each { |e| puts e }
13
+ # menu.each_pair { |e, v| puts "#{e} #{v}" }
14
+ # puts " -- :c -- "
15
+ # puts menu[:c]
16
+ # puts " -- :s -- "
17
+ # puts menu[:s].children
18
+ class MenuTree
19
+ attr_reader :value
20
+ def initialize value, hash = {}
21
+ @value = [value, hash]
22
+ end
23
+ def << kv
24
+ @value[1][kv[0]] = kv[1]
25
+ end
26
+ def hash
27
+ @value[1]
28
+ end
29
+ alias :children :hash
30
+ def push hsh
31
+ hash().merge hsh
32
+ end
33
+ def [](x)
34
+ hash()[x]
35
+ end
36
+ def []=(x,y)
37
+ hash()[x] = y
38
+ end
39
+ def submenu key, value, hash = {}
40
+ m = MenuTree.new value, hash
41
+ #hash()[key] = [value, hash]
42
+ hash()[key] = m
43
+ end
44
+ def each
45
+ hash().keys.each { |e| yield e }
46
+ end
47
+ def each_pair
48
+ hash().each_pair { |name, val| yield name, val }
49
+ end
50
+ end
51
+ end
52
+ if __FILE__ == $PROGRAM_NAME
53
+ menu = RubyCurses::MenuTree.new "Main", { c: :goprev, d: :gonext, e: :gonext, s: :submenu }
54
+ menu.submenu :s, "submenu", {a: :next1, b: :next2, f: :next3 }
55
+ puts menu.hash
56
+ puts "each ..."
57
+ menu.each { |e| puts e }
58
+ menu.each_pair { |e, v| puts "#{e} #{v}" }
59
+ puts " -- :c -- "
60
+ puts menu[:c]
61
+ puts " -- :s -- "
62
+ puts menu[:s].children
63
+ end
@@ -0,0 +1,142 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: multilinelabel.rb
3
+ # Description: Prints a label on the screen.
4
+ # This is the original label that was present in rwidgets.rb
5
+ # It allowed for multiple lines. I am simplifying that to a simple
6
+ # single line label.
7
+ # I am basically moving multiline labels out of hte core package
8
+ # Author: rkumar http://github.com/rkumar/rbcurse/
9
+ # Date: 2011-11-12 - 12:04
10
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
11
+ # Last update: 2011-11-12 - 12:05
12
+ # ----------------------------------------------------------------------------- #
13
+ #
14
+ module RubyCurses
15
+
16
+ # print static text on a form, allowing for text to be wrapped.
17
+ #
18
+ class MultiLineLabel < Widget
19
+ dsl_accessor :mnemonic # keyboard focus is passed to buddy based on this key (ALT mask)
20
+
21
+ # justify required a display length, esp if center.
22
+ dsl_property :justify #:right, :left, :center
23
+ dsl_property :display_length #please give this to ensure the we only print this much
24
+ #dsl_property :height #if you want a multiline label. already added to widget
25
+ # for consistency with others 2011-11-5
26
+ alias :width :display_length
27
+ alias :width= :display_length=
28
+
29
+ def initialize form, config={}, &block
30
+
31
+ # this crap was used in position_label, find another way. where is it used ?
32
+ #@row = config.fetch("row",-1) # why on earth this monstrosity ? 2011-11-5
33
+ #@col = config.fetch("col",-1)
34
+ #@bgcolor = config.fetch("bgcolor", $def_bg_color)
35
+ #@color = config.fetch("color", $def_fg_color)
36
+ @text = config.fetch("text", "NOTFOUND")
37
+ @editable = false
38
+ @focusable = false
39
+ super
40
+ @justify ||= :left
41
+ @name ||= @text
42
+ @repaint_required = true
43
+ end
44
+ #
45
+ # get the value for the label
46
+ def getvalue
47
+ @text_variable && @text_variable.value || @text
48
+ end
49
+ def label_for field
50
+ @label_for = field
51
+ #$log.debug " label for: #{@label_for}"
52
+ if @form
53
+ bind_hotkey
54
+ else
55
+ @when_form ||= []
56
+ @when_form << lambda { bind_hotkey }
57
+ end
58
+ end
59
+
60
+ ##
61
+ # for a button, fire it when label invoked without changing focus
62
+ # for other widgets, attempt to change focus to that field
63
+ def bind_hotkey
64
+ if !@mnemonic.nil?
65
+ ch = @mnemonic.downcase()[0].ord ## 1.9 DONE
66
+ # meta key
67
+ mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0)) ## 1.9
68
+ if @label_for.is_a? RubyCurses::Button and @label_for.respond_to? :fire
69
+ @form.bind_key(mch, @label_for) { |_form, _butt| _butt.fire }
70
+ else
71
+ $log.debug " bind_hotkey label for: #{@label_for}"
72
+ @form.bind_key(mch, @label_for) { |_form, _field| _field.focus }
73
+ end
74
+ end
75
+ end
76
+
77
+ ##
78
+ # XXX need to move wrapping etc up and done once.
79
+ def repaint
80
+ return unless @repaint_required
81
+ raise "Label row or col nil #{@row} , #{@col}, #{@text} " if @row.nil? || @col.nil?
82
+ r,c = rowcol
83
+
84
+ @bgcolor ||= $def_bg_color
85
+ @color ||= $def_fg_color
86
+ # value often nil so putting blank, but usually some application error
87
+ value = getvalue_for_paint || ""
88
+ lablist = []
89
+ # trying out array values 2011-10-16 more for messageboxes.
90
+ if value.is_a? Array
91
+ lablist = text
92
+ @height = text.size
93
+ elsif @height && @height > 1
94
+ lablist = wrap_text(value, @display_length).split("\n")
95
+ else
96
+ # ensure we do not exceed
97
+ if !@display_length.nil?
98
+ if value.length > @display_length
99
+ value = value[0..@display_length-1]
100
+ end
101
+ end
102
+ lablist << value
103
+ end
104
+ len = @display_length || value.length
105
+ acolor = get_color $datacolor
106
+ $log.debug "label :#{@text}, #{value}, r #{r}, c #{c} col= #{@color}, #{@bgcolor} acolor #{acolor} j:#{@justify} dlL: #{@display_length} "
107
+ firstrow = r
108
+ _height = @height || 1
109
+ str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
110
+ # loop added for labels that are wrapped.
111
+ # TODO clear separately since value can change in status like labels
112
+
113
+ @graphic = @form.window if @graphic.nil? ## HACK messagebox givig this in repaint, 423 not working ??
114
+ 0.upto(_height-1) { |i|
115
+ @graphic.printstring r+i, c, " " * len , acolor,@attr
116
+ }
117
+ lablist.each_with_index do |_value, ix|
118
+ break if ix >= _height
119
+ if @justify.to_sym == :center
120
+ padding = (@display_length - _value.length)/2
121
+ _value = " "*padding + _value + " "*padding # so its cleared if we change it midway
122
+ end
123
+ @graphic.printstring r, c, str % [len, _value], acolor,@attr
124
+ r += 1
125
+ end
126
+ if !@mnemonic.nil?
127
+ ulindex = value.index(@mnemonic) || value.index(@mnemonic.swapcase)
128
+ @graphic.mvchgat(y=firstrow, x=c+ulindex, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, acolor, nil)
129
+ end
130
+ #@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, color, nil)
131
+ @repaint_required = false
132
+ end
133
+ # Added 2011-10-22 to prevent some naive components from putting focus here.
134
+ def on_enter
135
+ raise "Cannot enter Label"
136
+ end
137
+ def on_leave
138
+ raise "Cannot leave Label"
139
+ end
140
+ # ADD HERE LABEL
141
+ end # class
142
+ end # module