rbcurse-core 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +69 -0
- data/VERSION +1 -0
- data/examples/abasiclist.rb +151 -0
- data/examples/alpmenu.rb +46 -0
- data/examples/app.sample +17 -0
- data/examples/atree.rb +100 -0
- data/examples/common/file.rb +45 -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/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +487 -0
- data/examples/dirtree.rb +90 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +132 -0
- data/examples/tasks.rb +167 -0
- data/examples/term2.rb +83 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +158 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +127 -0
- data/lib/rbcurse.rb +8 -0
- data/lib/rbcurse/core/docs/index.txt +73 -0
- data/lib/rbcurse/core/include/action.rb +40 -0
- data/lib/rbcurse/core/include/appmethods.rb +112 -0
- data/lib/rbcurse/core/include/bordertitle.rb +41 -0
- data/lib/rbcurse/core/include/chunk.rb +182 -0
- data/lib/rbcurse/core/include/io.rb +953 -0
- data/lib/rbcurse/core/include/listcellrenderer.rb +140 -0
- data/lib/rbcurse/core/include/listeditable.rb +317 -0
- data/lib/rbcurse/core/include/listscrollable.rb +590 -0
- data/lib/rbcurse/core/include/listselectable.rb +264 -0
- data/lib/rbcurse/core/include/multibuffer.rb +83 -0
- data/lib/rbcurse/core/include/orderedhash.rb +77 -0
- data/lib/rbcurse/core/include/ractionevent.rb +67 -0
- data/lib/rbcurse/core/include/rchangeevent.rb +27 -0
- data/lib/rbcurse/core/include/rhistory.rb +62 -0
- data/lib/rbcurse/core/include/rinputdataevent.rb +47 -0
- data/lib/rbcurse/core/include/vieditable.rb +170 -0
- data/lib/rbcurse/core/system/colormap.rb +163 -0
- data/lib/rbcurse/core/system/keyboard.rb +150 -0
- data/lib/rbcurse/core/system/keydefs.rb +30 -0
- data/lib/rbcurse/core/system/ncurses.rb +218 -0
- data/lib/rbcurse/core/system/panel.rb +162 -0
- data/lib/rbcurse/core/system/window.rb +901 -0
- data/lib/rbcurse/core/util/ansiparser.rb +117 -0
- data/lib/rbcurse/core/util/app.rb +1235 -0
- data/lib/rbcurse/core/util/basestack.rb +407 -0
- data/lib/rbcurse/core/util/bottomline.rb +1850 -0
- data/lib/rbcurse/core/util/colorparser.rb +71 -0
- data/lib/rbcurse/core/util/focusmanager.rb +31 -0
- data/lib/rbcurse/core/util/padreader.rb +189 -0
- data/lib/rbcurse/core/util/rcommandwindow.rb +587 -0
- data/lib/rbcurse/core/util/rdialogs.rb +619 -0
- data/lib/rbcurse/core/util/viewer.rb +149 -0
- data/lib/rbcurse/core/util/widgetshortcuts.rb +505 -0
- data/lib/rbcurse/core/widgets/applicationheader.rb +102 -0
- data/lib/rbcurse/core/widgets/box.rb +58 -0
- data/lib/rbcurse/core/widgets/divider.rb +310 -0
- data/lib/rbcurse/core/widgets/keylabelprinter.rb +178 -0
- data/lib/rbcurse/core/widgets/rcombo.rb +238 -0
- data/lib/rbcurse/core/widgets/rcontainer.rb +415 -0
- data/lib/rbcurse/core/widgets/rlink.rb +30 -0
- data/lib/rbcurse/core/widgets/rlist.rb +723 -0
- data/lib/rbcurse/core/widgets/rmenu.rb +939 -0
- data/lib/rbcurse/core/widgets/rmenulink.rb +22 -0
- data/lib/rbcurse/core/widgets/rmessagebox.rb +373 -0
- data/lib/rbcurse/core/widgets/rprogress.rb +118 -0
- data/lib/rbcurse/core/widgets/rtabbedpane.rb +615 -0
- data/lib/rbcurse/core/widgets/rtabbedwindow.rb +68 -0
- data/lib/rbcurse/core/widgets/rtextarea.rb +920 -0
- data/lib/rbcurse/core/widgets/rtextview.rb +780 -0
- data/lib/rbcurse/core/widgets/rtree.rb +787 -0
- data/lib/rbcurse/core/widgets/rwidget.rb +3040 -0
- data/lib/rbcurse/core/widgets/scrollbar.rb +143 -0
- data/lib/rbcurse/core/widgets/statusline.rb +94 -0
- data/lib/rbcurse/core/widgets/tabular.rb +264 -0
- data/lib/rbcurse/core/widgets/tabularwidget.rb +1211 -0
- data/lib/rbcurse/core/widgets/textpad.rb +516 -0
- data/lib/rbcurse/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbcurse/core/widgets/tree/treemodel.rb +428 -0
- metadata +156 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'rbcurse/core/widgets/rtextview'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
# NOTE: experimental, not yet firmed up
|
5
|
+
# If you use in application, please copy to some application folder in case i change this.
|
6
|
+
# Can be used for print_help_page
|
7
|
+
# TODO: add vi_keys here
|
8
|
+
# SUGGESTIONS WELCOME.
|
9
|
+
# @since 1.2.0
|
10
|
+
module RubyCurses
|
11
|
+
# a data viewer for viewing some text or filecontents
|
12
|
+
# view filename, :close_key => KEY_ENTER
|
13
|
+
# send data in an array
|
14
|
+
# view Array, :close_key => KEY_ENTER, :layout => [0,0,23,80]
|
15
|
+
# when passing layout reserve 4 rows for window and border. So for 2 lines of text
|
16
|
+
# give 6 rows.
|
17
|
+
class Viewer
|
18
|
+
# @param filename as string or content as array
|
19
|
+
# @yield textview object for further configuration before display
|
20
|
+
# NOTE: i am experimentally yielding textview object so i could supress borders
|
21
|
+
# just for kicks, but on can also bind_keys or events if one wanted.
|
22
|
+
def self.view what, config={} #:yield: textview
|
23
|
+
case what
|
24
|
+
when String # we have a path
|
25
|
+
content = _get_contents(what)
|
26
|
+
when Array
|
27
|
+
content = what
|
28
|
+
else
|
29
|
+
raise ArgumentError, "Viewer: Expecting Filename or Contents (array), but got #{what.class} "
|
30
|
+
end
|
31
|
+
wt = 0 # top margin
|
32
|
+
wl = 0 # left margin
|
33
|
+
wh = Ncurses.LINES-wt # height, goes to bottom of screen
|
34
|
+
ww = Ncurses.COLS-wl # width, goes to right end
|
35
|
+
wt, wl, wh, ww = config[:layout] if config.has_key? :layout
|
36
|
+
|
37
|
+
fp = config[:title] || ""
|
38
|
+
pf = config.fetch(:print_footer, true)
|
39
|
+
ta = config.fetch(:title_attrib, 'bold')
|
40
|
+
fa = config.fetch(:footer_attrib, 'bold')
|
41
|
+
type = config[:content_type]
|
42
|
+
|
43
|
+
layout = { :height => wh, :width => ww, :top => wt, :left => wl }
|
44
|
+
v_window = VER::Window.new(layout)
|
45
|
+
v_form = RubyCurses::Form.new v_window
|
46
|
+
colors = Ncurses.COLORS
|
47
|
+
back = :blue
|
48
|
+
back = 235 if colors >= 256
|
49
|
+
blue_white = get_color($datacolor, :white, back)
|
50
|
+
#blue_white = RubyCurses::Utils.get_color($datacolor, :white, 235)
|
51
|
+
textview = TextView.new v_form do
|
52
|
+
name "Viewer"
|
53
|
+
row 0
|
54
|
+
col 0
|
55
|
+
width ww
|
56
|
+
height wh-0 # earlier 2 but seems to be leaving space.
|
57
|
+
title fp
|
58
|
+
title_attrib ta
|
59
|
+
print_footer pf
|
60
|
+
footer_attrib fa
|
61
|
+
#border_attrib :reverse
|
62
|
+
border_color blue_white
|
63
|
+
end
|
64
|
+
require 'rbcurse/core/include/multibuffer'
|
65
|
+
textview.extend(RubyCurses::MultiBuffers)
|
66
|
+
|
67
|
+
t = textview
|
68
|
+
t.bind_key('<', 'move window left'){ f = t.form.window; c = f.left - 1; f.hide; f.mvwin(f.top, c); f.show;
|
69
|
+
f.reset_layout([f.height, f.width, f.top, c]);
|
70
|
+
}
|
71
|
+
t.bind_key('>', 'move window right'){ f = t.form.window; c = f.left + 1; f.hide; f.mvwin(f.top, c);
|
72
|
+
f.reset_layout([f.height, f.width, f.top, c]); f.show;
|
73
|
+
}
|
74
|
+
t.bind_key('^', 'move window up'){ f = t.form.window; c = f.top - 1 ; f.hide; f.mvwin(c, f.left);
|
75
|
+
f.reset_layout([f.height, f.width, c, f.left]) ; f.show;
|
76
|
+
}
|
77
|
+
t.bind_key('V', 'move window down'){ f = t.form.window; c = f.top + 1 ; f.hide; f.mvwin(c, f.left);
|
78
|
+
f.reset_layout([f.height, f.width, c, f.left]); f.show;
|
79
|
+
}
|
80
|
+
# yielding textview so you may further configure or bind keys or events
|
81
|
+
begin
|
82
|
+
textview.set_content content, :content_type => type
|
83
|
+
textview.add_content content, :content_type => type
|
84
|
+
# the next can also be used to use formatted_text(text, :ansi)
|
85
|
+
yield textview if block_given?
|
86
|
+
v_form.repaint
|
87
|
+
v_window.wrefresh
|
88
|
+
Ncurses::Panel.update_panels
|
89
|
+
# allow closing using q and Ctrl-q in addition to any key specified
|
90
|
+
# user should not need to specify key, since that becomes inconsistent across usages
|
91
|
+
while((ch = v_window.getchar()) != ?\C-q.getbyte(0) )
|
92
|
+
break if ch == config[:close_key] || ch == ?q.ord
|
93
|
+
# if you've asked for ENTER then i also check for 10 and 13
|
94
|
+
break if (ch == 10 || ch == 13) && config[:close_key] == KEY_ENTER
|
95
|
+
v_form.handle_key ch
|
96
|
+
v_form.repaint
|
97
|
+
end
|
98
|
+
rescue => err
|
99
|
+
$log.error " VIEWER ERROR #{err} "
|
100
|
+
$log.debug(err.backtrace.join("\n"))
|
101
|
+
alert "Viewer:" + err.to_s
|
102
|
+
ensure
|
103
|
+
v_window.destroy if !v_window.nil?
|
104
|
+
end
|
105
|
+
end
|
106
|
+
private
|
107
|
+
def self._get_contents fp
|
108
|
+
return "File #{fp} not readable" unless File.readable? fp
|
109
|
+
return Dir.new(fp).entries if File.directory? fp
|
110
|
+
case File.extname(fp)
|
111
|
+
when '.tgz','.gz'
|
112
|
+
cmd = "tar -ztvf #{fp}"
|
113
|
+
content = %x[#{cmd}]
|
114
|
+
when '.zip'
|
115
|
+
cmd = "unzip -l #{fp}"
|
116
|
+
content = %x[#{cmd}]
|
117
|
+
when '.jar', '.gem'
|
118
|
+
cmd = "tar -tvf #{fp}"
|
119
|
+
content = %x[#{cmd}]
|
120
|
+
when '.png', '.out','.jpg', '.gif','.pdf'
|
121
|
+
content = "File #{fp} not displayable"
|
122
|
+
when '.sqlite'
|
123
|
+
cmd = "sqlite3 #{fp} 'select name from sqlite_master;'"
|
124
|
+
content = %x[#{cmd}]
|
125
|
+
else
|
126
|
+
content = File.open(fp,"r").readlines
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end # class
|
130
|
+
|
131
|
+
end # module
|
132
|
+
if __FILE__ == $PROGRAM_NAME
|
133
|
+
require 'rbcurse/core/util/app'
|
134
|
+
|
135
|
+
App.new do
|
136
|
+
header = app_header "rbcurse 1.2.0", :text_center => "Viewer Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
|
137
|
+
message "Press F1 to exit from here"
|
138
|
+
|
139
|
+
RubyCurses::Viewer.view(ARGV[0] || $0, :close_key => KEY_ENTER, :title => "Enter to close") do |t|
|
140
|
+
# you may configure textview further here.
|
141
|
+
#t.suppress_borders true
|
142
|
+
#t.color = :black
|
143
|
+
#t.bgcolor = :white
|
144
|
+
# or
|
145
|
+
#t.attr = :reverse
|
146
|
+
end
|
147
|
+
|
148
|
+
end # app
|
149
|
+
end
|
@@ -0,0 +1,505 @@
|
|
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: 2011-11-21 - 19:28
|
8
|
+
#
|
9
|
+
# I hope this slowly does not become an unmaintainable maze like vimsplit
|
10
|
+
#
|
11
|
+
# "Simplicity hinges as much on cutting nonessential features as on adding helpful ones."
|
12
|
+
# - Walter Bender
|
13
|
+
#
|
14
|
+
# == TODO
|
15
|
+
# add multirow comps like textview and textarea, list
|
16
|
+
# add blocks that make sense like in app
|
17
|
+
# - what if user does not want form attached - app uses useform ot
|
18
|
+
# to check for this, if current_object don't add form
|
19
|
+
#
|
20
|
+
# - usage of _position inside means these shortcuts cannot be reused
|
21
|
+
# with other positioning systems, we'll be cut-pasting forever
|
22
|
+
#
|
23
|
+
# == CHANGES
|
24
|
+
# ------------------------------------------------------------ #
|
25
|
+
#
|
26
|
+
|
27
|
+
# what is the real purpose of the shortcuts, is it to avoid putting nil
|
28
|
+
# for form there if not required.
|
29
|
+
# Or is it positioning, such as in a stack. or just a method ?
|
30
|
+
require 'rbcurse/core/widgets/rlist'
|
31
|
+
require 'rbcurse/core/widgets/rtextview'
|
32
|
+
module RubyCurses
|
33
|
+
module WidgetShortcuts
|
34
|
+
class Ws
|
35
|
+
attr_reader :config
|
36
|
+
def initialize config={}
|
37
|
+
@config = config
|
38
|
+
end
|
39
|
+
def [](sym)
|
40
|
+
@config[sym]
|
41
|
+
end
|
42
|
+
def []=(sym, val)
|
43
|
+
@config[sym] = val
|
44
|
+
end
|
45
|
+
end
|
46
|
+
class WsStack < Ws; end
|
47
|
+
class WsFlow < Ws; end
|
48
|
+
def widget_shortcuts_init
|
49
|
+
@_ws_app_row = @_ws_app_col = 0
|
50
|
+
#@_ws_active = []
|
51
|
+
@_ws_active = nil # so we can use shortcuts if no stack used
|
52
|
+
@_ws_components = []
|
53
|
+
@variables = {}
|
54
|
+
end
|
55
|
+
def blank
|
56
|
+
label :text => ""
|
57
|
+
end
|
58
|
+
def line config={}
|
59
|
+
#horizontal line TODO
|
60
|
+
#row = config[:row] || @app_row
|
61
|
+
#width = config[:width] || 20
|
62
|
+
#_position config
|
63
|
+
#col = config[:col] || 1
|
64
|
+
#@color_pair = config[:color_pair] || $datacolor
|
65
|
+
#@attrib = config[:attrib] || Ncurses::A_NORMAL
|
66
|
+
#@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
|
67
|
+
#@window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width)
|
68
|
+
#@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
|
69
|
+
end
|
70
|
+
def radio config={}, &block
|
71
|
+
a = config[:group]
|
72
|
+
# should we not check for a nil
|
73
|
+
if @variables.has_key? a
|
74
|
+
v = @variables[a]
|
75
|
+
else
|
76
|
+
v = Variable.new
|
77
|
+
@variables[a] = v
|
78
|
+
end
|
79
|
+
config[:variable] = v
|
80
|
+
config.delete(:group)
|
81
|
+
w = RadioButton.new nil, config #, &block
|
82
|
+
_position w
|
83
|
+
if block
|
84
|
+
w.bind(:PRESS, &block)
|
85
|
+
end
|
86
|
+
return w
|
87
|
+
end
|
88
|
+
# create a shortcut for a class
|
89
|
+
# path is path of file to use in require starting with rbcurse
|
90
|
+
# klass is name of class to instantiate
|
91
|
+
def self.def_widget(path, klass, short=nil)
|
92
|
+
p=""
|
93
|
+
if path
|
94
|
+
p="require \"#{path}\""
|
95
|
+
end
|
96
|
+
short ||= klass.downcase
|
97
|
+
eval %{
|
98
|
+
def #{short}(config={}, &block)
|
99
|
+
if config.is_a? String
|
100
|
+
_s = config
|
101
|
+
config = {}
|
102
|
+
config[:text] = _s
|
103
|
+
end
|
104
|
+
#{p}
|
105
|
+
w = #{klass}.new nil, config
|
106
|
+
_position w
|
107
|
+
w.command &block if block_given?
|
108
|
+
return w
|
109
|
+
end
|
110
|
+
}
|
111
|
+
end
|
112
|
+
def_widget "rbcurse/core/widgets/rprogress", "Progress"
|
113
|
+
def_widget "rbcurse/core/widgets/scrollbar", "Scrollbar"
|
114
|
+
def_widget nil, "Label"
|
115
|
+
def_widget nil, "Field"
|
116
|
+
def_widget nil, :CheckBox, 'check'
|
117
|
+
def_widget nil, :Button
|
118
|
+
def_widget nil, :ToggleButton, 'toggle'
|
119
|
+
def menubar &block
|
120
|
+
require 'rbcurse/core/widgets/rmenu'
|
121
|
+
RubyCurses::MenuBar.new &block
|
122
|
+
end
|
123
|
+
def app_header title, config={}, &block
|
124
|
+
require 'rbcurse/core/widgets/applicationheader'
|
125
|
+
header = ApplicationHeader.new @form, title, config, &block
|
126
|
+
end
|
127
|
+
# editable text area
|
128
|
+
def textarea config={}, &block
|
129
|
+
require 'rbcurse/core/widgets/rtextarea'
|
130
|
+
# TODO confirm events many more
|
131
|
+
events = [ :CHANGE, :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 = TextArea.new useform, config
|
140
|
+
w.width = :expand unless w.width
|
141
|
+
w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
|
142
|
+
_position(w)
|
143
|
+
w.height ||= 8 # TODO
|
144
|
+
# need to expand to stack's width or flows itemwidth if given
|
145
|
+
if block
|
146
|
+
w.bind(block_event, &block)
|
147
|
+
end
|
148
|
+
return w
|
149
|
+
end
|
150
|
+
def textview config={}, &block
|
151
|
+
events = [ :LEAVE, :ENTER ]
|
152
|
+
block_event = events[0]
|
153
|
+
#_process_args args, config, block_event, events
|
154
|
+
#config[:width] = config[:display_length] unless config.has_key? :width
|
155
|
+
# if no width given, expand to flows width
|
156
|
+
#config[:width] ||= @stack.last.width if @stack.last
|
157
|
+
useform = nil
|
158
|
+
#useform = @form if @current_object.empty?
|
159
|
+
w = TextView.new useform, config
|
160
|
+
w.width = :expand unless w.width
|
161
|
+
w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
|
162
|
+
_position(w)
|
163
|
+
# need to expand to stack's width or flows itemwidth if given
|
164
|
+
if block
|
165
|
+
w.bind(block_event, &block)
|
166
|
+
end
|
167
|
+
return w
|
168
|
+
end
|
169
|
+
def listbox config={}, &block
|
170
|
+
events = [ :PRESS, :ENTER_ROW, :LEAVE, :ENTER ]
|
171
|
+
block_event = events[0]
|
172
|
+
#_process_args args, config, block_event, events
|
173
|
+
#config[:width] = config[:display_length] unless config.has_key? :width
|
174
|
+
# if no width given, expand to flows width
|
175
|
+
#config[:width] ||= @stack.last.width if @stack.last
|
176
|
+
useform = nil
|
177
|
+
#useform = @form if @current_object.empty?
|
178
|
+
w = List.new useform, config
|
179
|
+
w.width = :expand unless w.width
|
180
|
+
w.height ||= :expand # TODO We may need to push this before _position so it can be accounted for in stack
|
181
|
+
_position(w)
|
182
|
+
# need to expand to stack's width or flows itemwidth if given
|
183
|
+
if block
|
184
|
+
w.bind(block_event, &block)
|
185
|
+
end
|
186
|
+
return w
|
187
|
+
end
|
188
|
+
# prints pine-like key labels
|
189
|
+
def dock labels, config={}, &block
|
190
|
+
require 'rbcurse/core/widgets/keylabelprinter'
|
191
|
+
klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
|
192
|
+
end
|
193
|
+
|
194
|
+
def link config={}, &block
|
195
|
+
if config.is_a? String
|
196
|
+
_s = config
|
197
|
+
config = {}
|
198
|
+
config[:text] = _s
|
199
|
+
end
|
200
|
+
require 'rbcurse/core/widgets/rlink'
|
201
|
+
events = [ :PRESS, :LEAVE, :ENTER ]
|
202
|
+
block_event = :PRESS
|
203
|
+
config[:highlight_foreground] = "yellow"
|
204
|
+
config[:highlight_background] = "red"
|
205
|
+
toggle = Link.new nil, config
|
206
|
+
_position(toggle)
|
207
|
+
if block
|
208
|
+
toggle.bind(block_event, toggle, &block)
|
209
|
+
end
|
210
|
+
return toggle
|
211
|
+
end
|
212
|
+
def menulink config={}, &block
|
213
|
+
if config.is_a? String
|
214
|
+
_s = config
|
215
|
+
config = {}
|
216
|
+
config[:text] = _s
|
217
|
+
end
|
218
|
+
require 'rbcurse/core/widgets/rmenulink'
|
219
|
+
events = [ :PRESS, :LEAVE, :ENTER ]
|
220
|
+
block_event = :PRESS
|
221
|
+
config[:highlight_foreground] = "yellow"
|
222
|
+
config[:highlight_background] = "red"
|
223
|
+
#config[:hotkey] = true
|
224
|
+
w = MenuLink.new nil, config
|
225
|
+
_position(w)
|
226
|
+
if block
|
227
|
+
w.bind(block_event, w, &block)
|
228
|
+
end
|
229
|
+
return w
|
230
|
+
end
|
231
|
+
def tree config={}, &block
|
232
|
+
require 'rbcurse/core/widgets/rtree'
|
233
|
+
events = [:TREE_WILL_EXPAND_EVENT, :TREE_EXPANDED_EVENT, :TREE_SELECTION_EVENT, :PROPERTY_CHANGE, :LEAVE, :ENTER ]
|
234
|
+
block_event = nil
|
235
|
+
#config[:height] ||= 10
|
236
|
+
# if no width given, expand to flows width
|
237
|
+
useform = nil
|
238
|
+
#useform = @form if @current_object.empty?
|
239
|
+
w = Tree.new useform, config, &block
|
240
|
+
w.width ||= :expand
|
241
|
+
w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
|
242
|
+
_position w
|
243
|
+
return w
|
244
|
+
end
|
245
|
+
# creates a simple readonly table, that allows users to click on rows
|
246
|
+
# and also on the header. Header clicking is for column-sorting.
|
247
|
+
def tabular_widget config={}, &block
|
248
|
+
require 'rbcurse/core/widgets/tabularwidget'
|
249
|
+
events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ]
|
250
|
+
block_event = nil
|
251
|
+
# if no width given, expand to stack width
|
252
|
+
#config.delete :title
|
253
|
+
useform = nil
|
254
|
+
|
255
|
+
w = TabularWidget.new useform, config # NO BLOCK GIVEN
|
256
|
+
w.width ||= :expand
|
257
|
+
w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
|
258
|
+
_position(w)
|
259
|
+
if block_given?
|
260
|
+
#@current_object << w
|
261
|
+
yield_or_eval &block
|
262
|
+
#@current_object.pop
|
263
|
+
end
|
264
|
+
return w
|
265
|
+
end
|
266
|
+
alias :table :tabular_widget
|
267
|
+
def vimsplit config={}, &block
|
268
|
+
require 'rbcurse/extras/widgets/rvimsplit'
|
269
|
+
#TODO check these
|
270
|
+
events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ]
|
271
|
+
block_event = nil
|
272
|
+
config[:height] ||= 10
|
273
|
+
_position(w)
|
274
|
+
# if no width given, expand to flows width
|
275
|
+
#config.delete :title
|
276
|
+
useform = nil
|
277
|
+
|
278
|
+
w = VimSplit.new useform, config # NO BLOCK GIVEN
|
279
|
+
if block_given?
|
280
|
+
#@current_object << w
|
281
|
+
#instance_eval &block if block_given?
|
282
|
+
yield w
|
283
|
+
#@current_object.pop
|
284
|
+
end
|
285
|
+
return w
|
286
|
+
end
|
287
|
+
def _position w
|
288
|
+
if @_ws_active.nil? || @_ws_active.empty?
|
289
|
+
# no stack or flow, this is independent usage, or else we are outside stacks and flows
|
290
|
+
#
|
291
|
+
# this is outside any stack or flow, so we do the minimal
|
292
|
+
# user should specify row and col
|
293
|
+
w.row ||= 0
|
294
|
+
w.col ||= 0
|
295
|
+
#$log.debug "XXX: LABEL #{w.row} , #{w.col} "
|
296
|
+
w.set_form @form if @form # temporary,, only set if not inside an object FIXME
|
297
|
+
if w.width == :expand # calculate from current col, not 0 FIXME
|
298
|
+
w.width = FFI::NCurses.COLS-w.col # or take windows width since this could be in a message box
|
299
|
+
end
|
300
|
+
if w.height == :expand
|
301
|
+
# take from current row, and not zero FIXME
|
302
|
+
w.height = FFI::NCurses.LINES-w.row # or take windows width since this could be in a message box
|
303
|
+
end
|
304
|
+
return
|
305
|
+
|
306
|
+
end
|
307
|
+
# -------------------------- there is a stack or flow -------------------- #
|
308
|
+
#
|
309
|
+
cur = @_ws_active.last
|
310
|
+
unless cur
|
311
|
+
raise "This should have been handled previously.Somethings wrong, check/untested"
|
312
|
+
end
|
313
|
+
r = cur[:row] || 0
|
314
|
+
c = cur[:col] || 0
|
315
|
+
w.row = r
|
316
|
+
w.col = c
|
317
|
+
# if flow then take flows height, else use dummy value
|
318
|
+
if w.height_pc
|
319
|
+
w.height = ( (cur[:height] * w.height_pc.to_i)/100).floor
|
320
|
+
end
|
321
|
+
if w.height == :expand
|
322
|
+
if cur.is_a? WsFlow
|
323
|
+
w.height = cur[:height] || 8 #or raise "height not known for flow"
|
324
|
+
else
|
325
|
+
w.height = cur[:item_height] || 8 #or raise "height not known for flow"
|
326
|
+
end
|
327
|
+
#alert "setting ht to #{w.height}, #{cur[:height]} , for #{cur} "
|
328
|
+
end
|
329
|
+
if w.width == :expand
|
330
|
+
if cur.is_a? WsFlow
|
331
|
+
if cur[:item_width]
|
332
|
+
w.width = cur[:item_width] #or raise "item_Width not known for flow #{cur.class}, #{cur[:item_width]}, #{cur[:width]} , #{w.width_pc} "
|
333
|
+
elsif w.width_pc
|
334
|
+
#w.width = w.width_pc * cur[:width]
|
335
|
+
w.width = (cur[:width] * (w.width_pc.to_i * 0.01)).floor
|
336
|
+
else
|
337
|
+
w.width = cur[:width]
|
338
|
+
end
|
339
|
+
raise "width could not be calculated. i need flow width and item width_pc" if w.width == :expand
|
340
|
+
else
|
341
|
+
w.width = cur[:width] or raise "Width not known for stack #{cur.class}, #{cur[:width]} "
|
342
|
+
end
|
343
|
+
end
|
344
|
+
if cur.is_a? WsStack
|
345
|
+
r += w.height || 1 # NOTE, we need to have height for this purpose defined BEFORE calling for list/text
|
346
|
+
cur[:row] = r
|
347
|
+
else
|
348
|
+
wid = cur[:item_width] || w.width || 10
|
349
|
+
c += wid + 1
|
350
|
+
cur[:col] = c
|
351
|
+
end
|
352
|
+
#alert "set width to #{w.width} ,cur: #{cur[:width]} ,iw: #{cur[:item_width]} "
|
353
|
+
if cur.is_a? WsFlow
|
354
|
+
unless w.height
|
355
|
+
w.height = cur[:height] #or raise "Height not known for flow"
|
356
|
+
end
|
357
|
+
end
|
358
|
+
w.color ||= cur[:color]
|
359
|
+
w.bgcolor ||= cur[:bgcolor]
|
360
|
+
w.set_form @form if @form # temporary
|
361
|
+
@_ws_components << w
|
362
|
+
cur[:components] << w
|
363
|
+
end
|
364
|
+
# make it as simple as possible, don't try to be intelligent or
|
365
|
+
# clever, put as much on the user
|
366
|
+
def stack config={}, &block
|
367
|
+
s = WsStack.new config
|
368
|
+
@_ws_active ||= []
|
369
|
+
_configure s
|
370
|
+
@_ws_active << s
|
371
|
+
yield_or_eval &block if block_given?
|
372
|
+
@_ws_active.pop
|
373
|
+
|
374
|
+
# ---- stack is finished now
|
375
|
+
last = @_ws_active.last
|
376
|
+
if last
|
377
|
+
case last
|
378
|
+
when WsStack
|
379
|
+
when WsFlow
|
380
|
+
last[:col] += last[:item_width] || 0
|
381
|
+
# this tries to set height of outer flow based on highest row
|
382
|
+
# printed, however that does not account for height of object,
|
383
|
+
# so user should give a height to the flow.
|
384
|
+
last[:height] = s[:row] if s[:row] > (last[:height]||0)
|
385
|
+
$log.debug "XXX: STACK setting col to #{s[:col]} "
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
390
|
+
#
|
391
|
+
# item_width - width to use per item
|
392
|
+
# but the item width may apply to stacks inside not to items
|
393
|
+
def flow config={}, &block
|
394
|
+
s = WsFlow.new config
|
395
|
+
@_ws_active ||= []
|
396
|
+
_configure s
|
397
|
+
@_ws_active << s
|
398
|
+
yield_or_eval &block if block_given?
|
399
|
+
@_ws_active.pop
|
400
|
+
last = @_ws_active.last
|
401
|
+
if last
|
402
|
+
case last
|
403
|
+
when WsStack
|
404
|
+
if s[:height]
|
405
|
+
last[:row] += s[:height]
|
406
|
+
else
|
407
|
+
#last[:row] += last[:highest_row]
|
408
|
+
last[:row] += 1
|
409
|
+
end
|
410
|
+
when WsFlow
|
411
|
+
last[:col] += last[:item_width] || 0
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
# flow and stack could have a border option
|
416
|
+
# NOTE: box takes one row below too, so :expand overwrites that line
|
417
|
+
def box config={}, &block
|
418
|
+
require 'rbcurse/core/widgets/box'
|
419
|
+
# take current stacks row and col
|
420
|
+
# advance row by one and col by one
|
421
|
+
# at end note row and advance by one
|
422
|
+
# draw a box around using these coordinates. width should be
|
423
|
+
# provided unless we have item width or something.
|
424
|
+
@_ws_active ||= []
|
425
|
+
last = @_ws_active.last
|
426
|
+
if last
|
427
|
+
r = last[:row]
|
428
|
+
c = last[:col]
|
429
|
+
config[:row] = r
|
430
|
+
config[:col] = c
|
431
|
+
last[:row] += config[:margin_top] || 1
|
432
|
+
last[:col] += config[:margin_left] || 1
|
433
|
+
_box = Box.new @form, config # needs to be created first or will overwrite area after others painted
|
434
|
+
yield_or_eval &block if block_given?
|
435
|
+
# FIXME last[height] needs to account for row
|
436
|
+
h = config[:height] || last[:height] || (last[:row] - r)
|
437
|
+
h = 2 if h < 2
|
438
|
+
w = config[:width] || last[:width] || 15 # tmp
|
439
|
+
case last
|
440
|
+
when WsFlow
|
441
|
+
w = last[:col]
|
442
|
+
when WsStack
|
443
|
+
#h += 1
|
444
|
+
end
|
445
|
+
config[:row] = r
|
446
|
+
config[:col] = c
|
447
|
+
config[:height] = h
|
448
|
+
config[:width] = w
|
449
|
+
_box.row r
|
450
|
+
_box.col c
|
451
|
+
_box.height h
|
452
|
+
_box.width w
|
453
|
+
last[:row] += 1
|
454
|
+
last[:col] += 1 # ??? XXX if flow we need to increment properly or not ?
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
# This configures a stack or flow not the objects inside
|
459
|
+
def _configure s
|
460
|
+
s[:row] ||= 0
|
461
|
+
s[:col] ||= 0
|
462
|
+
s[:row] += (s[:margin_top] || 0)
|
463
|
+
s[:col] += (s[:margin_left] || 0)
|
464
|
+
s[:width] = FFI::NCurses.COLS-s[:col] if s[:width] == :expand
|
465
|
+
s[:height] = FFI::NCurses.LINES-s[:row] if s[:height] == :expand # 2011-11-30
|
466
|
+
last = @_ws_active.last
|
467
|
+
if last
|
468
|
+
if s[:width_pc]
|
469
|
+
if last.is_a? WsStack
|
470
|
+
s[:width] = (last[:width] * (s[:width_pc].to_i * 0.01)).floor
|
471
|
+
else
|
472
|
+
# i think this width is picked up by next stack in this flow
|
473
|
+
last[:item_width] = (last[:width] * (s[:width_pc].to_i* 0.01)).floor
|
474
|
+
end
|
475
|
+
end
|
476
|
+
if s[:height_pc]
|
477
|
+
if last.is_a? WsFlow
|
478
|
+
s[:height] = ( (last[:height] * s[:height_pc].to_i)/100).floor
|
479
|
+
else
|
480
|
+
# this works only for flows within stacks not for an object unless
|
481
|
+
# you put a single object in a flow
|
482
|
+
s[:item_height] = ( (last[:height] * s[:height_pc].to_i)/100).floor
|
483
|
+
end
|
484
|
+
#alert "item height set as #{s[:height]} for #{s} "
|
485
|
+
end
|
486
|
+
if last.is_a? WsStack
|
487
|
+
s[:row] += (last[:row] || 0)
|
488
|
+
s[:col] += (last[:col] || 0)
|
489
|
+
else
|
490
|
+
s[:row] += (last[:row] || 0)
|
491
|
+
s[:col] += (last[:col] || 0) # we are updating with item_width as each st finishes
|
492
|
+
s[:width] ||= last[:item_width] #
|
493
|
+
end
|
494
|
+
else
|
495
|
+
# this should be outer most flow or stack, if nothing mentioned
|
496
|
+
# trying this out
|
497
|
+
s[:width] ||= :expand
|
498
|
+
s[:height] ||= :expand
|
499
|
+
s[:width] = FFI::NCurses.COLS-s[:col] if s[:width] == :expand
|
500
|
+
s[:height] = FFI::NCurses.LINES-s[:row] if s[:height] == :expand # 2011-11-30
|
501
|
+
end
|
502
|
+
s[:components] = []
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|