rbcurse 1.4.0 → 1.4.1.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/NOTES +68 -0
- data/README.markdown +73 -330
- data/TODO2.txt +2 -2
- data/VERSION +1 -1
- data/examples/abasiclist.rb +8 -2
- data/examples/alpmenu.rb +1 -1
- data/examples/app.rb +1 -24
- data/examples/appdirtree.rb +1 -1
- data/examples/appemail.rb +8 -14
- data/examples/appemaillb.rb +2 -2
- data/examples/appgcompose.rb +7 -5
- data/examples/common/file.rb +40 -0
- data/examples/{rmail.rb → common/rmail.rb} +0 -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/tasks.txt +27 -0
- data/examples/{todocsv.csv → data/todocsv.csv} +0 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +49 -14
- data/examples/{appgmail.rb → deprecated/appgmail.rb} +1 -1
- data/examples/{splitp.rb → deprecated/splitp.rb} +0 -0
- data/examples/{testscrolllb.rb → deprecated/testscrolllb.rb} +0 -0
- data/examples/{testscrollp.rb → deprecated/testscrollp.rb} +0 -0
- data/examples/{testscrollta.rb → deprecated/testscrollta.rb} +0 -0
- data/examples/{testscrolltable.rb → deprecated/testscrolltable.rb} +0 -0
- data/examples/{testsplit.rb → deprecated/testsplit.rb} +0 -0
- data/examples/{testsplit2.rb → deprecated/testsplit2.rb} +0 -0
- data/examples/{testsplit3.rb → deprecated/testsplit3.rb} +0 -0
- data/examples/{testsplit3_1.rb → deprecated/testsplit3_1.rb} +0 -0
- data/examples/{testsplit3a.rb → deprecated/testsplit3a.rb} +0 -0
- data/examples/{testsplit3b.rb → deprecated/testsplit3b.rb} +0 -0
- data/examples/{testsplitta.rb → deprecated/testsplitta.rb} +0 -0
- data/examples/{testsplittv.rb → deprecated/testsplittv.rb} +0 -0
- data/examples/{testsplittvv.rb → deprecated/testsplittvv.rb} +0 -0
- data/examples/{testtpane.rb → deprecated/testtpane.rb} +0 -0
- data/examples/{testtpane2.rb → deprecated/testtpane2.rb} +0 -0
- data/examples/{testtpanetable.rb → deprecated/testtpanetable.rb} +0 -0
- data/examples/dirtree.rb +17 -7
- data/examples/experimental/resultsetdemo.rb +280 -0
- data/examples/experimental/testmform.rb +35 -0
- data/examples/{testscroller.rb → experimental/testscroller.rb} +1 -19
- data/examples/experimental/teststackflow.rb +111 -0
- data/examples/menu1.rb +1 -0
- data/examples/multispl.rb +4 -4
- data/examples/newmessagebox.rb +130 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +0 -3
- data/examples/qdfilechooser.rb +0 -3
- data/examples/rfe.rb +134 -18
- data/examples/rfe_renderer.rb +48 -2
- data/examples/sqlc.rb +2 -1
- data/examples/sqlm.rb +0 -2
- data/examples/table1.rb +1 -7
- data/examples/term2.rb +4 -1
- data/examples/test1.rb +0 -5
- data/examples/test2.rb +42 -31
- data/examples/testapp2.rb +8 -1
- data/examples/testchars.rb +0 -4
- data/examples/testcombo.rb +5 -9
- data/examples/testkeypress.rb +0 -3
- data/examples/testmenu.rb +0 -4
- data/examples/testmulticomp.rb +3 -5
- data/examples/testmulticontainer.rb +94 -0
- data/examples/testtable.rb +0 -5
- data/examples/testtabp.rb +16 -18
- data/examples/testtodo.rb +1 -5
- data/examples/testwsshortcuts.rb +64 -0
- data/examples/testwsshortcuts2.rb +126 -0
- data/examples/viewtodo.rb +1 -4
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/app.rb +92 -69
- data/lib/rbcurse/applicationheader.rb +46 -6
- data/lib/rbcurse/celleditor.rb +1 -9
- data/lib/rbcurse/comboboxcellrenderer.rb +0 -4
- data/lib/rbcurse/common/ansiparser.rb +117 -0
- data/{examples → lib/rbcurse/common}/appmethods.rb +25 -0
- data/lib/rbcurse/common/basestack.rb +407 -0
- data/lib/rbcurse/common/bordertitle.rb +41 -0
- data/lib/rbcurse/common/chunk.rb +177 -0
- data/lib/rbcurse/common/colorparser.rb +71 -0
- data/lib/rbcurse/common/keydefs.rb +30 -0
- data/lib/rbcurse/common/widgetshortcuts.rb +302 -0
- data/lib/rbcurse/deprecated/README.markdown +12 -0
- data/lib/rbcurse/{rscrollpane.rb → deprecated/rscrollpane.rb} +0 -0
- data/lib/rbcurse/{rsplitpane.rb → deprecated/rsplitpane.rb} +0 -0
- data/lib/rbcurse/{rsplitpane2.rb → deprecated/rsplitpane2.rb} +0 -0
- data/lib/rbcurse/{rviewport.rb → deprecated/rviewport.rb} +0 -0
- data/lib/rbcurse/experimental/README.markdown +14 -0
- data/lib/rbcurse/experimental/resultsettextview.rb +585 -0
- data/lib/rbcurse/experimental/stackflow.rb +478 -0
- data/lib/rbcurse/extras/bottomline.rb +85 -16
- data/lib/rbcurse/extras/box.rb +58 -0
- data/lib/rbcurse/extras/directorylist.rb +1 -1
- data/lib/rbcurse/extras/horizlist.rb +203 -0
- data/lib/rbcurse/extras/listselectable.rb +8 -0
- data/lib/rbcurse/extras/multiform.rb +330 -0
- data/lib/rbcurse/extras/multilinelabel.rb +142 -0
- data/lib/rbcurse/extras/newmessagebox.rb +328 -0
- data/lib/rbcurse/extras/newtabbedpane.rb +612 -0
- data/lib/rbcurse/extras/newtabbedwindow.rb +68 -0
- data/lib/rbcurse/extras/padreader.rb +189 -0
- data/lib/rbcurse/extras/rcomboedit.rb +256 -0
- data/lib/rbcurse/extras/resultsetbrowser.rb +281 -0
- data/lib/rbcurse/extras/statusline.rb +44 -6
- data/lib/rbcurse/extras/tabularwidget.rb +141 -104
- data/lib/rbcurse/extras/textpad.rb +516 -0
- data/lib/rbcurse/extras/viewer.rb +2 -0
- data/lib/rbcurse/io.rb +120 -3
- data/lib/rbcurse/listcellrenderer.rb +2 -1
- data/lib/rbcurse/listkeys.rb +1 -1
- data/lib/rbcurse/listscrollable.rb +72 -7
- data/lib/rbcurse/rbasiclistbox.rb +64 -12
- data/lib/rbcurse/rchangeevent.rb +0 -1
- data/lib/rbcurse/rcombo.rb +54 -59
- data/lib/rbcurse/rcommandwindow.rb +46 -10
- data/lib/rbcurse/rcontainer.rb +415 -0
- data/lib/rbcurse/rdialogs.rb +242 -165
- data/lib/rbcurse/rinputdataevent.rb +0 -1
- data/lib/rbcurse/rlistbox.rb +19 -9
- data/lib/rbcurse/rmessagebox.rb +1 -5
- data/lib/rbcurse/rmulticontainer.rb +64 -61
- data/lib/rbcurse/rmultitextview.rb +0 -2
- data/lib/rbcurse/rpopupmenu.rb +0 -2
- data/lib/rbcurse/rscrollform.rb +61 -12
- data/lib/rbcurse/rtabbedpane.rb +89 -73
- data/lib/rbcurse/rtabbedwindow.rb +53 -211
- data/lib/rbcurse/rtable.rb +0 -2
- data/lib/rbcurse/rtextarea.rb +14 -14
- data/lib/rbcurse/rtextview.rb +165 -50
- data/lib/rbcurse/rvimsplit.rb +15 -12
- data/lib/rbcurse/rwidget.rb +404 -150
- data/lib/rbcurse/table/tablecellrenderer.rb +1 -4
- data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -3
- data/lib/ver/ncurses.rb +1 -9
- data/lib/ver/rpad.rb +375 -0
- data/lib/ver/window.rb +262 -440
- metadata +73 -31
@@ -0,0 +1,41 @@
|
|
1
|
+
# I am moving the common title and border printing stuff into
|
2
|
+
# a separate module.
|
3
|
+
module BorderTitle
|
4
|
+
dsl_accessor :suppress_borders #to_print_borders
|
5
|
+
dsl_accessor :border_attrib, :border_color
|
6
|
+
dsl_accessor :title #set this on top
|
7
|
+
dsl_accessor :title_attrib #bold, reverse, normal
|
8
|
+
dsl_accessor :border_attrib, :border_color #
|
9
|
+
|
10
|
+
def bordertitle_init
|
11
|
+
@row_offset = @col_offset = 0 if @suppress_borders
|
12
|
+
@internal_width = 1 if @suppress_borders
|
13
|
+
end
|
14
|
+
# why the dash does it reduce height by one.
|
15
|
+
def print_borders
|
16
|
+
raise ArgumentError, "Graphic not set" unless @graphic
|
17
|
+
width = @width
|
18
|
+
height = @height-1
|
19
|
+
window = @graphic
|
20
|
+
startcol = @col
|
21
|
+
startrow = @row
|
22
|
+
@color_pair = get_color($datacolor)
|
23
|
+
bordercolor = @border_color || @color_pair
|
24
|
+
borderatt = @border_attrib || Ncurses::A_NORMAL
|
25
|
+
window.print_border startrow, startcol, height, width, bordercolor, borderatt
|
26
|
+
print_title
|
27
|
+
end
|
28
|
+
def print_title
|
29
|
+
return unless @title
|
30
|
+
raise "#{self} needs width" unless @width
|
31
|
+
@color_pair ||= get_color($datacolor) # should we not use this ??? XXX
|
32
|
+
#$log.debug " print_title #{@row}, #{@col}, #{@width} "
|
33
|
+
# check title.length and truncate if exceeds width
|
34
|
+
_title = @title
|
35
|
+
if @title.length > @width - 2
|
36
|
+
_title = @title[0..@width-2]
|
37
|
+
end
|
38
|
+
@graphic.printstring( @row, @col+(@width-_title.length)/2, _title, @color_pair, @title_attrib) unless @title.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# ------------------------------------------------------------ #
|
2
|
+
# File: chunk.rb
|
3
|
+
# Description:
|
4
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
5
|
+
# Date: 07.11.11 - 12:31
|
6
|
+
# Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
7
|
+
# Last update: use ,,L
|
8
|
+
# ------------------------------------------------------------ #
|
9
|
+
#
|
10
|
+
|
11
|
+
module Chunks
|
12
|
+
extend self
|
13
|
+
class Chunk
|
14
|
+
|
15
|
+
# color_pair of associated text
|
16
|
+
# text to print
|
17
|
+
# attribute of associated text
|
18
|
+
#attr_accessor :color, :text, :attrib
|
19
|
+
attr_reader :chunk
|
20
|
+
|
21
|
+
def initialize color, text, attrib
|
22
|
+
@chunk = [ color, text, attrib ]
|
23
|
+
#@color = color
|
24
|
+
#@text = text
|
25
|
+
#@attrib = attrib
|
26
|
+
end
|
27
|
+
def color
|
28
|
+
@chunk[0]
|
29
|
+
end
|
30
|
+
def text
|
31
|
+
@chunk[1]
|
32
|
+
end
|
33
|
+
def attrib
|
34
|
+
@chunk[2]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# consists of an array of chunks and corresponds to a line
|
39
|
+
# to be printed.
|
40
|
+
class ChunkLine
|
41
|
+
|
42
|
+
# an array of chunks
|
43
|
+
attr_reader :chunks
|
44
|
+
|
45
|
+
def initialize arr=nil
|
46
|
+
@chunks = arr.nil? ? Array.new : arr
|
47
|
+
end
|
48
|
+
def <<(chunk)
|
49
|
+
raise ArgumentError, "Chunk object expected. Received #{chunk.class} " unless chunk.is_a? Chunk
|
50
|
+
@chunks << chunk
|
51
|
+
end
|
52
|
+
alias :add :<<
|
53
|
+
def each &block
|
54
|
+
@chunks.each &block
|
55
|
+
end
|
56
|
+
|
57
|
+
# returns length of text in chunks
|
58
|
+
def row_length
|
59
|
+
result = 0
|
60
|
+
@chunks.each { |e| result += e.text.length }
|
61
|
+
return result
|
62
|
+
end
|
63
|
+
alias :length :row_length
|
64
|
+
alias :size :row_length
|
65
|
+
|
66
|
+
# return a Chunkline containing only the text for the range requested
|
67
|
+
def substring start, size
|
68
|
+
end
|
69
|
+
end
|
70
|
+
class ColorParser
|
71
|
+
def initialize cp
|
72
|
+
color_parser cp
|
73
|
+
@color_pair = $datacolor
|
74
|
+
@attrib = FFI::NCurses::A_NORMAL
|
75
|
+
@color_array = [:white]
|
76
|
+
@bgcolor_array = [:black]
|
77
|
+
@attrib_array = [@attrib]
|
78
|
+
@color_pair_array = [@color_pair]
|
79
|
+
@color = :white
|
80
|
+
@bgcolor = :black
|
81
|
+
end
|
82
|
+
#
|
83
|
+
# Takes a formatted string and converts the parsed parts to chunks.
|
84
|
+
#
|
85
|
+
# @param [String] takes the entire line or string and breaks into an array of chunks
|
86
|
+
# @yield chunk if block
|
87
|
+
# @return [ChunkLine] # [Array] array of chunks
|
88
|
+
# @since 1.4.1 2011-11-3 experimental, can change
|
89
|
+
public
|
90
|
+
def convert_to_chunk s, colorp=$datacolor, att=FFI::NCurses::A_NORMAL
|
91
|
+
#require 'rbcurse/common/chunk'
|
92
|
+
|
93
|
+
@color_parser ||= get_default_color_parser()
|
94
|
+
## defaults
|
95
|
+
color_pair = @color_pair
|
96
|
+
attrib = @attrib
|
97
|
+
#res = []
|
98
|
+
res = ChunkLine.new
|
99
|
+
color = @color
|
100
|
+
bgcolor = @bgcolor
|
101
|
+
# stack the values, so when user issues "/end" we can pop earlier ones
|
102
|
+
|
103
|
+
@color_parser.parse_format(s) do |p|
|
104
|
+
case p
|
105
|
+
when Array
|
106
|
+
## got color / attrib info, this starts a new span
|
107
|
+
|
108
|
+
#color, bgcolor, attrib = *p
|
109
|
+
lc, lb, la = *p
|
110
|
+
if la
|
111
|
+
@attrib = get_attrib la
|
112
|
+
end
|
113
|
+
if lc || lb
|
114
|
+
@color = lc ? lc : @color_array.last
|
115
|
+
@bgcolor = lb ? lb : @bgcolor_array.last
|
116
|
+
@color_array << @color
|
117
|
+
@bgcolor_array << @bgcolor
|
118
|
+
@color_pair = get_color($datacolor, @color, @bgcolor)
|
119
|
+
end
|
120
|
+
@color_pair_array << @color_pair
|
121
|
+
@attrib_array << @attrib
|
122
|
+
#$log.debug "XXX: CHUNK start #{color_pair} , #{attrib} :: c:#{lc} b:#{lb} "
|
123
|
+
#$log.debug "XXX: CHUNK start arr #{@color_pair_array} :: #{@attrib_array} "
|
124
|
+
|
125
|
+
when :endcolor
|
126
|
+
|
127
|
+
# end the current (last) span
|
128
|
+
@color_pair_array.pop
|
129
|
+
@color_pair = @color_pair_array.last
|
130
|
+
@attrib_array.pop
|
131
|
+
@attrib = @attrib_array.last
|
132
|
+
#$log.debug "XXX: CHUNK end #{color_pair} , #{attrib} "
|
133
|
+
#$log.debug "XXX: CHUNK end arr #{@color_pair_array} :: #{@attrib_array} "
|
134
|
+
when :reset # ansi has this
|
135
|
+
# end all previous colors
|
136
|
+
@color_pair = $datacolor # @color_pair_array.first
|
137
|
+
@color_pair_array = [@color_pair]
|
138
|
+
@attrib = FFI::NCurses::A_NORMAL #@attrib_array.first
|
139
|
+
@attrib_array = [@attrib]
|
140
|
+
@bgcolor_array = [@bgcolor_array.first]
|
141
|
+
@color_array = [@color_array.first]
|
142
|
+
|
143
|
+
when String
|
144
|
+
|
145
|
+
## create the chunk
|
146
|
+
$log.debug "XXX: CHUNK using on #{p} : #{@color_pair} , #{@attrib} "
|
147
|
+
|
148
|
+
#chunk = [color_pair, p, attrib]
|
149
|
+
chunk = Chunk.new @color_pair, p, @attrib
|
150
|
+
if block_given?
|
151
|
+
yield chunk
|
152
|
+
else
|
153
|
+
res << chunk
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end # parse
|
157
|
+
return res unless block_given?
|
158
|
+
end
|
159
|
+
def get_default_color_parser
|
160
|
+
require 'rbcurse/common/colorparser'
|
161
|
+
@color_parser || DefaultColorParser.new
|
162
|
+
end
|
163
|
+
# supply with a color parser, if you supplied formatted text
|
164
|
+
public
|
165
|
+
def color_parser f
|
166
|
+
$log.debug "XXX: color_parser setting in CP to #{f} "
|
167
|
+
if f == :tmux
|
168
|
+
@color_parser = get_default_color_parser()
|
169
|
+
elsif f == :ansi
|
170
|
+
require 'rbcurse/common/ansiparser'
|
171
|
+
@color_parser = AnsiParser.new
|
172
|
+
else
|
173
|
+
@color_parser = f
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end # class
|
177
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
2
|
+
# File: colorparser.rb
|
3
|
+
# Description: Default parse for our tmux format
|
4
|
+
# The aim is to be able to specify parsers so different kinds
|
5
|
+
# of formatting or documents can be used, such as ANSI formatted
|
6
|
+
# manpages.
|
7
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
8
|
+
# Date: 07.11.11 - 13:17
|
9
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
10
|
+
# Last update: use ,,L
|
11
|
+
# ----------------------------------------------------------------------------- #
|
12
|
+
# == TODO
|
13
|
+
# - perhaps we can compile the regexp once and reuse
|
14
|
+
#
|
15
|
+
|
16
|
+
class DefaultColorParser
|
17
|
+
|
18
|
+
# NOTE: Experimental and minimal
|
19
|
+
# parses the formatted string and yields either an array of color, bgcolor and attrib
|
20
|
+
# or the text. This will be called by convert_to_chunk.
|
21
|
+
#
|
22
|
+
# Currently, assumes colors and attributes are correct. No error checking or fancy stuff.
|
23
|
+
# s="#[fg=green]hello there#[fg=yellow, bg=black, dim]"
|
24
|
+
# @since 1.4.1 2011-11-3 experimental, can change
|
25
|
+
# @return [nil] knows nothign about output format.
|
26
|
+
|
27
|
+
def parse_format s # yields attribs or text
|
28
|
+
## set default colors
|
29
|
+
color = :white
|
30
|
+
bgcolor = :black
|
31
|
+
attrib = FFI::NCurses::A_NORMAL
|
32
|
+
text = ""
|
33
|
+
|
34
|
+
## split #[...]
|
35
|
+
a = s.split /(#\[[^\]]*\])/
|
36
|
+
a.each { |e|
|
37
|
+
## process color or attrib portion
|
38
|
+
if e[0,2] == "#[" && e[-1] == "]"
|
39
|
+
# now resetting 1:20 PM November 3, 2011 , earlier we were carrying over
|
40
|
+
color, bgcolor, attrib = nil, nil, nil
|
41
|
+
catch(:done) do
|
42
|
+
e = e[2..-2]
|
43
|
+
## first split on commas to separate fg, bg and attr
|
44
|
+
atts = e.split /\s*,\s*/
|
45
|
+
atts.each { |att|
|
46
|
+
## next split on =
|
47
|
+
part = att.split /\s*=\s*/
|
48
|
+
case part[0]
|
49
|
+
when "fg"
|
50
|
+
color = part[1]
|
51
|
+
when "bg"
|
52
|
+
bgcolor = part[1]
|
53
|
+
when "/end", "end"
|
54
|
+
yield :endcolor if block_given?
|
55
|
+
#next
|
56
|
+
throw :done
|
57
|
+
else
|
58
|
+
# attrib
|
59
|
+
attrib = part[0]
|
60
|
+
end
|
61
|
+
}
|
62
|
+
yield [color,bgcolor,attrib] if block_given?
|
63
|
+
end # catch
|
64
|
+
else
|
65
|
+
text = e
|
66
|
+
yield text if block_given?
|
67
|
+
end
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
2
|
+
# File: keydefs.rb
|
3
|
+
# Description: Some common keys used in app. Earlier part of rwidget.rb
|
4
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
5
|
+
# Date: 08.11.11 - 14:57
|
6
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
7
|
+
# Last update: 08.11.11 - 14:57
|
8
|
+
# ----------------------------------------------------------------------------- #
|
9
|
+
#
|
10
|
+
|
11
|
+
# some common definition that we use throughout app. Do not add more, only what is common.
|
12
|
+
# I should not have added Sh-F9 and C-left since they are rare, but only to show they exist.
|
13
|
+
#
|
14
|
+
KEY_TAB = 9
|
15
|
+
KEY_F1 = FFI::NCurses::KEY_F1
|
16
|
+
KEY_F10 = FFI::NCurses::KEY_F10
|
17
|
+
KEY_ENTER = 10 # FFI::NCurses::KEY_ENTER gives 343
|
18
|
+
KEY_BTAB = 353 # nc gives same
|
19
|
+
KEY_RETURN = 13 # Nc gives 343 for KEY_ENTER
|
20
|
+
KEY_DELETE = 330
|
21
|
+
KEY_BACKSPACE = KEY_BSPACE = 127 # Nc gives 263 for BACKSPACE
|
22
|
+
KEY_CC = 3 # C-c
|
23
|
+
KEY_LEFT = FFI::NCurses::KEY_LEFT
|
24
|
+
KEY_RIGHT = FFI::NCurses::KEY_RIGHT
|
25
|
+
KEY_UP = FFI::NCurses::KEY_UP
|
26
|
+
KEY_DOWN = FFI::NCurses::KEY_DOWN
|
27
|
+
C_LEFT = 18168
|
28
|
+
C_RIGHT = 18167
|
29
|
+
S_F9 = 17949126
|
30
|
+
META_KEY = 128
|
@@ -0,0 +1,302 @@
|
|
1
|
+
# ------------------------------------------------------------ #
|
2
|
+
# File: widgetshortcuts.rb
|
3
|
+
# Description: A common module for shortcuts to create widgets
|
4
|
+
# Also, stacks and flows objects
|
5
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
6
|
+
# Date: 05.11.11 - 15:13
|
7
|
+
# Last update: 06.11.11 - 10:57
|
8
|
+
# == TODO
|
9
|
+
# add multirow comps like textview and textarea, list
|
10
|
+
# add blocks that make sense like in app
|
11
|
+
# - what if user does not want form attached - app uses useform ot
|
12
|
+
# to check for this, if current_object don't add form
|
13
|
+
#
|
14
|
+
# - usage of _position inside means these shortcuts cannot be reused
|
15
|
+
# with other positioning systems, we'll be cut-pasting forever
|
16
|
+
#
|
17
|
+
# == CHANGES
|
18
|
+
# ------------------------------------------------------------ #
|
19
|
+
#
|
20
|
+
|
21
|
+
# what is the real purpose of the shortcuts, is it to avoid putting nil
|
22
|
+
# for form there if not required.
|
23
|
+
# Or is it positioning, such as in a stack. or just a method ?
|
24
|
+
module RubyCurses
|
25
|
+
module WidgetShortcuts
|
26
|
+
class Ws
|
27
|
+
attr_reader :config
|
28
|
+
def initialize config={}
|
29
|
+
@config = config
|
30
|
+
end
|
31
|
+
def [](sym)
|
32
|
+
@config[sym]
|
33
|
+
end
|
34
|
+
def []=(sym, val)
|
35
|
+
@config[sym] = val
|
36
|
+
end
|
37
|
+
end
|
38
|
+
class WsStack < Ws; end
|
39
|
+
class WsFlow < Ws; end
|
40
|
+
def widget_shortcuts_init
|
41
|
+
@_ws_app_row = @_ws_app_col = 0
|
42
|
+
@_ws_active = []
|
43
|
+
@_ws_components = []
|
44
|
+
@variables = {}
|
45
|
+
end
|
46
|
+
def field config={}, &block
|
47
|
+
w = Field.new nil, config #, &block
|
48
|
+
_position w
|
49
|
+
if block
|
50
|
+
w.bind(:CHANGED, &block)
|
51
|
+
end
|
52
|
+
return w
|
53
|
+
end
|
54
|
+
def label config={}, &block
|
55
|
+
w = Label.new nil, config, &block
|
56
|
+
_position w
|
57
|
+
end
|
58
|
+
def blank
|
59
|
+
label :text => ""
|
60
|
+
end
|
61
|
+
def line config={}
|
62
|
+
#horizontal line TODO
|
63
|
+
#row = config[:row] || @app_row
|
64
|
+
#width = config[:width] || 20
|
65
|
+
#_position config
|
66
|
+
#col = config[:col] || 1
|
67
|
+
#@color_pair = config[:color_pair] || $datacolor
|
68
|
+
#@attrib = config[:attrib] || Ncurses::A_NORMAL
|
69
|
+
#@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
|
70
|
+
#@window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width)
|
71
|
+
#@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
|
72
|
+
end
|
73
|
+
def check config={}, &block
|
74
|
+
w = CheckBox.new nil, config #, &block
|
75
|
+
_position w
|
76
|
+
if block
|
77
|
+
w.bind(:PRESS, &block)
|
78
|
+
end
|
79
|
+
return w
|
80
|
+
end
|
81
|
+
def button config={}, &block
|
82
|
+
w = Button.new nil, config #, &block
|
83
|
+
_position w
|
84
|
+
if block
|
85
|
+
w.bind(:PRESS, &block)
|
86
|
+
end
|
87
|
+
return w
|
88
|
+
end
|
89
|
+
def radio config={}, &block
|
90
|
+
a = config[:group]
|
91
|
+
# should we not check for a nil
|
92
|
+
if @variables.has_key? a
|
93
|
+
v = @variables[a]
|
94
|
+
else
|
95
|
+
v = Variable.new
|
96
|
+
@variables[a] = v
|
97
|
+
end
|
98
|
+
config[:variable] = v
|
99
|
+
config.delete(:group)
|
100
|
+
w = RadioButton.new nil, config #, &block
|
101
|
+
_position w
|
102
|
+
if block
|
103
|
+
w.bind(:PRESS, &block)
|
104
|
+
end
|
105
|
+
return w
|
106
|
+
end
|
107
|
+
# editable text area
|
108
|
+
def textarea config={}, &block
|
109
|
+
require 'rbcurse/rtextarea'
|
110
|
+
# TODO confirm events many more
|
111
|
+
events = [ :CHANGE, :LEAVE, :ENTER ]
|
112
|
+
block_event = events[0]
|
113
|
+
#_process_args args, config, block_event, events
|
114
|
+
#config[:width] = config[:display_length] unless config.has_key? :width
|
115
|
+
# if no width given, expand to flows width
|
116
|
+
#config[:width] ||= @stack.last.width if @stack.last
|
117
|
+
useform = nil
|
118
|
+
#useform = @form if @current_object.empty?
|
119
|
+
w = TextArea.new useform, config
|
120
|
+
w.width = :expand unless w.width
|
121
|
+
w.height ||= 8 # TODO
|
122
|
+
_position(w)
|
123
|
+
# need to expand to stack's width or flows itemwidth if given
|
124
|
+
if block
|
125
|
+
w.bind(block_event, &block)
|
126
|
+
end
|
127
|
+
return w
|
128
|
+
end
|
129
|
+
def textview config={}, &block
|
130
|
+
require 'rbcurse/rtextview'
|
131
|
+
events = [ :LEAVE, :ENTER ]
|
132
|
+
block_event = events[0]
|
133
|
+
#_process_args args, config, block_event, events
|
134
|
+
#config[:width] = config[:display_length] unless config.has_key? :width
|
135
|
+
# if no width given, expand to flows width
|
136
|
+
#config[:width] ||= @stack.last.width if @stack.last
|
137
|
+
useform = nil
|
138
|
+
#useform = @form if @current_object.empty?
|
139
|
+
w = TextView.new useform, config
|
140
|
+
w.width = :expand unless w.width
|
141
|
+
w.height ||= 8 # TODO
|
142
|
+
_position(w)
|
143
|
+
# need to expand to stack's width or flows itemwidth if given
|
144
|
+
if block
|
145
|
+
w.bind(block_event, &block)
|
146
|
+
end
|
147
|
+
return w
|
148
|
+
end
|
149
|
+
def _position w
|
150
|
+
cur = @_ws_active.last
|
151
|
+
# this is outside any stack or flow, so we do the minimal
|
152
|
+
# user should specify row and col
|
153
|
+
unless cur
|
154
|
+
w.row ||= 0
|
155
|
+
w.col ||= 0
|
156
|
+
$log.debug "XXX: LABEL #{w.row} , #{w.col} "
|
157
|
+
w.set_form @form if @form # temporary,, only set if not inside an object FIXME
|
158
|
+
if w.width == :expand
|
159
|
+
w.width = FFI::NCurses.COLS-0 # or take windows width since this could be in a message box
|
160
|
+
end
|
161
|
+
if w.height == :expand
|
162
|
+
# take from current row, and not zero FIXME
|
163
|
+
w.height = FFI::NCurses.LINES-0 # or take windows width since this could be in a message box
|
164
|
+
end
|
165
|
+
return
|
166
|
+
end
|
167
|
+
r = cur[:row] || 0
|
168
|
+
c = cur[:col] || 0
|
169
|
+
w.row = r
|
170
|
+
w.col = c
|
171
|
+
if cur.is_a? WsStack
|
172
|
+
r += w.height || 1
|
173
|
+
cur[:row] = r
|
174
|
+
else
|
175
|
+
wid = cur[:item_width] || w.width || 10
|
176
|
+
c += wid + 1
|
177
|
+
cur[:col] = c
|
178
|
+
end
|
179
|
+
if w.width == :expand
|
180
|
+
w.width = cur[:width] or raise "Width not known for stack"
|
181
|
+
end
|
182
|
+
if w.height == :expand
|
183
|
+
w.height = cur[:height] or raise "height not known for flow"
|
184
|
+
end
|
185
|
+
w.color ||= cur[:color]
|
186
|
+
w.bgcolor ||= cur[:bgcolor]
|
187
|
+
w.set_form @form if @form # temporary
|
188
|
+
@_ws_components << w
|
189
|
+
cur[:components] << w
|
190
|
+
end
|
191
|
+
# make it as simple as possible, don't try to be intelligent or
|
192
|
+
# clever, put as much on the user
|
193
|
+
def stack config={}, &block
|
194
|
+
s = WsStack.new config
|
195
|
+
_configure s
|
196
|
+
@_ws_active << s
|
197
|
+
yield_or_eval &block if block_given?
|
198
|
+
@_ws_active.pop
|
199
|
+
|
200
|
+
# ---- stack is finished now
|
201
|
+
last = @_ws_active.last
|
202
|
+
if last
|
203
|
+
case last
|
204
|
+
when WsStack
|
205
|
+
when WsFlow
|
206
|
+
last[:col] += last[:item_width] || 0
|
207
|
+
# this tries to set height of outer flow based on highest row
|
208
|
+
# printed, however that does not account for height of object,
|
209
|
+
# so user should give a height to the flow.
|
210
|
+
last[:height] = s[:row] if s[:row] > (last[:height]||0)
|
211
|
+
$log.debug "XXX: STACK setting col to #{s[:col]} "
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
#
|
217
|
+
# item_width - width to use per item
|
218
|
+
# but the item width may apply to stacks inside not to items
|
219
|
+
def flow config={}, &block
|
220
|
+
s = WsFlow.new config
|
221
|
+
_configure s
|
222
|
+
@_ws_active << s
|
223
|
+
yield_or_eval &block if block_given?
|
224
|
+
@_ws_active.pop
|
225
|
+
last = @_ws_active.last
|
226
|
+
if last
|
227
|
+
case last
|
228
|
+
when WsStack
|
229
|
+
if s[:height]
|
230
|
+
last[:row] += s[:height]
|
231
|
+
else
|
232
|
+
#last[:row] += last[:highest_row]
|
233
|
+
last[:row] += 1
|
234
|
+
end
|
235
|
+
when WsFlow
|
236
|
+
last[:col] += last[:item_width] || 0
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
# flow and stack could have a border option
|
241
|
+
def box config={}, &block
|
242
|
+
require 'rbcurse/extras/box'
|
243
|
+
# take current stacks row and col
|
244
|
+
# advance row by one and col by one
|
245
|
+
# at end note row and advance by one
|
246
|
+
# draw a box around using these coordinates. width should be
|
247
|
+
# provided unless we have item width or something.
|
248
|
+
last = @_ws_active.last
|
249
|
+
if last
|
250
|
+
r = last[:row]
|
251
|
+
c = last[:col]
|
252
|
+
config[:row] = r
|
253
|
+
config[:col] = c
|
254
|
+
last[:row] += config[:margin_top] || 1
|
255
|
+
last[:col] += config[:margin_left] || 1
|
256
|
+
_box = Box.new @form, config # needs to be created first or will overwrite area after others painted
|
257
|
+
yield_or_eval &block if block_given?
|
258
|
+
h = config[:height] || last[:height] || (last[:row] - r)
|
259
|
+
h = 2 if h < 2
|
260
|
+
w = config[:width] || last[:width] || 15 # tmp
|
261
|
+
case last
|
262
|
+
when WsFlow
|
263
|
+
w = last[:col]
|
264
|
+
when WsStack
|
265
|
+
#h += 1
|
266
|
+
end
|
267
|
+
config[:row] = r
|
268
|
+
config[:col] = c
|
269
|
+
config[:height] = h
|
270
|
+
config[:width] = w
|
271
|
+
_box.row r
|
272
|
+
_box.col c
|
273
|
+
_box.height h
|
274
|
+
_box.width w
|
275
|
+
last[:row] += 1
|
276
|
+
last[:col] += 1 # ??? XXX if flow we need to increment properly or not ?
|
277
|
+
end
|
278
|
+
end
|
279
|
+
def _configure s
|
280
|
+
s[:row] ||= 0
|
281
|
+
s[:col] ||= 0
|
282
|
+
s[:row] += (s[:margin_top] || 0)
|
283
|
+
s[:col] += (s[:margin_left] || 0)
|
284
|
+
s[:width] = FFI::NCurses.COLS if s[:width] == :expand
|
285
|
+
last = @_ws_active.last
|
286
|
+
if last
|
287
|
+
if last.is_a? WsStack
|
288
|
+
s[:row] += (last[:row] || 0)
|
289
|
+
s[:col] += (last[:col] || 0)
|
290
|
+
else
|
291
|
+
s[:row] += (last[:row] || 0)
|
292
|
+
s[:col] += (last[:col] || 0) # we are updating with item_width as each st finishes
|
293
|
+
s[:width] ||= last[:item_width] #
|
294
|
+
end
|
295
|
+
end
|
296
|
+
s[:components] = []
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|