rbcurse 0.1.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.
- data/CHANGELOG +1570 -0
- data/History.txt +6 -0
- data/Manifest.txt +54 -0
- data/README.txt +304 -0
- data/Rakefile +28 -0
- data/examples/qdfilechooser.rb +68 -0
- data/examples/rfe.rb +853 -0
- data/examples/rfe_renderer.rb +69 -0
- data/examples/test1.rb +242 -0
- data/examples/test2.rb +498 -0
- data/examples/testcombo.rb +95 -0
- data/examples/testkeypress.rb +61 -0
- data/examples/testmenu.rb +105 -0
- data/examples/testtable.rb +266 -0
- data/examples/testtabp.rb +106 -0
- data/examples/testtodo.rb +532 -0
- data/examples/viewtodo.rb +512 -0
- data/lib/rbcurse/action.rb +31 -0
- data/lib/rbcurse/applicationheader.rb +57 -0
- data/lib/rbcurse/celleditor.rb +120 -0
- data/lib/rbcurse/checkboxcellrenderer.rb +69 -0
- data/lib/rbcurse/colormap.rb +133 -0
- data/lib/rbcurse/comboboxcellrenderer.rb +45 -0
- data/lib/rbcurse/defaultlistselectionmodel.rb +49 -0
- data/lib/rbcurse/keylabelprinter.rb +143 -0
- data/lib/rbcurse/listcellrenderer.rb +99 -0
- data/lib/rbcurse/listkeys.rb +33 -0
- data/lib/rbcurse/listscrollable.rb +216 -0
- data/lib/rbcurse/listselectable.rb +67 -0
- data/lib/rbcurse/mapper.rb +108 -0
- data/lib/rbcurse/orderedhash.rb +77 -0
- data/lib/rbcurse/rcombo.rb +243 -0
- data/lib/rbcurse/rdialogs.rb +183 -0
- data/lib/rbcurse/rform.rb +845 -0
- data/lib/rbcurse/rinputdataevent.rb +36 -0
- data/lib/rbcurse/rlistbox.rb +804 -0
- data/lib/rbcurse/rmenu.rb +666 -0
- data/lib/rbcurse/rmessagebox.rb +325 -0
- data/lib/rbcurse/rpopupmenu.rb +754 -0
- data/lib/rbcurse/rtabbedpane.rb +259 -0
- data/lib/rbcurse/rtable.rb +1296 -0
- data/lib/rbcurse/rtextarea.rb +673 -0
- data/lib/rbcurse/rtextview.rb +335 -0
- data/lib/rbcurse/rwidget.rb +1731 -0
- data/lib/rbcurse/scrollable.rb +301 -0
- data/lib/rbcurse/selectable.rb +94 -0
- data/lib/rbcurse/table/tablecellrenderer.rb +85 -0
- data/lib/rbcurse/table/tabledatecellrenderer.rb +102 -0
- data/lib/rbcurse.rb +7 -0
- data/lib/ver/keyboard.rb +150 -0
- data/lib/ver/keyboard2.rb +170 -0
- data/lib/ver/ncurses.rb +102 -0
- data/lib/ver/window.rb +369 -0
- data/test/test_rbcurse.rb +0 -0
- metadata +118 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ncurses'
|
3
|
+
require 'logger'
|
4
|
+
#require 'lib/rbcurse/rwidget'
|
5
|
+
|
6
|
+
|
7
|
+
##
|
8
|
+
# This file gives us a mean of using a component as an editor in a list or later table.
|
9
|
+
# The component is created once and used with each row.
|
10
|
+
# It does not really have a form associated with it, although we do set a form
|
11
|
+
# so it can display itself. Otherwise it is not added to the forms widget list, so the
|
12
|
+
# form has no idea tha this widget exists.
|
13
|
+
#
|
14
|
+
# Tested with Field, combo and checkbox
|
15
|
+
# TODO test and integrate with tables.
|
16
|
+
#
|
17
|
+
module RubyCurses
|
18
|
+
class CellEditor
|
19
|
+
include ConfigSetup
|
20
|
+
include RubyCurses::Utils
|
21
|
+
|
22
|
+
def initialize component, config={}, &block
|
23
|
+
@component = component
|
24
|
+
s = @component.class.to_s.downcase()
|
25
|
+
s.slice!("rubycurses::")
|
26
|
+
@_class = s.to_sym
|
27
|
+
#$log.debug " CELL EIDOTR got #{@_class}"
|
28
|
+
config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
|
29
|
+
instance_eval &block if block_given?
|
30
|
+
end
|
31
|
+
def getvalue
|
32
|
+
case @_class
|
33
|
+
when :field
|
34
|
+
return field_getvalue
|
35
|
+
when :checkbox
|
36
|
+
return checkbox_getvalue
|
37
|
+
when :combobox
|
38
|
+
return combobox_getvalue
|
39
|
+
else
|
40
|
+
raise "Unknown class #{@_class} in CellEditor getv"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# maybe this should check valid (on_leave) and throw exception
|
44
|
+
def field_getvalue
|
45
|
+
#@component.on_leave # throws exception! Added 2009-01-17 00:47
|
46
|
+
@component.init_vars # 2009-01-18 01:13 should not carry over to next row curpos and pcol
|
47
|
+
return @component.getvalue
|
48
|
+
end
|
49
|
+
def checkbox_getvalue
|
50
|
+
@component.getvalue
|
51
|
+
end
|
52
|
+
def combobox_getvalue
|
53
|
+
#@component.on_leave # added 2009-01-19 12:12
|
54
|
+
@component.getvalue
|
55
|
+
#@component.selected_item
|
56
|
+
end
|
57
|
+
def setvalue value
|
58
|
+
case @_class
|
59
|
+
when :field
|
60
|
+
@component.set_buffer value
|
61
|
+
when :checkbox
|
62
|
+
@component.checked value
|
63
|
+
when :combobox
|
64
|
+
@component.set_buffer value
|
65
|
+
#index = @component.list.index value
|
66
|
+
#@component.current_index = index
|
67
|
+
else
|
68
|
+
raise "Unknown class #{@_class} in CellEditor setv"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
def component
|
72
|
+
@component
|
73
|
+
end
|
74
|
+
# should be called from on_leave_cell of table, but is beng called from editing_stopped FIXME
|
75
|
+
def on_leave row, col
|
76
|
+
f = @component
|
77
|
+
f.on_leave
|
78
|
+
if f.respond_to? :editable and f.modified?
|
79
|
+
$log.debug " Table about to fire CHANGED for #{f} "
|
80
|
+
f.fire_handler(:CHANGED, f)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
def prepare_editor parent, row, col, value
|
84
|
+
#value = value.dup if value.respond_to? :dup
|
85
|
+
value = value.dup rescue value
|
86
|
+
setvalue value #.dup
|
87
|
+
widget = component()
|
88
|
+
widget.row = row
|
89
|
+
widget.col = col
|
90
|
+
# unfortunately 2009-01-11 19:47 combo boxes editable allows changing value
|
91
|
+
# FIXME so combo's can be editable, but no new value added
|
92
|
+
if @_class == :combobox
|
93
|
+
widget.editable = false if widget.respond_to? :editable # chb's don't ???
|
94
|
+
else
|
95
|
+
widget.editable = true if widget.respond_to? :editable # chb's don't ???
|
96
|
+
end
|
97
|
+
widget.focusable = true
|
98
|
+
widget.visible = true
|
99
|
+
widget.form = parent.form
|
100
|
+
#$log.debug " prepare editor value #{widget.display_length} displlen #{widget.maxlen}"
|
101
|
+
#widget.display_length = widget.display_length -1
|
102
|
+
widget.bgcolor = 'yellow'
|
103
|
+
widget.color = 'black'
|
104
|
+
widget.on_enter
|
105
|
+
#widget.attr = Ncurses::A_REVERSE | Ncurses::A_BOLD
|
106
|
+
#$log.debug " prepare editor value #{value} : fr:#{row}, fc:#{col}"
|
107
|
+
end
|
108
|
+
#This may not really be necessary since we paint the cell editor only if editing is on
|
109
|
+
def cancel_editor
|
110
|
+
widget = component()
|
111
|
+
# NOOO THIS IS CALLED BY CANCEL AND STOP
|
112
|
+
# somehow we need to ensure that if on_leave fails you can't get out. Here its a bit late
|
113
|
+
# i think FIXME TODO
|
114
|
+
#widget.on_leave # call so any triggers or validations can fire
|
115
|
+
widget.focusable = false
|
116
|
+
widget.visible = false
|
117
|
+
widget.attr = Ncurses::A_REVERSE
|
118
|
+
end
|
119
|
+
end # class
|
120
|
+
end # module
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ncurses'
|
3
|
+
require 'logger'
|
4
|
+
require 'rbcurse/listcellrenderer'
|
5
|
+
module RubyCurses
|
6
|
+
|
7
|
+
##
|
8
|
+
# This is a basic list cell renderer that will render the to_s value of anything.
|
9
|
+
# Using alignment one can use for numbers too.
|
10
|
+
# However, for booleans it will print true and false. If editing, you may want checkboxes
|
11
|
+
class CheckBoxCellRenderer < ListCellRenderer
|
12
|
+
include ConfigSetup
|
13
|
+
include RubyCurses::Utils
|
14
|
+
dsl_accessor :justify # :right, :left, :center # added 2008-12-22 19:02
|
15
|
+
dsl_accessor :display_length # please give this to ensure the we only print this much
|
16
|
+
dsl_accessor :height # if you want a multiline label.
|
17
|
+
dsl_accessor :text # text of label
|
18
|
+
dsl_accessor :value # text of label
|
19
|
+
dsl_accessor :color, :bgcolor
|
20
|
+
dsl_accessor :row, :col
|
21
|
+
dsl_accessor :parent #usuall the table to get colors and other default info
|
22
|
+
dsl_accessor :surround_chars
|
23
|
+
|
24
|
+
def initialize boolean=nil, config={}, &block
|
25
|
+
@value = boolean
|
26
|
+
@text = "" # what if someone wants to show a label later. ??? XXX
|
27
|
+
@editable = false
|
28
|
+
@focusable = false
|
29
|
+
config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
|
30
|
+
instance_eval &block if block_given?
|
31
|
+
init_vars
|
32
|
+
end
|
33
|
+
def init_vars
|
34
|
+
@justify ||= :left
|
35
|
+
@display_length ||= 5
|
36
|
+
@surround_chars = ['[',']']
|
37
|
+
end
|
38
|
+
def getvalue
|
39
|
+
@value
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
#
|
44
|
+
def repaint graphic, r=@row,c=@col, row_index=-1,value=@value, focussed=false, selected=false
|
45
|
+
#$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor= #{acolor} j:#{@justify} dlL: #{@display_length} "
|
46
|
+
|
47
|
+
prepare_default_colors focussed, selected
|
48
|
+
|
49
|
+
buttontext = value ? "X" : " "
|
50
|
+
# HOW TO DO THE TEXT ??? XXX
|
51
|
+
# the space in dtext next line is a cheat, to clear off the space that the
|
52
|
+
# editor is leaving.
|
53
|
+
dtext = " " #@display_length.nil? ? @text : "%-*s" % [@display_length, @text]
|
54
|
+
if @align_right
|
55
|
+
#@text_offset = 0
|
56
|
+
#@col_offset = dtext.length + @surround_chars[0].length + 1
|
57
|
+
str = "#{dtext} " + @surround_chars[0] + buttontext + @surround_chars[1]
|
58
|
+
else
|
59
|
+
pretext = @surround_chars[0] + buttontext + @surround_chars[1]
|
60
|
+
#@text_offset = pretext.length + 1
|
61
|
+
#@col_offset = @surround_chars[0].length
|
62
|
+
#@surround_chars[0] + buttontext + @surround_chars[1] + " #{@text}"
|
63
|
+
str = pretext + " #{dtext}"
|
64
|
+
end
|
65
|
+
graphic.printstring r, c, str, @color_pair,@attr
|
66
|
+
end
|
67
|
+
# ADD HERE
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ver/ncurses'
|
3
|
+
module ColorMap
|
4
|
+
## private
|
5
|
+
# returns a color constant for a human color string
|
6
|
+
def ColorMap.get_color_const colorstring
|
7
|
+
Ncurses.const_get "COLOR_#{colorstring.upcase}"
|
8
|
+
end
|
9
|
+
## private
|
10
|
+
# creates a new color pair, puts in color map and returns color_pair
|
11
|
+
# number
|
12
|
+
def ColorMap.install_color fgc, bgc
|
13
|
+
# $log.debug " install_color found #{fgc} #{@bgc} "
|
14
|
+
@color_id += 1
|
15
|
+
fg = ColorMap.get_color_const fgc
|
16
|
+
bg = ColorMap.get_color_const bgc
|
17
|
+
Ncurses.init_pair(@color_id, fg, bg);
|
18
|
+
$color_map[[fgc, bgc]] = @color_id
|
19
|
+
return @color_id
|
20
|
+
end
|
21
|
+
## public
|
22
|
+
# returns a color_pair for a given foreground and background color
|
23
|
+
def ColorMap.get_color fgc, bgc=$def_bg_color
|
24
|
+
if $color_map.include? [fgc, bgc]
|
25
|
+
# $log.debug " get_color found #{fgc} #{@bgc} "
|
26
|
+
return $color_map[[fgc, bgc]]
|
27
|
+
else
|
28
|
+
# $log.debug " get_color NOT found #{fgc} #{@bgc} "
|
29
|
+
return ColorMap.install_color fgc, bgc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def ColorMap.colors
|
33
|
+
@@colors
|
34
|
+
end
|
35
|
+
|
36
|
+
## public
|
37
|
+
# setup color map at start of application
|
38
|
+
def ColorMap.setup
|
39
|
+
@color_id = 0
|
40
|
+
$color_map = {}
|
41
|
+
Ncurses.start_color();
|
42
|
+
# Initialize few color pairs
|
43
|
+
$def_fg_color = "white" # pls set these 2 for your application
|
44
|
+
$def_bg_color = "black"
|
45
|
+
#COLORS = [COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
|
46
|
+
# COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE]
|
47
|
+
@@colors = %w[black red green yellow blue magenta cyan white]
|
48
|
+
|
49
|
+
# make foreground colors
|
50
|
+
bg = ColorMap.get_color_const $def_bg_color
|
51
|
+
@@colors[0...@@colors.size].each_with_index do |color, i|
|
52
|
+
next if color == $def_bg_color
|
53
|
+
ColorMap.install_color color, $def_bg_color
|
54
|
+
end
|
55
|
+
$reversecolor = ColorMap.get_color $def_bg_color, $def_fg_color
|
56
|
+
$popupcolor = ColorMap.get_color 'cyan', $def_fg_color
|
57
|
+
|
58
|
+
$errorcolor = ColorMap.get_color 'white', 'red'
|
59
|
+
$promptcolor = $selectedcolor = ColorMap.get_color('yellow', 'red')
|
60
|
+
$normalcolor = $datacolor = ColorMap.get_color('white', 'black')
|
61
|
+
$bottomcolor = $topcolor = ColorMap.get_color('white', 'blue')
|
62
|
+
|
63
|
+
# $log.debug " colormap SETUP: #{$datacolor} #{$reversecolor} "
|
64
|
+
end
|
65
|
+
|
66
|
+
end # modul
|
67
|
+
if $0 == __FILE__
|
68
|
+
require 'logger'
|
69
|
+
require 'lib/ver/window'
|
70
|
+
include Ncurses
|
71
|
+
include ColorMap
|
72
|
+
# Initialize curses
|
73
|
+
begin
|
74
|
+
VER::start_ncurses
|
75
|
+
@window = VER::Window.root_window
|
76
|
+
$log = Logger.new("view.log")
|
77
|
+
$log.level = Logger::DEBUG
|
78
|
+
ColorMap.setup
|
79
|
+
|
80
|
+
# Create the window to be associated with the form
|
81
|
+
# Un post form and free the memory
|
82
|
+
|
83
|
+
catch(:close) do
|
84
|
+
# $log.debug "START ---------"
|
85
|
+
# need to pass a form, not window.
|
86
|
+
r = 1; c = 2; i=0
|
87
|
+
attr = Ncurses::A_NORMAL
|
88
|
+
@window.printstring 20, c, "press 0-9 to change BG color, F1/q to quit. r-everse, n-ormal,b-old ", ColorMap.get_color('white')
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
while((ch = @window.getchar()) != KEY_F1 )
|
93
|
+
next if ch == -1
|
94
|
+
break if ch == ?q
|
95
|
+
case ch
|
96
|
+
when ?r
|
97
|
+
attr |= Ncurses::A_REVERSE
|
98
|
+
when ?b
|
99
|
+
attr |= Ncurses::A_BOLD
|
100
|
+
when ?n
|
101
|
+
attr = Ncurses::A_NORMAL
|
102
|
+
when ?u
|
103
|
+
attr |= Ncurses::A_UNDERLINE
|
104
|
+
else
|
105
|
+
i = ch.chr.to_i
|
106
|
+
i = 1 if i > ColorMap::colors.length-1
|
107
|
+
end
|
108
|
+
bg = ColorMap::colors[i]
|
109
|
+
@@colors = %w[black red green yellow blue magenta cyan white]
|
110
|
+
@window.printstring r, c, "%-40s" % "red #{bg} ", ColorMap.get_color('red',bg) , attr
|
111
|
+
@window.printstring 2, c, "%-40s" % "blue #{bg} ", ColorMap.get_color('blue',bg) , attr
|
112
|
+
@window.printstring 3, c, "%-40s" % "white #{bg} ", ColorMap.get_color('white',bg) , attr
|
113
|
+
@window.printstring 4, c, "%-40s" % "green #{bg} ", ColorMap.get_color('green',bg) , attr
|
114
|
+
@window.printstring 5, c, "%-40s" % "cyan #{bg} ", ColorMap.get_color('cyan',bg) , attr
|
115
|
+
@window.printstring 6, c, "%-40s" % "magenta #{bg} ", ColorMap.get_color('magenta',bg) , attr
|
116
|
+
@window.printstring 7, c, "black #{bg} ", ColorMap.get_color('black',bg) , attr
|
117
|
+
@window.wrefresh
|
118
|
+
end
|
119
|
+
# VER::Keyboard.focus = tp
|
120
|
+
end
|
121
|
+
rescue => ex
|
122
|
+
ensure
|
123
|
+
# @panel = @window.panel if @window
|
124
|
+
# Ncurses::Panel.del_panel(@panel) if !@panel.nil?
|
125
|
+
# @window.delwin if !@window.nil?
|
126
|
+
@window.destroy unless @window.nil?
|
127
|
+
VER::stop_ncurses
|
128
|
+
p ex if ex
|
129
|
+
p(ex.backtrace.join("\n")) if ex
|
130
|
+
# $log.debug( ex) if ex
|
131
|
+
# $log.debug(ex.backtrace.join("\n")) if ex
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ncurses'
|
3
|
+
require 'logger'
|
4
|
+
#require 'lib/rbcurse/rwidget'
|
5
|
+
module RubyCurses
|
6
|
+
|
7
|
+
##
|
8
|
+
# This is a list cell renderer that will render combo boxes.
|
9
|
+
# Since a combo box extends a field therefore the repaint of field is used.
|
10
|
+
# In other words there is nothing much to do here.
|
11
|
+
#
|
12
|
+
class ComboBoxCellRenderer < ListCellRenderer
|
13
|
+
include ConfigSetup
|
14
|
+
include RubyCurses::Utils
|
15
|
+
dsl_accessor :justify # :right, :left, :center # added 2008-12-22 19:02
|
16
|
+
dsl_accessor :display_length # please give this to ensure the we only print this much
|
17
|
+
dsl_accessor :height # if you want a multiline label.
|
18
|
+
dsl_accessor :text # text of label
|
19
|
+
dsl_accessor :color, :bgcolor
|
20
|
+
dsl_accessor :row, :col
|
21
|
+
dsl_accessor :parent #usuall the table to get colors and other default info
|
22
|
+
|
23
|
+
def initialize text="", config={}, &block
|
24
|
+
@text = text
|
25
|
+
@editable = false
|
26
|
+
@focusable = false
|
27
|
+
config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
|
28
|
+
instance_eval &block if block_given?
|
29
|
+
init_vars
|
30
|
+
end
|
31
|
+
def init_vars
|
32
|
+
@justify ||= :left
|
33
|
+
@display_length ||= 10
|
34
|
+
end
|
35
|
+
## me thinks this is unused
|
36
|
+
def getvalue
|
37
|
+
raise "I think this is unused. comboboxcellrenderer line 36"
|
38
|
+
@text
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# ADD HERE
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RubyCurses
|
2
|
+
class DefaultListSelectionModel
|
3
|
+
include EventHandler
|
4
|
+
attr_accessor :selection_mode
|
5
|
+
attr_reader :anchor_selection_index
|
6
|
+
attr_reader :lead_selection_index
|
7
|
+
def initialize
|
8
|
+
@selected_indices=[]
|
9
|
+
@anchor_selection_index = -1
|
10
|
+
@lead_selection_index = -1
|
11
|
+
@selection_mode = :MULTIPLE
|
12
|
+
end
|
13
|
+
|
14
|
+
def clear_selection
|
15
|
+
@selected_indices=[]
|
16
|
+
end
|
17
|
+
def is_selected_index ix
|
18
|
+
@selected_indices.include? ix
|
19
|
+
end
|
20
|
+
def get_max_selection_index
|
21
|
+
@selected_indices[-1]
|
22
|
+
end
|
23
|
+
def get_min_selection_index
|
24
|
+
@selected_indices[0]
|
25
|
+
end
|
26
|
+
def get_selected_rows
|
27
|
+
@selected_indices
|
28
|
+
end
|
29
|
+
## TODO should go in sorted, and no dupes
|
30
|
+
def add_selection_interval ix0, ix1
|
31
|
+
if @selection_mode != :MULTIPLE
|
32
|
+
clear_selection
|
33
|
+
end
|
34
|
+
@anchor_selection_index = ix0
|
35
|
+
@lead_selection_index = ix1
|
36
|
+
ix0.upto(ix1) {|i| @selected_indices << i unless @selected_indices.include? i }
|
37
|
+
end
|
38
|
+
def remove_selection_interval ix0, ix1
|
39
|
+
@anchor_selection_index = ix0
|
40
|
+
@lead_selection_index = ix1
|
41
|
+
@selected_indices.delete_if {|x| x >= ix0 and x <= ix1}
|
42
|
+
end
|
43
|
+
def insert_index_interval ix0, len
|
44
|
+
@anchor_selection_index = ix0
|
45
|
+
@lead_selection_index = ix0+len
|
46
|
+
add_selection_interval @anchor_selection_index, @lead_selection_index
|
47
|
+
end
|
48
|
+
end # class DefaultListSelectionModel
|
49
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'rbcurse/rwidget'
|
2
|
+
include Ncurses
|
3
|
+
include RubyCurses
|
4
|
+
module RubyCurses
|
5
|
+
class KeyLabelPrinter < Widget
|
6
|
+
attr_reader :key_labels
|
7
|
+
dsl_property :mode
|
8
|
+
|
9
|
+
def initialize form, key_labels, config={}, &block
|
10
|
+
|
11
|
+
super form, config, &block
|
12
|
+
@mode ||= :normal
|
13
|
+
#@key_labels = key_labels
|
14
|
+
@key_hash = {}
|
15
|
+
@key_hash[@mode] = key_labels
|
16
|
+
@editable = false
|
17
|
+
@focusable = false
|
18
|
+
@cols ||= Ncurses.COLS-1
|
19
|
+
@row ||= Ncurses.LINES-3
|
20
|
+
@col ||= 0
|
21
|
+
@repaint_required = true
|
22
|
+
@footer_color_pair ||= $bottomcolor
|
23
|
+
@footer_mnemonic_color_pair ||= $reversecolor #2
|
24
|
+
end
|
25
|
+
def key_labels mode=@mode
|
26
|
+
@key_hash[mode]
|
27
|
+
end
|
28
|
+
# returns the keys as printed. these may or may not help
|
29
|
+
# in validation depedign on what you passed as zeroth index
|
30
|
+
def get_current_keys
|
31
|
+
a = []
|
32
|
+
@key_hash[@mode].each do |arr|
|
33
|
+
a << arr[0] unless arr.nil?
|
34
|
+
end
|
35
|
+
return a
|
36
|
+
end
|
37
|
+
def getvalue
|
38
|
+
@key_hash
|
39
|
+
end
|
40
|
+
def set_key_labels _key_labels, mode=:normal
|
41
|
+
@key_hash[mode] = _key_labels
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# XXX need to move wrapping etc up and done once.
|
46
|
+
def repaint
|
47
|
+
return unless @repaint_required
|
48
|
+
r,c = rowcol
|
49
|
+
print_key_labels(arr = key_labels(), mode=@mode)
|
50
|
+
@repaint_required = false
|
51
|
+
end
|
52
|
+
def append_key_label key, label, mode=@mode
|
53
|
+
@key_labels << [key, label] if !@key_labels.include? [key, label]
|
54
|
+
@repaint_required = true
|
55
|
+
end
|
56
|
+
def print_key_labels(arr = key_labels(), mode=@mode)
|
57
|
+
#return if !@show_key_labels # XXX
|
58
|
+
@win ||= @form.window
|
59
|
+
@padding = @cols / (arr.length/2)
|
60
|
+
posx = 0
|
61
|
+
even = []
|
62
|
+
odd = []
|
63
|
+
arr.each_index { |i|
|
64
|
+
if i % 2 == 0
|
65
|
+
#arr[i+1] = ['',''] if arr[i+1].nil?
|
66
|
+
nextarr = arr[i+1] || ['', '']
|
67
|
+
keyw = [arr[i][0].length, nextarr[0].length].max
|
68
|
+
labelw = [arr[i][1].length, nextarr[1].length].max
|
69
|
+
|
70
|
+
even << [ sprintf("%*s", keyw, arr[i][0]), sprintf("%-*s", labelw, arr[i][1]) ]
|
71
|
+
odd << [ sprintf("%*s", keyw, nextarr[0]), sprintf("%-*s", labelw, nextarr[1]) ]
|
72
|
+
#$log.debug("loop even: #{even.inspect}")
|
73
|
+
else
|
74
|
+
end
|
75
|
+
}
|
76
|
+
#$log.debug("even: #{even.inspect}")
|
77
|
+
#$log.debug("odd : #{odd.inspect}")
|
78
|
+
#posy = @barrow-1
|
79
|
+
posy = @row
|
80
|
+
print_key_labels_row(posy, posx, even)
|
81
|
+
posy = @row+1
|
82
|
+
print_key_labels_row(posy, posx, odd)
|
83
|
+
#@win.wrefresh # needed else secod row not shown after askchoice XXX
|
84
|
+
end
|
85
|
+
def print_key_labels_row(posy, posx, arr)
|
86
|
+
# FIXME: this logic of padding needs to take into account
|
87
|
+
# width of window
|
88
|
+
padding = 8
|
89
|
+
padding = 4 if arr.length > 5
|
90
|
+
padding = 2 if arr.length > 7
|
91
|
+
padding = 0 if arr.length > 9
|
92
|
+
#padding = @padding # XXX 2008-11-13 23:01
|
93
|
+
my_form_win = @win
|
94
|
+
@win.printstring(posy,0, "%-*s" % [@cols," "], @footer_color_pair, @attr)
|
95
|
+
arr.each do |kl|
|
96
|
+
key = kl[0]
|
97
|
+
lab = kl[1]
|
98
|
+
if key !="" # don't print that white blank space for fillers
|
99
|
+
color_pair= @footer_mnemonic_color_pair # $reversecolor #2
|
100
|
+
x = posx + (key.length - key.strip.length)
|
101
|
+
my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
|
102
|
+
my_form_win.mvprintw(posy, x, "%s" % kl[0].strip );
|
103
|
+
my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
|
104
|
+
end
|
105
|
+
color_pair=@footer_color_pair
|
106
|
+
posx = posx + kl[0].length
|
107
|
+
my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
|
108
|
+
|
109
|
+
#lab = sprintf(" %s %*s" , kl[1], padding, " ");
|
110
|
+
lab = sprintf(" %s %s" , kl[1], " "*padding);
|
111
|
+
my_form_win.mvprintw(posy, posx, lab)
|
112
|
+
my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
|
113
|
+
posx = posx + lab.length
|
114
|
+
end
|
115
|
+
end
|
116
|
+
##
|
117
|
+
# updates existing label with a new one.
|
118
|
+
# @return true if updated, else false
|
119
|
+
def update_application_key_label(display_code, new_display_code, text)
|
120
|
+
@repaint_required = true
|
121
|
+
labels = key_labels()
|
122
|
+
labels.each_index do |ix|
|
123
|
+
lab = labels[ix]
|
124
|
+
if lab[0] == display_code
|
125
|
+
labels[ix] = [new_display_code , text]
|
126
|
+
$log.debug("updated #{labels[ix]}")
|
127
|
+
return true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
return false
|
131
|
+
end
|
132
|
+
##
|
133
|
+
# inserts an application label at given index
|
134
|
+
# to add the key, use create_datakeys to add bindings
|
135
|
+
# remember to call restore_application_key_labels after updating/inserting
|
136
|
+
def insert_application_key_label(index, display_code, text)
|
137
|
+
@repaint_required = true
|
138
|
+
labels = key_labels()
|
139
|
+
labels.insert(index, [display_code , text] )
|
140
|
+
end
|
141
|
+
# ADD HERE KEYLABEL
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ncurses'
|
3
|
+
require 'logger'
|
4
|
+
require 'rbcurse/rwidget'
|
5
|
+
module RubyCurses
|
6
|
+
|
7
|
+
##
|
8
|
+
# This is a basic list cell renderer that will render the to_s value of anything.
|
9
|
+
# Using alignment one can use for numbers too.
|
10
|
+
# However, for booleans it will print true and false. If editing, you may want checkboxes
|
11
|
+
class ListCellRenderer
|
12
|
+
#include DSL
|
13
|
+
#include EventHandler
|
14
|
+
include RubyCurses::ConfigSetup
|
15
|
+
include RubyCurses::Utils
|
16
|
+
dsl_accessor :justify # :right, :left, :center # added 2008-12-22 19:02
|
17
|
+
dsl_accessor :display_length # please give this to ensure the we only print this much
|
18
|
+
dsl_accessor :height # if you want a multiline label.
|
19
|
+
dsl_accessor :text # text of label
|
20
|
+
dsl_accessor :color, :bgcolor
|
21
|
+
dsl_accessor :row, :col
|
22
|
+
dsl_accessor :parent #usuall the table to get colors and other default info
|
23
|
+
|
24
|
+
def initialize text="", config={}, &block
|
25
|
+
@text = text
|
26
|
+
@editable = false
|
27
|
+
@focusable = false
|
28
|
+
config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
|
29
|
+
instance_eval &block if block_given?
|
30
|
+
init_vars
|
31
|
+
end
|
32
|
+
def init_vars
|
33
|
+
@justify ||= :left
|
34
|
+
@display_length ||= 10
|
35
|
+
end
|
36
|
+
def getvalue
|
37
|
+
@text
|
38
|
+
end
|
39
|
+
##
|
40
|
+
# sets @color_pair and @attr
|
41
|
+
def prepare_default_colors focussed, selected
|
42
|
+
@color_pair = get_color $datacolor
|
43
|
+
#acolor =get_color $datacolor, @color || @parent.color, @bgcolor || @parent.bgcolor #unless @parent.nil?
|
44
|
+
@attr = @row_attr || Ncurses::A_NORMAL
|
45
|
+
##@row_attr = Ncurses::A_NORMAL # added 2009-02-04 18:35 since overriding in rfe
|
46
|
+
|
47
|
+
|
48
|
+
## determine bg and fg and attr
|
49
|
+
if selected
|
50
|
+
@attr = Ncurses::A_BOLD if selected
|
51
|
+
@color_pair =get_color $selectedcolor, @parent.selected_color, @parent.selected_bgcolor unless @parent.nil?
|
52
|
+
end
|
53
|
+
if focussed
|
54
|
+
@attr |= Ncurses::A_REVERSE
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
#
|
60
|
+
def repaint graphic, r=@row,c=@col, row_index=-1,value=@text, focussed=false, selected=false
|
61
|
+
#$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor= #{acolor} j:#{@justify} dlL: #{@display_length} "
|
62
|
+
|
63
|
+
prepare_default_colors focussed, selected
|
64
|
+
|
65
|
+
lablist = []
|
66
|
+
value=value.to_s # ??
|
67
|
+
if @height && @height > 1
|
68
|
+
lablist = wrap_text(value, @display_length).split("\n")
|
69
|
+
else
|
70
|
+
# ensure we do not exceed
|
71
|
+
if !@display_length.nil?
|
72
|
+
if value.length > @display_length
|
73
|
+
value = value[0..@display_length-1]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
lablist << value
|
77
|
+
end
|
78
|
+
len = @display_length || value.length
|
79
|
+
_height = @height || 1
|
80
|
+
str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
|
81
|
+
# loop added for labels that are wrapped.
|
82
|
+
# clear separately since value can change in status like labels
|
83
|
+
#len -= @left_margin
|
84
|
+
0.upto(_height-1) { |i|
|
85
|
+
graphic.printstring r+i, c, ( " " * len) , @color_pair,@attr
|
86
|
+
}
|
87
|
+
lablist.each_with_index do |_value, ix|
|
88
|
+
break if ix >= _height
|
89
|
+
if @justify.to_sym == :center
|
90
|
+
padding = (@display_length - _value.length)/2
|
91
|
+
_value = " "*padding + _value + " "*padding # so its cleared if we change it midway
|
92
|
+
end
|
93
|
+
graphic.printstring r, c, str % [len, _value], @color_pair,@attr
|
94
|
+
r += 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
# ADD HERE
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RubyCurses
|
2
|
+
module ListKeys
|
3
|
+
## Note: keeping variables gives the false feeling that one can change the var anytime.
|
4
|
+
# That was possible earlier, but now that i am binding the key at construction time
|
5
|
+
# any changes to the vars after construction won't have an effect.
|
6
|
+
def install_list_keys
|
7
|
+
@KEY_ROW_SELECTOR ||= ?\C-x
|
8
|
+
@KEY_GOTO_TOP ||= ?\M-0
|
9
|
+
@KEY_GOTO_BOTTOM ||= ?\M-9
|
10
|
+
@KEY_ASK_FIND_FORWARD ||= ?\M-f
|
11
|
+
@KEY_ASK_FIND_BACKWARD ||= ?\M-F
|
12
|
+
@KEY_FIND_NEXT ||= ?\M-g
|
13
|
+
@KEY_FIND_PREV ||= ?\M-G
|
14
|
+
@KEY_SCROLL_FORWARD ||= ?\C-n
|
15
|
+
@KEY_SCROLL_BACKWARD ||= ?\C-p
|
16
|
+
|
17
|
+
@KEY_CLEAR_SELECTION ||= ?\M-e
|
18
|
+
@KEY_PREV_SELECTION ||= ?\M-"
|
19
|
+
@KEY_NEXT_SELECTION ||= ?\M-'
|
20
|
+
|
21
|
+
=begin
|
22
|
+
bind_key(@KEY_ROW_SELECTOR) { toggle_row_selection }
|
23
|
+
bind_key(@KEY_GOTO_TOP) { goto_top }
|
24
|
+
bind_key(@KEY_GOTO_BOTTOM) { goto_bottom }
|
25
|
+
bind_key(@KEY_CLEAR_SELECTION) { clear_selection }
|
26
|
+
bind_key(@KEY_ASK_FIND_FORWARD) { ask_search_forward }
|
27
|
+
bind_key(@KEY_ASK_FIND_BACKWARD) { ask_search_backward }
|
28
|
+
bind_key(@KEY_FIND_NEXT) { find_next }
|
29
|
+
bind_key(@KEY_FIND_PREV) { find_prev }
|
30
|
+
=end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|