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
@@ -1,5 +1,21 @@
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
2
|
+
# File: applicationheader.rb
|
3
|
+
# Description: Prints a header on first row, with right, left and centered text
|
4
|
+
# NOTE: on some terminal such as xterm-256color spaces do not print
|
5
|
+
# so you will see black or empty spaces between text.
|
6
|
+
# This does not happen on screen and xterm-color.
|
7
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
8
|
+
# Date:
|
9
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
10
|
+
# Last update: 2011-11-16 - 00:07
|
11
|
+
#
|
12
|
+
# CHANGES:
|
13
|
+
# For some terminals, like xterm-256color which were not printing spaces
|
14
|
+
# I've changed to code so only text is printed where it has to with no
|
15
|
+
# padding. These terminals remove the padding color.
|
16
|
+
# ----------------------------------------------------------------------------- #
|
17
|
+
#
|
1
18
|
require 'rbcurse/rwidget'
|
2
|
-
#include Ncurses # FFI 2011-09-8
|
3
19
|
include RubyCurses
|
4
20
|
module RubyCurses
|
5
21
|
class ApplicationHeader < Widget
|
@@ -39,20 +55,44 @@ module RubyCurses
|
|
39
55
|
return unless @repaint_required
|
40
56
|
|
41
57
|
#print_header(htext, posy = 0, posx = 0)
|
42
|
-
|
58
|
+
att = get_attrib @attr
|
59
|
+
len = @window.width
|
60
|
+
len = Ncurses.COLS-0 if len == 0
|
61
|
+
# print a bar across the screen
|
62
|
+
@window.attron(Ncurses.COLOR_PAIR(@color_pair) | att)
|
63
|
+
@window.mvhline(@row, @col, 1, len)
|
64
|
+
@window.attroff(Ncurses.COLOR_PAIR(@color_pair) | att)
|
65
|
+
#print_header(@text1 + " %15s " % @text2 + " %20s" % @text_center , posy=0, posx=0)
|
66
|
+
|
67
|
+
# Now print the text in the correct positions with no padding, else some terminal
|
68
|
+
# will blacken the text out.
|
69
|
+
print_header("#{@text1} #{@text2}") # + " %20s" % @text_center , posy=0, posx=0)
|
70
|
+
print_center("#{@text_center}") # + " %20s" % @text_center , posy=0, posx=0)
|
43
71
|
print_top_right(@text_right)
|
44
72
|
@repaint_required = false
|
45
73
|
end
|
46
74
|
def print_header(htext, r = 0, c = 0)
|
47
|
-
|
75
|
+
#win = @window
|
76
|
+
#len = @window.width
|
77
|
+
#len = Ncurses.COLS-0 if len == 0
|
78
|
+
#
|
79
|
+
#@form.window.printstring r, c, "%-*s" % [len, htext], @color_pair, @attr
|
80
|
+
@form.window.printstring r, c, htext, @color_pair, @attr
|
81
|
+
end
|
82
|
+
def print_center(htext, r = 0, c = 0)
|
48
83
|
win = @window
|
49
|
-
len =
|
50
|
-
|
84
|
+
len = win.width
|
85
|
+
len = Ncurses.COLS-0 if len == 0
|
86
|
+
#
|
87
|
+
#@form.window.printstring r, c, "%-*s" % [len, htext], @color_pair, @attr
|
88
|
+
win.printstring r, ((len-htext.length)/2).floor, htext, @color_pair, @attr
|
51
89
|
end
|
52
90
|
def print_top_right(htext)
|
53
91
|
$log.debug " def print_top_right(#{htext})"
|
54
92
|
hlen = htext.length
|
55
|
-
len = Ncurses.COLS-
|
93
|
+
len = Ncurses.COLS-0
|
94
|
+
len = @window.width
|
95
|
+
len = Ncurses.COLS-0 if len == 0
|
56
96
|
@form.window.printstring 0, len-hlen, htext, @color_pair, @attr
|
57
97
|
end
|
58
98
|
##
|
data/lib/rbcurse/celleditor.rb
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
#require 'ncurses'
|
3
|
-
require 'logger'
|
4
|
-
#require 'lib/rbcurse/rwidget'
|
5
|
-
|
6
1
|
|
7
2
|
##
|
8
3
|
# This file gives us a mean of using a component as an editor in a list or later table.
|
@@ -23,7 +18,6 @@ module RubyCurses
|
|
23
18
|
s = @component.class.to_s.downcase()
|
24
19
|
s.slice!("rubycurses::")
|
25
20
|
@_class = s.to_sym
|
26
|
-
#$log.debug " CELL EIDOTR got #{@_class}"
|
27
21
|
config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
|
28
22
|
instance_eval &block if block_given?
|
29
23
|
end
|
@@ -75,7 +69,6 @@ module RubyCurses
|
|
75
69
|
f = @component
|
76
70
|
f.on_leave
|
77
71
|
if f.respond_to? :editable and f.modified?
|
78
|
-
$log.debug " Table about to fire CHANGED for #{f} "
|
79
72
|
f.fire_handler(:CHANGED, f)
|
80
73
|
end
|
81
74
|
end
|
@@ -97,13 +90,12 @@ module RubyCurses
|
|
97
90
|
widget.visible = true
|
98
91
|
widget.form = parent.form
|
99
92
|
#$log.debug " prepare editor value #{widget.display_length} displlen #{widget.maxlen}"
|
100
|
-
|
93
|
+
#$log.debug " prepare editor form: #{widget.form} " # 2011-11-15 12:54:41
|
101
94
|
#widget.display_length = widget.display_length -1
|
102
95
|
widget.bgcolor = 'yellow'
|
103
96
|
widget.color = 'black'
|
104
97
|
widget.on_enter
|
105
98
|
#widget.attr = Ncurses::A_REVERSE | Ncurses::A_BOLD
|
106
|
-
#$log.debug " prepare editor value #{value} : fr:#{row}, fc:#{col}"
|
107
99
|
end
|
108
100
|
#This may not really be necessary since we paint the cell editor only if editing is on
|
109
101
|
def cancel_editor
|
@@ -0,0 +1,117 @@
|
|
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 AnsiParser
|
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 = s.split /(\x1b\[\d*(?:;\d+)*?[a-zA-Z])/
|
37
|
+
a.each { |e|
|
38
|
+
## process color or attrib portion
|
39
|
+
#[ "", "\e[1m", "", "\e[34m", "", "\e[47m", "Showing all items...", "\e[0m", "", "\e[0m", "\n"]
|
40
|
+
if e[0] == "\x1b" && e[-1] == "m"
|
41
|
+
|
42
|
+
#e.each { |f| x=/^.\[(.*).$/.match(f)
|
43
|
+
$log.debug "XXX: ANSI e #{e} "
|
44
|
+
x=/^.\[(.*).$/.match(e)
|
45
|
+
color, bgcolor, attrib = nil, nil, nil
|
46
|
+
$log.debug "XXX: ANSI #{x} ..... #{x[1]} "
|
47
|
+
args = x[1].split ';'
|
48
|
+
## first split on commas to separate fg, bg and attr
|
49
|
+
# http://ascii-table.com/ansi-escape-sequences.php
|
50
|
+
args.each { |att|
|
51
|
+
$log.debug "XXX: ANSI att: #{att} "
|
52
|
+
case att.to_i
|
53
|
+
when 0
|
54
|
+
color, bgcolor, attrib = nil, nil, nil
|
55
|
+
yield :reset # actually this resets all so we need an endall or clearall reset
|
56
|
+
|
57
|
+
when 1
|
58
|
+
attrib = 'bold'
|
59
|
+
when 2
|
60
|
+
attrib = 'dim'
|
61
|
+
when 4
|
62
|
+
attrib = 'underline'
|
63
|
+
when 5
|
64
|
+
attrib = 'blink'
|
65
|
+
when 7
|
66
|
+
attrib = 'reverse'
|
67
|
+
when 8
|
68
|
+
attrib = 'hidden' # XXX
|
69
|
+
when 30
|
70
|
+
color = 'black'
|
71
|
+
when 31
|
72
|
+
color = 'red'
|
73
|
+
when 32
|
74
|
+
color = 'green'
|
75
|
+
when 33
|
76
|
+
color = 'yellow'
|
77
|
+
when 34
|
78
|
+
color = 'blue'
|
79
|
+
when 35
|
80
|
+
color = 'magenta'
|
81
|
+
when 36
|
82
|
+
color = 'cyan'
|
83
|
+
when 37
|
84
|
+
color = 'white'
|
85
|
+
|
86
|
+
#Background colors
|
87
|
+
when 40
|
88
|
+
bgcolor = 'black'
|
89
|
+
when 41
|
90
|
+
bgcolor = 'red'
|
91
|
+
when 42
|
92
|
+
bgcolor = 'green'
|
93
|
+
when 43
|
94
|
+
bgcolor = 'yellow'
|
95
|
+
when 44
|
96
|
+
bgcolor = 'blue'
|
97
|
+
when 45
|
98
|
+
bgcolor = 'magenta'
|
99
|
+
when 46
|
100
|
+
bgcolor = 'cyan'
|
101
|
+
when 47
|
102
|
+
bgcolor = 'white'
|
103
|
+
else
|
104
|
+
$log.warn "XXX: WARN ANSI not used #{att} "
|
105
|
+
end
|
106
|
+
} # args.ea
|
107
|
+
#} # e.each
|
108
|
+
$log.debug "XXX: ANSI YIELDING #{color} , #{bgcolor} , #{attrib} "
|
109
|
+
yield [color,bgcolor,attrib] if block_given?
|
110
|
+
else
|
111
|
+
text = e
|
112
|
+
yield text if block_given?
|
113
|
+
end
|
114
|
+
} # a.each
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module RubyCurses
|
2
2
|
module Utils
|
3
|
+
private
|
3
4
|
def _suspend clear=true
|
4
5
|
return unless block_given?
|
5
6
|
Ncurses.def_prog_mode
|
@@ -22,6 +23,11 @@ module RubyCurses
|
|
22
23
|
@window.wrefresh if @window
|
23
24
|
Ncurses::Panel.update_panels
|
24
25
|
end
|
26
|
+
#
|
27
|
+
# Suspends to shell so user can execute commands.
|
28
|
+
# Maybe not be able to get your prompt correctly.
|
29
|
+
#
|
30
|
+
public
|
25
31
|
def suspend
|
26
32
|
_suspend(false) do
|
27
33
|
system("tput cup 26 0")
|
@@ -32,6 +38,10 @@ module RubyCurses
|
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
41
|
+
#
|
42
|
+
# Displays application help using either array provided
|
43
|
+
# or checking for :help_text method
|
44
|
+
# @param [Array] help text
|
35
45
|
def display_app_help help_array= nil
|
36
46
|
if help_array
|
37
47
|
arr = help_array
|
@@ -64,12 +74,19 @@ module RubyCurses
|
|
64
74
|
t.attr = :reverse
|
65
75
|
end
|
66
76
|
end
|
77
|
+
#
|
78
|
+
# prompts user for unix command and displays output in viewer
|
79
|
+
#
|
67
80
|
def shell_output
|
68
81
|
cmd = get_string("Enter shell command:", 50)
|
69
82
|
if cmd && !cmd.empty?
|
70
83
|
run_command cmd
|
71
84
|
end
|
72
85
|
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# executes given command and displays in viewer
|
89
|
+
# @param [String] unix command, e.g., git -st
|
73
90
|
def run_command cmd
|
74
91
|
# http://whynotwiki.com/Ruby_/_Process_management#What_happens_to_standard_error_.28stderr.29.3F
|
75
92
|
require 'rbcurse/extras/viewer'
|
@@ -82,6 +99,14 @@ module RubyCurses
|
|
82
99
|
res.gsub!("\t"," ")
|
83
100
|
RubyCurses::Viewer.view(res.split("\n"), :close_key => KEY_RETURN, :title => "<Enter> to close, M-l M-h to scroll")
|
84
101
|
end
|
102
|
+
def shell_out command
|
103
|
+
@window.hide
|
104
|
+
Ncurses.endwin
|
105
|
+
system command
|
106
|
+
Ncurses.refresh
|
107
|
+
#Ncurses.curs_set 0 # why ?
|
108
|
+
@window.show
|
109
|
+
end
|
85
110
|
end # utils
|
86
111
|
end # module RubyC
|
87
112
|
include RubyCurses::Utils
|
@@ -0,0 +1,407 @@
|
|
1
|
+
#
|
2
|
+
# Common stack flow functionality
|
3
|
+
# * Name: basestack.rb
|
4
|
+
# * Description: Classes that allow user to stack and flow components
|
5
|
+
#
|
6
|
+
# * Date: 30.10.11 - 12:57
|
7
|
+
# * Last update: 30.10.11 - 12:57
|
8
|
+
#
|
9
|
+
module RubyCurses
|
10
|
+
module ModStack
|
11
|
+
#
|
12
|
+
# Base class for stacks and flows.
|
13
|
+
# Will manage determining row col and width height of objects
|
14
|
+
# Stacks place objects one below another. Flows place objects to the
|
15
|
+
# right of the previous. Orientation can be reversed.
|
16
|
+
#
|
17
|
+
class BaseStack
|
18
|
+
attr_accessor :components
|
19
|
+
attr_reader :config
|
20
|
+
attr_accessor :form
|
21
|
+
def initialize config={}, components=[]
|
22
|
+
@config = config
|
23
|
+
config.each do |k, v|
|
24
|
+
instance_variable_set "@#{k}", v
|
25
|
+
end
|
26
|
+
@components = components
|
27
|
+
@calc_needed = true
|
28
|
+
end
|
29
|
+
# XXX if user sets later, we won't be checking the config
|
30
|
+
# We check the actual variables which config sets in init
|
31
|
+
%w[ parent_component width height weight row col orientation].each { |e|
|
32
|
+
eval(
|
33
|
+
"def #{e}
|
34
|
+
@config[:#{e}]
|
35
|
+
end
|
36
|
+
def #{e}=(val)
|
37
|
+
@config[:#{e}]=val
|
38
|
+
instance_variable_set \"@#{e}\", val
|
39
|
+
@calc_needed = true
|
40
|
+
end"
|
41
|
+
)
|
42
|
+
}
|
43
|
+
alias :parent :parent_component
|
44
|
+
#alias :parent= :parent_component
|
45
|
+
def repaint # stack
|
46
|
+
$log.debug "XXX: stack repaint recalc #{@calc_needed} "
|
47
|
+
@components.each { |e| e.form = @form unless e.form } #unless @calc_needed
|
48
|
+
recalc if @calc_needed
|
49
|
+
@components.each { |e| e.repaint }
|
50
|
+
end
|
51
|
+
def repaint_all x
|
52
|
+
@calc_needed = true
|
53
|
+
end
|
54
|
+
def override_graphic gr
|
55
|
+
@graphic = gr
|
56
|
+
end
|
57
|
+
def focusable; false; end
|
58
|
+
# Calculates row col and width height
|
59
|
+
# for each subc-omponent based on coords of Container
|
60
|
+
# This is to be called only when the container has got its coordinates (i.e
|
61
|
+
# Containers repaint). This should be in this objects repaint.
|
62
|
+
def recalc
|
63
|
+
@calc_needed = false
|
64
|
+
comp = self
|
65
|
+
if comp.is_a? BaseStack
|
66
|
+
check_coords comp
|
67
|
+
@margin_left ||= 0
|
68
|
+
@margin_right ||= 0
|
69
|
+
@margin_top ||= 0
|
70
|
+
@margin_bottom ||= 0
|
71
|
+
if comp.is_a? Stack
|
72
|
+
r = row + @margin_top
|
73
|
+
rem = 0
|
74
|
+
ht = height - (@margin_top + @margin_bottom)
|
75
|
+
if @orientation == :bottom
|
76
|
+
mult = -1
|
77
|
+
comps = @components.reverse
|
78
|
+
r = row + height - @margin_bottom
|
79
|
+
|
80
|
+
else
|
81
|
+
mult = 1
|
82
|
+
comps = @components
|
83
|
+
|
84
|
+
end
|
85
|
+
comps.each { |e|
|
86
|
+
# should only happen if expandable FIXME
|
87
|
+
e.height = 0.01 * e.weight * (ht - (e.margin_top + e.margin_bottom))
|
88
|
+
hround = e.height.floor
|
89
|
+
rem += e.height - hround
|
90
|
+
e.height = hround #- (@margin_top + @margin_bottom)
|
91
|
+
# rounding creates a problem, since 0.5 gets rounded up and we can exceed bound
|
92
|
+
# So i floor, and maintain the lost space, and add it back when it exceeds 1
|
93
|
+
# This way the last components gets stretched to meet the end, which is required
|
94
|
+
# when the height of the stack is odd and there's a left-over row
|
95
|
+
if rem >= 1
|
96
|
+
e.height += 1
|
97
|
+
rem = 0
|
98
|
+
end
|
99
|
+
# Item level margins have not been accounted for when calculating weightages, and
|
100
|
+
# should not be used on the weightage axis
|
101
|
+
r += e.margin_top
|
102
|
+
if @orientation == :bottom
|
103
|
+
r += e.height * mult
|
104
|
+
e.row = r
|
105
|
+
else
|
106
|
+
e.row = r
|
107
|
+
r += e.height + 0
|
108
|
+
end
|
109
|
+
e.width = width - (@margin_left + @margin_right + e.margin_left + e.margin_right)
|
110
|
+
e.col = col + @margin_left + e.margin_left # ??? XXX
|
111
|
+
$log.debug "XXX: recalc stack #{e.widget.class} r:#{e.row} c:#{e.col} h:#{e.height} = we:#{e.weight} * h:#{height} "
|
112
|
+
#e.col_offset = col_offset # ??? XXX
|
113
|
+
check_coords e
|
114
|
+
e.repaint_all(true)
|
115
|
+
e.recalc if e.is_a? BaseStack
|
116
|
+
}
|
117
|
+
elsif comp.is_a? Flow
|
118
|
+
c = col + @margin_left #+ col_offset
|
119
|
+
rem = 0
|
120
|
+
wd = width - (@margin_left + @margin_right)
|
121
|
+
# right_to_left orientation
|
122
|
+
if @orientation == :right
|
123
|
+
mult = -1
|
124
|
+
comps = @components.reverse
|
125
|
+
c = col + width - @margin_right
|
126
|
+
$log.debug "XXX: ORIENT1f recalc #{@orientation} "
|
127
|
+
else
|
128
|
+
mult = 1
|
129
|
+
comps = @components
|
130
|
+
$log.debug "XXX: ORIENT2f recalc #{@orientation} "
|
131
|
+
end
|
132
|
+
comps.each { |e|
|
133
|
+
e.width = e.weight * wd * 0.01
|
134
|
+
wround = e.width.floor
|
135
|
+
rem += e.width - wround
|
136
|
+
e.width = wround
|
137
|
+
# see comment in prev block regarding remaininder
|
138
|
+
if rem >= 1
|
139
|
+
e.width += 1
|
140
|
+
rem = 0
|
141
|
+
end
|
142
|
+
e.height = height - (@margin_top + @margin_bottom) #* weight * 0.01
|
143
|
+
#e.height = e.height.round
|
144
|
+
if @orientation == :right
|
145
|
+
c += e.width * mult # mult 1 or -1
|
146
|
+
e.col = c
|
147
|
+
else
|
148
|
+
e.col = c
|
149
|
+
c += e.width * mult # mult 1 or -1
|
150
|
+
end
|
151
|
+
e.row = row + @margin_top
|
152
|
+
check_coords e
|
153
|
+
$log.debug "XXX: recalc flow #{e.widget.class} r:#{e.row} c:#{e.col} h:#{e.height} = we:#{e.weight} * w:#{width} "
|
154
|
+
e.repaint_all(true) # why not happening when we change row, hieght etc
|
155
|
+
e.recalc if e.is_a? BaseStack
|
156
|
+
}
|
157
|
+
end
|
158
|
+
else
|
159
|
+
alert "in else recalc DOES NOT COME HERE "
|
160
|
+
comp.col = comp.parent.col
|
161
|
+
comp.row = comp.parent.row
|
162
|
+
comp.height = comp.parent.height
|
163
|
+
comp.width = comp.parent.width
|
164
|
+
$log.debug "XXX: recalc else #{comp.class} r #{comp.row} c #{comp.col} . h #{comp} height w #{comp.width} "
|
165
|
+
end
|
166
|
+
end
|
167
|
+
# Traverses the comopnent tree and calculates weightages for all components
|
168
|
+
# based on what has been specified by user
|
169
|
+
def check_coords e # stack
|
170
|
+
r = e.row
|
171
|
+
c = e.col
|
172
|
+
if r >= row + height
|
173
|
+
$log.warn "XXX: WARN e.class is out of bounds row #{r} "
|
174
|
+
e.visible = false
|
175
|
+
end
|
176
|
+
if c >= col + width
|
177
|
+
$log.warn "XXX: WARN e.class is out of bounds col #{c} "
|
178
|
+
e.visible = false
|
179
|
+
end
|
180
|
+
end
|
181
|
+
def increase c=@current_component
|
182
|
+
p = self #c.parent_component
|
183
|
+
ci = p.components.index(c)
|
184
|
+
ni = ci + 1
|
185
|
+
if p.components[ni].nil?
|
186
|
+
ni = nil
|
187
|
+
end
|
188
|
+
case p
|
189
|
+
when Flow
|
190
|
+
# increase width of current and reduce from neighbor
|
191
|
+
if ni
|
192
|
+
n = p.components[ni]
|
193
|
+
$log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
|
194
|
+
|
195
|
+
c.width += 1
|
196
|
+
n.width -= 1
|
197
|
+
n.col += 1
|
198
|
+
end
|
199
|
+
|
200
|
+
when Stack
|
201
|
+
if ni
|
202
|
+
n = p.components[ni]
|
203
|
+
$log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
|
204
|
+
|
205
|
+
c.height += 1
|
206
|
+
n.height -= 1
|
207
|
+
n.row += 1
|
208
|
+
end
|
209
|
+
$log.debug "XXX: INC st current #{ci}, total#{p.components.count} "
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
def decrease c=@current_component
|
214
|
+
p = self #c.parent_component
|
215
|
+
ci = p.components.index(c)
|
216
|
+
ni = ci + 1
|
217
|
+
if p.components[ni].nil?
|
218
|
+
ni = nil
|
219
|
+
end
|
220
|
+
case p
|
221
|
+
when Flow
|
222
|
+
# increase width of current and reduce from neighbor
|
223
|
+
if ni
|
224
|
+
n = p.components[ni]
|
225
|
+
$log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
|
226
|
+
|
227
|
+
c.width -= 1
|
228
|
+
n.width += 1
|
229
|
+
n.col -= 1
|
230
|
+
end
|
231
|
+
|
232
|
+
when Stack
|
233
|
+
if ni
|
234
|
+
n = p.components[ni]
|
235
|
+
$log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
|
236
|
+
|
237
|
+
c.height -= 1
|
238
|
+
n.height += 1
|
239
|
+
n.row -= 1
|
240
|
+
end
|
241
|
+
$log.debug "XXX: INC st current #{ci}, total#{p.components.count} "
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
def to_s
|
246
|
+
@components
|
247
|
+
end
|
248
|
+
end # class Base
|
249
|
+
# A stack positions objects one below the other
|
250
|
+
class Stack < BaseStack; end
|
251
|
+
# A flow positions objects in a left to right
|
252
|
+
class Flow < BaseStack; end
|
253
|
+
#
|
254
|
+
# A wrapper over widget mostly because it adds weight and margins
|
255
|
+
#
|
256
|
+
class Item
|
257
|
+
attr_reader :config, :widget
|
258
|
+
attr_reader :margin_top, :margin_left, :margin_bottom, :margin_right
|
259
|
+
def initialize config={}, widget
|
260
|
+
@config = config
|
261
|
+
config.each do |k, v|
|
262
|
+
instance_variable_set "@#{k}", v
|
263
|
+
end
|
264
|
+
@margin_left ||= 0
|
265
|
+
@margin_right ||= 0
|
266
|
+
@margin_top ||= 0
|
267
|
+
@margin_bottom ||= 0
|
268
|
+
@widget = widget
|
269
|
+
end
|
270
|
+
def weight; @config[:weight]||100; end
|
271
|
+
def weight=(val); @config[:weight]=val; end
|
272
|
+
def repaint; @widget.repaint; end
|
273
|
+
%w[ form parent parent_component width height row col row_offset col_offset focusable].each { |e|
|
274
|
+
eval(
|
275
|
+
"def #{e}
|
276
|
+
@widget.#{e}
|
277
|
+
end
|
278
|
+
def #{e}=(val)
|
279
|
+
@widget.#{e}=val
|
280
|
+
end"
|
281
|
+
)
|
282
|
+
}
|
283
|
+
def method_missing(sym, *args, &block)
|
284
|
+
@widget.send sym, *args, &block
|
285
|
+
end
|
286
|
+
end # class Item
|
287
|
+
|
288
|
+
# --------------------- module level ------------------------------#
|
289
|
+
# General routin to traverse components and their components
|
290
|
+
def traverse c, &block
|
291
|
+
if c.is_a? BaseStack
|
292
|
+
yield c
|
293
|
+
c.components.each { |e|
|
294
|
+
yield e
|
295
|
+
}
|
296
|
+
c.components.each { |e| traverse(e, &block) }
|
297
|
+
@ctr -= 1
|
298
|
+
else
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# traverse the components and their children
|
303
|
+
#
|
304
|
+
def each &block
|
305
|
+
@components.each { |e| traverse e, &block }
|
306
|
+
end
|
307
|
+
# module level
|
308
|
+
private
|
309
|
+
def _stack type, config={}, &block
|
310
|
+
case type
|
311
|
+
when :stack
|
312
|
+
s = Stack.new(config)
|
313
|
+
when :flow
|
314
|
+
s = Flow.new(config)
|
315
|
+
end
|
316
|
+
_add s
|
317
|
+
@active << s
|
318
|
+
yield_or_eval &block if block_given?
|
319
|
+
@active.pop
|
320
|
+
# if active is empty then this is where we could calculate
|
321
|
+
# percentatges and do recalc, thus making it independent
|
322
|
+
end
|
323
|
+
# module level
|
324
|
+
private
|
325
|
+
private
|
326
|
+
def _add s
|
327
|
+
if @active.empty?
|
328
|
+
$log.debug "XXX: ADDING TO components #{s} "
|
329
|
+
unless s.is_a? BaseStack
|
330
|
+
raise "No stack or flow to add to. Results may not be what you want"
|
331
|
+
end
|
332
|
+
@components << s
|
333
|
+
else
|
334
|
+
@active.last.components << s
|
335
|
+
end
|
336
|
+
__add s
|
337
|
+
end
|
338
|
+
|
339
|
+
# module level
|
340
|
+
private
|
341
|
+
public
|
342
|
+
def stack config={}, &block
|
343
|
+
_stack :stack, config, &block
|
344
|
+
end
|
345
|
+
def flow config={}, &block
|
346
|
+
_stack :flow, config, &block
|
347
|
+
end
|
348
|
+
# module level
|
349
|
+
private
|
350
|
+
def add w, config={}
|
351
|
+
i = Item.new config, w
|
352
|
+
_add i
|
353
|
+
end
|
354
|
+
alias :add_widget :add
|
355
|
+
# module level
|
356
|
+
private
|
357
|
+
def calc_weightages2 components, parent
|
358
|
+
#puts " #{@ctr} --> #{c.type}, wt: #{c.config[:weight]} "
|
359
|
+
@ctr += 1
|
360
|
+
wt = 0
|
361
|
+
cnt = 0
|
362
|
+
sz = components.count
|
363
|
+
$log.debug "XXX: calc COMP COUNT #{sz} "
|
364
|
+
# calculate how much weightage has been given by user
|
365
|
+
# so we can allocate average to other components
|
366
|
+
components.each { |e|
|
367
|
+
if e.config[:weight]
|
368
|
+
wt += e.config[:weight]
|
369
|
+
cnt += 1
|
370
|
+
end
|
371
|
+
$log.debug "XXX: INC setting parent #{parent} to #{e} "
|
372
|
+
e.config[:parent] = parent
|
373
|
+
e.config[:level] = @ctr
|
374
|
+
}
|
375
|
+
used = sz - cnt
|
376
|
+
$log.debug "XXX: ADDING calc COMP COUNT #{sz} - #{cnt} "
|
377
|
+
if used > 0
|
378
|
+
avg = (100-wt)/used
|
379
|
+
# Allocate average to other components
|
380
|
+
components.each { |e| e.config[:weight] = avg unless e.config[:weight] }
|
381
|
+
end
|
382
|
+
components.each { |e| calc_weightages2(e.components, e) if e.respond_to? :components }
|
383
|
+
@ctr -= 1
|
384
|
+
end
|
385
|
+
# module level
|
386
|
+
private
|
387
|
+
# given an widget, return the item, so we can change weight or some other config
|
388
|
+
def item_for widget
|
389
|
+
each do |e|
|
390
|
+
if e.is_a? Item
|
391
|
+
if e.widget == widget
|
392
|
+
return e
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
return nil
|
397
|
+
end
|
398
|
+
# module level
|
399
|
+
# returns the parent (flow or stack) for a given widget
|
400
|
+
# allowing user to change configuration such as weight
|
401
|
+
def parent_of widget
|
402
|
+
f = item_for widget
|
403
|
+
return f.config[:parent] if f
|
404
|
+
return nil
|
405
|
+
end
|
406
|
+
end # mod modstack
|
407
|
+
end # mod
|