ppcurses 0.0.25 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +50 -11
- data/lib/ppcurses/Screen.rb +128 -15
- data/lib/ppcurses/actions/BaseAction.rb +1 -2
- data/lib/ppcurses/actions/GetBooleanAction.rb +6 -6
- data/lib/ppcurses/actions/GetDataAction.rb +4 -4
- data/lib/ppcurses/actions/GetEnumeratedStringAction.rb +6 -6
- data/lib/ppcurses/actions/GetIntegerAction.rb +2 -2
- data/lib/ppcurses/actions/GetStringAction.rb +2 -0
- data/lib/ppcurses/actions/PromptAction.rb +2 -2
- data/lib/ppcurses/application.rb +219 -0
- data/lib/ppcurses/date/meta_month.rb +139 -0
- data/lib/ppcurses/form/button.rb +120 -0
- data/lib/ppcurses/form/combo_box.rb +93 -0
- data/lib/ppcurses/form/date_picker.rb +86 -0
- data/lib/ppcurses/form/form.rb +96 -0
- data/lib/ppcurses/form/input_element.rb +189 -0
- data/lib/ppcurses/form/radio_button_group.rb +56 -0
- data/lib/ppcurses/geometry.rb +23 -0
- data/lib/ppcurses/menu/BaseMenu.rb +8 -14
- data/lib/ppcurses/menu/Menu.rb +5 -8
- data/lib/ppcurses/menu/RadioMenu.rb +2 -5
- data/lib/ppcurses/menu/choice_menu.rb +33 -0
- data/lib/ppcurses/menu/date_menu.rb +97 -0
- data/lib/ppcurses/menu_bar.rb +102 -0
- data/lib/ppcurses/table_view.rb +58 -0
- data/lib/ppcurses/view.rb +45 -0
- data/lib/ppcurses/window/pp_window.rb +42 -0
- data/lib/ppcurses.rb +57 -3
- data/test/application/create_application.rb +23 -0
- data/test/date/printMetaMonth.rb +30 -0
- data/test/form/menu_opens_form.rb +15 -0
- data/test/form/simple_form.rb +48 -0
- data/test/form/test_combo.rb +20 -0
- data/test/form/test_date_picker.rb +19 -0
- data/test/getBooleanAction.rb +1 -1
- data/test/getDataAction.rb +6 -6
- data/test/getEnumStringAction.rb +4 -4
- data/test/getIntegerAction.rb +4 -4
- data/test/menu/changeMenuBorder.rb +1 -1
- data/test/menu/compositeMenu.rb +2 -2
- data/test/menu/displayMenu.rb +1 -1
- data/test/raw_screen/display_colours.rb +69 -0
- data/test/raw_screen/press_a_key.rb +18 -0
- data/test/table_view/testTableView.rb +16 -0
- data/test/threads/block_test.rb +63 -0
- data/test/threads/handle_resize.rb +43 -0
- metadata +37 -12
- data/lib/ppcurses/Constants.rb +0 -8
@@ -0,0 +1,139 @@
|
|
1
|
+
|
2
|
+
def group(xs, n)
|
3
|
+
(0..xs.size / n - 1).collect { |i| xs[i * n, n] } # / This comment fixes a Visual Studio Code highlighting bug
|
4
|
+
end
|
5
|
+
|
6
|
+
# --------------------------------------------------------------------------
|
7
|
+
# This algorithm is based on ref/cal.rb by Tadayoshi Funaba
|
8
|
+
#
|
9
|
+
# Differences:
|
10
|
+
# - Only supports a monthly calendar type; no yearly calendar.
|
11
|
+
#
|
12
|
+
# - Returns a secondary day position array that specifies the row
|
13
|
+
# and column for each day of the month. Useful for highlighting a
|
14
|
+
# specific day.
|
15
|
+
#
|
16
|
+
# Example day position array for May 2015. The 1st of February
|
17
|
+
# occurs in the second row and the 16th column of the returned
|
18
|
+
# string calendar array
|
19
|
+
#
|
20
|
+
# day_pos = [ nil, [2,16], [2,19],
|
21
|
+
# [3,1], [3,4], [3,7], [3,10], [3,13], [3,16], [3,19],
|
22
|
+
# [4,0], [4,3], [4,6], [4,9], [4,12], [4,15], [4,18],
|
23
|
+
# [5,0], [5,3], [5,6], [5,9], [5,12], [5,15], [5,18],
|
24
|
+
# [6,0], [6,3], [6,6], [6,9], [6,12], [6,15], [6,18],
|
25
|
+
# [7,0] ]
|
26
|
+
#
|
27
|
+
#
|
28
|
+
# - Takes a Date object as initial parameter
|
29
|
+
#
|
30
|
+
# - K variable eliminated
|
31
|
+
#
|
32
|
+
# - Does not support the transformation option
|
33
|
+
#
|
34
|
+
#
|
35
|
+
def pict(day)
|
36
|
+
|
37
|
+
year = day.year
|
38
|
+
month = day.month
|
39
|
+
|
40
|
+
dw = 2 # Day width
|
41
|
+
mw = (dw + 1) * 7 - 1 # Month width
|
42
|
+
day_pos = [ nil ] # Create an array indexed by 1 by putting nil in slot zero.
|
43
|
+
|
44
|
+
# First day of the month e.g. 2015-05-01
|
45
|
+
fi = Date.new(year, month, 1, Date::GREGORIAN)
|
46
|
+
# Go backwards to the earliest closest day divisible by 7 date, e.g. 2015-04-26,
|
47
|
+
# using the Julian day number and modulus.
|
48
|
+
fi -= (fi.jd + 1) % 7
|
49
|
+
|
50
|
+
ve = (fi..fi + 6).collect{ |cu|
|
51
|
+
%w(S M Tu W Th F S)[cu.wday]
|
52
|
+
}
|
53
|
+
|
54
|
+
row = 1
|
55
|
+
pos = -1
|
56
|
+
# Creates an array of values ["S", " M", ... "31"]
|
57
|
+
ve += (fi..fi + 41).collect{ |cu| # of type Date
|
58
|
+
|
59
|
+
pos += 1 # Needed for meta info
|
60
|
+
if (cu.jd + 1) % 7 == 0 then
|
61
|
+
row += 1
|
62
|
+
pos = 0
|
63
|
+
end
|
64
|
+
|
65
|
+
if cu.mon == month then
|
66
|
+
|
67
|
+
# -------- Save meta information in day_pos array
|
68
|
+
i = pos * 3
|
69
|
+
if cu.mday < 10 then i += 1 end
|
70
|
+
|
71
|
+
day_pos.push [row, i]
|
72
|
+
# --------- End Meta info ------------------
|
73
|
+
|
74
|
+
cu.mday
|
75
|
+
end.to_s
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
# adds padding based on day width "1" --> " 1"
|
80
|
+
ve = ve.collect{|e| e.rjust(dw)}
|
81
|
+
|
82
|
+
# Creates an array of arrays. 7 for the days in the week
|
83
|
+
gr = group(ve, 7)
|
84
|
+
|
85
|
+
# Converts inner arrays to strings
|
86
|
+
ta = gr.collect{|xs| xs.join(' ')}
|
87
|
+
|
88
|
+
# Adds month/year header to top
|
89
|
+
ca = %w(January February March April May June July
|
90
|
+
August September October November December)[month - 1]
|
91
|
+
ca = ca + ' ' + year.to_s
|
92
|
+
ca = ca.center(mw)
|
93
|
+
ta.unshift(ca)
|
94
|
+
|
95
|
+
return ta, day_pos
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
module PPCurses
|
101
|
+
|
102
|
+
|
103
|
+
# A container object that holds:
|
104
|
+
#
|
105
|
+
# - A date object
|
106
|
+
# - The month the day belongs to in string array format
|
107
|
+
# - The row and column position of the date in the string array
|
108
|
+
#
|
109
|
+
# This container is used for displaying dates in the datepicker.
|
110
|
+
# The row and column position are necessary so that the day
|
111
|
+
# selected can be highlighted.
|
112
|
+
#
|
113
|
+
class MetaMonth
|
114
|
+
|
115
|
+
attr_accessor :day
|
116
|
+
attr_accessor :month_str_array
|
117
|
+
attr_accessor :day_pos
|
118
|
+
|
119
|
+
def initialize(day=Date.today)
|
120
|
+
self.day = day
|
121
|
+
end
|
122
|
+
|
123
|
+
def day=(new_day)
|
124
|
+
@day = new_day
|
125
|
+
@month_str_array, @day_pos = pict(@day)
|
126
|
+
end
|
127
|
+
|
128
|
+
def day_row
|
129
|
+
@day_pos[ @day.day ][0]
|
130
|
+
end
|
131
|
+
|
132
|
+
def day_col
|
133
|
+
@day_pos[ @day.day ][1]
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module PPCurses
|
2
|
+
|
3
|
+
class Button < View
|
4
|
+
|
5
|
+
attr_accessor :label
|
6
|
+
attr_accessor :selected
|
7
|
+
attr_accessor :pushed
|
8
|
+
|
9
|
+
attr_accessor :action
|
10
|
+
|
11
|
+
def initialize(label)
|
12
|
+
@label = label
|
13
|
+
@selected = false
|
14
|
+
@pushed = false
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Screen should be of type Curses::Window
|
19
|
+
#
|
20
|
+
def show(screen)
|
21
|
+
screen.attron(Curses::A_REVERSE) if @selected
|
22
|
+
screen.addstr("< #{@label} >")
|
23
|
+
screen.attroff(Curses::A_REVERSE) if @selected
|
24
|
+
end
|
25
|
+
|
26
|
+
def width
|
27
|
+
@label.length + 4
|
28
|
+
end
|
29
|
+
|
30
|
+
def height
|
31
|
+
1
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_curs_pos(screen)
|
35
|
+
Curses.curs_set(INVISIBLE)
|
36
|
+
end
|
37
|
+
|
38
|
+
def key_down( key )
|
39
|
+
|
40
|
+
if key == ENTER
|
41
|
+
@action.call unless action.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
# For grouping two buttons together, i.e. SUBMIT/CANCEL
|
52
|
+
class ButtonPair < View
|
53
|
+
|
54
|
+
attr_accessor :selected
|
55
|
+
attr_accessor :selected_element
|
56
|
+
|
57
|
+
attr_reader :button1
|
58
|
+
attr_reader :button2
|
59
|
+
|
60
|
+
def initialize(button1_label, button2_label)
|
61
|
+
@button1 = Button.new(button1_label)
|
62
|
+
@button2 = Button.new(button2_label)
|
63
|
+
|
64
|
+
@selected_button = @button1
|
65
|
+
|
66
|
+
@selected = false
|
67
|
+
end
|
68
|
+
|
69
|
+
def selected=(val)
|
70
|
+
@selected_button.selected = val
|
71
|
+
@selected=val
|
72
|
+
end
|
73
|
+
|
74
|
+
def height
|
75
|
+
1
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_curs_pos(screen)
|
79
|
+
Curses.curs_set(INVISIBLE)
|
80
|
+
end
|
81
|
+
|
82
|
+
def key_down( key )
|
83
|
+
if key == KEY_RIGHT or key == KEY_LEFT
|
84
|
+
@selected_button.selected=false
|
85
|
+
|
86
|
+
if @selected_button == @button1
|
87
|
+
@selected_button = @button2
|
88
|
+
else
|
89
|
+
@selected_button = @button1
|
90
|
+
end
|
91
|
+
|
92
|
+
@selected_button.selected=true
|
93
|
+
return
|
94
|
+
end
|
95
|
+
|
96
|
+
@selected_button.key_down(key)
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
def show(screen)
|
101
|
+
|
102
|
+
p = screen.cur_point
|
103
|
+
p.y+=1
|
104
|
+
screen.set_pos_by_point(p)
|
105
|
+
|
106
|
+
|
107
|
+
@button1.show(screen)
|
108
|
+
|
109
|
+
p.x += @button1.width + 2
|
110
|
+
screen.set_pos_by_point(p)
|
111
|
+
|
112
|
+
@button2.show(screen)
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
module PPCurses
|
4
|
+
|
5
|
+
class ComboBox < View
|
6
|
+
|
7
|
+
DOWN_ARROW = '∇'
|
8
|
+
|
9
|
+
# Does the element have focus in the form?
|
10
|
+
attr_accessor :selected
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(label, options)
|
14
|
+
@label = label
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
@display_width = 13
|
18
|
+
@choice_made = false
|
19
|
+
|
20
|
+
@options.each do |option|
|
21
|
+
if option.length > @display_width
|
22
|
+
@display_width = option.length
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def show(screen)
|
29
|
+
screen.attron(A_REVERSE) if @selected
|
30
|
+
screen.addstr("#{@label}:")
|
31
|
+
|
32
|
+
@combo_display_point = screen.cur_point
|
33
|
+
|
34
|
+
screen.attroff(A_REVERSE) if @selected
|
35
|
+
|
36
|
+
screen.addstr(display_string)
|
37
|
+
end
|
38
|
+
|
39
|
+
def height
|
40
|
+
1
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_curs_pos(screen)
|
44
|
+
screen.curs_set(INVISIBLE)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return Value
|
48
|
+
# The object in the receiver's internal item list corresponding to the last item selected
|
49
|
+
# from the pop-up list, or nil if no item is selected.
|
50
|
+
def object_value_of_selected_item
|
51
|
+
if @options_menu.nil?
|
52
|
+
return nil
|
53
|
+
end
|
54
|
+
|
55
|
+
@options[@options_menu.selection]
|
56
|
+
end
|
57
|
+
|
58
|
+
def key_down(key)
|
59
|
+
|
60
|
+
if key == ENTER
|
61
|
+
|
62
|
+
if @options_menu.nil?
|
63
|
+
@options_menu = PPCurses::ChoiceMenu.new( @options )
|
64
|
+
end
|
65
|
+
|
66
|
+
@options_menu.set_origin(@combo_display_point)
|
67
|
+
|
68
|
+
@options_menu.show
|
69
|
+
@options_menu.menu_selection
|
70
|
+
|
71
|
+
if @options_menu.pressed_enter
|
72
|
+
@choice_made = true
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#------------------------------------------------
|
80
|
+
protected
|
81
|
+
def display_string
|
82
|
+
if @choice_made
|
83
|
+
return ' '+ "#{@options[@options_menu.selection].center(@display_width,'-')} #{DOWN_ARROW}"
|
84
|
+
end
|
85
|
+
|
86
|
+
' ' + ' select '.center(@display_width,'-') + " #{DOWN_ARROW}"
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
module PPCurses
|
4
|
+
|
5
|
+
|
6
|
+
# Ruby date objects are immutable
|
7
|
+
# ---------------------------------
|
8
|
+
# 09-15-1950
|
9
|
+
# 05-04-2015 = May 4th 2015
|
10
|
+
class DatePicker < View
|
11
|
+
|
12
|
+
DOWN_ARROW = '∇'
|
13
|
+
|
14
|
+
# Does the element have focus in the form?
|
15
|
+
attr_accessor :selected
|
16
|
+
|
17
|
+
|
18
|
+
def initialize(label, initial_date = Date.today)
|
19
|
+
@label = label
|
20
|
+
@display_width = 13
|
21
|
+
@date = initial_date
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def show(screen)
|
26
|
+
screen.attron(A_REVERSE) if @selected
|
27
|
+
screen.addstr("#{@label}:")
|
28
|
+
|
29
|
+
@combo_display_point = screen.cur_point
|
30
|
+
|
31
|
+
screen.attroff(A_REVERSE) if @selected
|
32
|
+
|
33
|
+
screen.addstr(display_string)
|
34
|
+
end
|
35
|
+
|
36
|
+
def height
|
37
|
+
1
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_curs_pos(screen)
|
41
|
+
screen.curs_set(INVISIBLE)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return Value
|
45
|
+
# The object in the receiver's internal item list corresponding to the last item selected
|
46
|
+
# from the pop-up list, or nil if no item is selected.
|
47
|
+
def object_value_of_selected_item
|
48
|
+
if @options_menu.nil?
|
49
|
+
return nil
|
50
|
+
end
|
51
|
+
|
52
|
+
@options[@options_menu.selection]
|
53
|
+
end
|
54
|
+
|
55
|
+
def key_down(key)
|
56
|
+
|
57
|
+
if key == ENTER
|
58
|
+
|
59
|
+
if @date_menu.nil?
|
60
|
+
@date_menu = PPCurses::DateMenu.new(@date)
|
61
|
+
end
|
62
|
+
|
63
|
+
@date_menu.set_origin(@combo_display_point)
|
64
|
+
|
65
|
+
@date_menu.show
|
66
|
+
@date_menu.menu_selection
|
67
|
+
|
68
|
+
if @date_menu.pressed_enter
|
69
|
+
@date = @date_menu.day
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
#------------------------------------------------
|
77
|
+
protected
|
78
|
+
def display_string
|
79
|
+
" #{@date.month}-#{@date.day}-#{@date.year} #{DOWN_ARROW}"
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module PPCurses
|
2
|
+
|
3
|
+
class Form < View
|
4
|
+
|
5
|
+
attr_accessor :selected_element
|
6
|
+
|
7
|
+
#
|
8
|
+
# Screen should be of type Curses::Window
|
9
|
+
#
|
10
|
+
def initialize
|
11
|
+
@elements = []
|
12
|
+
end
|
13
|
+
|
14
|
+
# Formal protocol required
|
15
|
+
# Adds an element to the form. Elements are rendered in the order they are added.
|
16
|
+
#
|
17
|
+
# An element must implement the following protocol:
|
18
|
+
#
|
19
|
+
# - def show(screen)
|
20
|
+
# - def height
|
21
|
+
# - def set_curs_pos(screen)
|
22
|
+
# - def key_down(key)
|
23
|
+
# - def selected=
|
24
|
+
#
|
25
|
+
def add (element)
|
26
|
+
PPCurses.implements_protocol( element, %w(show height set_curs_pos key_down selected=))
|
27
|
+
@elements.push(element)
|
28
|
+
|
29
|
+
if @selected_element.nil?
|
30
|
+
set_selected_element(@elements[0])
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def submitted?
|
37
|
+
@button_pair.button1.pushed
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def key_down( key )
|
42
|
+
|
43
|
+
if key == KEY_UP or key == KEY_DOWN or key == TAB
|
44
|
+
selected_index = @elements.index(@selected_element)
|
45
|
+
n_choices = @elements.length
|
46
|
+
|
47
|
+
if key == KEY_DOWN or key == TAB
|
48
|
+
(selected_index == n_choices-1) ? next_selection = 0 : next_selection = selected_index + 1
|
49
|
+
else
|
50
|
+
(selected_index == 0) ? next_selection = n_choices - 1 : next_selection = selected_index - 1
|
51
|
+
end
|
52
|
+
|
53
|
+
set_selected_element(@elements[next_selection])
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
@selected_element.key_down(key)
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# TODO -- call display of subview???
|
63
|
+
def display(screen)
|
64
|
+
y = 1
|
65
|
+
x = 1
|
66
|
+
|
67
|
+
for i in 0..@elements.length - 1
|
68
|
+
element = @elements[i]
|
69
|
+
screen.setpos(y, x)
|
70
|
+
element.show(screen)
|
71
|
+
y += element.height
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
@selected_element.set_curs_pos(screen) unless @selected_element.nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
# --------------------------------------------------------------------------------
|
79
|
+
protected
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
def set_selected_element(new_element)
|
84
|
+
|
85
|
+
unless @selected_element.nil?
|
86
|
+
@selected_element.selected=false
|
87
|
+
end
|
88
|
+
|
89
|
+
@selected_element = new_element
|
90
|
+
@selected_element.selected=true
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module PPCurses
|
2
|
+
|
3
|
+
class InputElement < View
|
4
|
+
|
5
|
+
attr_accessor :label
|
6
|
+
attr_accessor :value
|
7
|
+
attr_accessor :size
|
8
|
+
attr_accessor :selected
|
9
|
+
|
10
|
+
attr_accessor :filter
|
11
|
+
|
12
|
+
attr_accessor :value_start_point
|
13
|
+
|
14
|
+
|
15
|
+
# Stores the X location of the cursor relative to the
|
16
|
+
# value being displayed. If the cursor is in
|
17
|
+
# the middle of the string then subsequent keys
|
18
|
+
# will be added from this location, etc.
|
19
|
+
attr_accessor :cursor_location
|
20
|
+
|
21
|
+
|
22
|
+
def initialize(label, size )
|
23
|
+
@label = label
|
24
|
+
@size = size
|
25
|
+
@selected = false
|
26
|
+
@value = ''
|
27
|
+
@cursor_location = 0
|
28
|
+
@filter = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Creates an InputElement that only allows integer input
|
32
|
+
#
|
33
|
+
def InputElement.new_integer_only( label, size)
|
34
|
+
i_only = PPCurses::InputElement.new(label, size)
|
35
|
+
i_only.filter =PPCurses::NumberFilter.new
|
36
|
+
i_only
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def show(screen)
|
41
|
+
print_label( screen )
|
42
|
+
|
43
|
+
@value_start_point = screen.cur_point
|
44
|
+
|
45
|
+
print_value( screen )
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
def key_down( key )
|
51
|
+
if key == DELETE
|
52
|
+
handle_delete
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
if key == KEY_LEFT
|
57
|
+
@cursor_location -= 1 unless @cursor_location == 0
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
if key == KEY_RIGHT
|
62
|
+
@cursor_location += 1 unless @cursor_location == @value.length
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Ignore control characters
|
68
|
+
if key.is_a?(Fixnum)
|
69
|
+
return
|
70
|
+
end
|
71
|
+
|
72
|
+
# Adding new characters to the string
|
73
|
+
|
74
|
+
# Check size of string before adding another character
|
75
|
+
if @value.length >= @size
|
76
|
+
# Ignore input
|
77
|
+
return
|
78
|
+
end
|
79
|
+
|
80
|
+
unless passes_filter(key)
|
81
|
+
return
|
82
|
+
end
|
83
|
+
|
84
|
+
add_character(key)
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def passes_filter( key )
|
90
|
+
if @filter.nil?
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
|
94
|
+
@filter.passes_filter( key )
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def set_curs_pos(screen)
|
99
|
+
Curses.curs_set(VISIBLE)
|
100
|
+
x = @value_start_point.x + @cursor_location
|
101
|
+
|
102
|
+
screen.setpos( @value_start_point.y, x )
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def height
|
107
|
+
1
|
108
|
+
end
|
109
|
+
|
110
|
+
# --------------------------------------------------------------------------------
|
111
|
+
protected
|
112
|
+
|
113
|
+
|
114
|
+
def print_label( screen )
|
115
|
+
screen.attron(Curses::A_REVERSE) if @selected
|
116
|
+
screen.addstr("#{@label}:")
|
117
|
+
screen.attroff(Curses::A_REVERSE) if @selected
|
118
|
+
screen.addstr(' ')
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
def print_value( screen )
|
123
|
+
screen.attron(Curses::A_UNDERLINE)
|
124
|
+
screen.addstr(@value.ljust(@size))
|
125
|
+
screen.attroff(Curses::A_UNDERLINE)
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
def handle_delete
|
130
|
+
# Cursor is at the front of the string, nothing in
|
131
|
+
# front of it to delete, or there is nothing to delete
|
132
|
+
if @cursor_location == 0 or @value.length == 0
|
133
|
+
return
|
134
|
+
end
|
135
|
+
|
136
|
+
if @value.length == 1
|
137
|
+
@value = ''
|
138
|
+
@cursor_location = 0
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
142
|
+
# Cursor is at the end of the string, remove the last character
|
143
|
+
if @cursor_location == @value.length
|
144
|
+
@value = @value.slice(0..@cursor_location-2)
|
145
|
+
elsif @cursor_location == 1
|
146
|
+
# cursor is right after the first character
|
147
|
+
@value = @value.slice(1..@value.length-1)
|
148
|
+
else
|
149
|
+
# Cursor is in the middle of the string, remove the character at the cursor location
|
150
|
+
# Example:
|
151
|
+
#
|
152
|
+
# abcdefg
|
153
|
+
# 1234567
|
154
|
+
# ^ -> cursor-location = 3
|
155
|
+
#
|
156
|
+
@value = @value.slice(0..@cursor_location-2) + @value.slice(@cursor_location..@value.length-1)
|
157
|
+
end
|
158
|
+
|
159
|
+
@cursor_location -= 1
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def add_character ( char )
|
164
|
+
if @cursor_location == @value.length
|
165
|
+
@value += char
|
166
|
+
else
|
167
|
+
@value = @value.slice(0..@cursor_location-1) + char + @value.slice(@cursor_location..@value.length-1)
|
168
|
+
end
|
169
|
+
|
170
|
+
@cursor_location += 1
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
class NumberFilter
|
178
|
+
|
179
|
+
def passes_filter( key )
|
180
|
+
if key =~ /^\d+$/
|
181
|
+
return true
|
182
|
+
end
|
183
|
+
|
184
|
+
false
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|