canis 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/CHANGES +52 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +2 -0
- data/canis.gemspec +25 -0
- data/examples/alpmenu.rb +46 -0
- data/examples/app.sample +19 -0
- data/examples/appemail.rb +191 -0
- data/examples/atree.rb +105 -0
- data/examples/bline.rb +181 -0
- data/examples/common/devel.rb +319 -0
- data/examples/common/file.rb +93 -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 +59 -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 +16 -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 +506 -0
- data/examples/dirtree.rb +177 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +212 -0
- data/examples/tasks.rb +179 -0
- data/examples/term2.rb +88 -0
- data/examples/testbuttons.rb +307 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testdb.rb +182 -0
- data/examples/testfields.rb +208 -0
- data/examples/testflowlayout.rb +43 -0
- data/examples/testkeypress.rb +98 -0
- data/examples/testlistbox.rb +187 -0
- data/examples/testlistbox1.rb +199 -0
- data/examples/testmessagebox.rb +144 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +107 -0
- data/examples/testsplitlayout.rb +53 -0
- data/examples/testsplitlayout1.rb +49 -0
- data/examples/teststacklayout.rb +48 -0
- data/examples/testwsshortcuts.rb +68 -0
- data/examples/testwsshortcuts2.rb +129 -0
- data/lib/canis.rb +16 -0
- data/lib/canis/core/docs/index.txt +104 -0
- data/lib/canis/core/docs/list.txt +16 -0
- data/lib/canis/core/docs/style_help.yml +34 -0
- data/lib/canis/core/docs/tabbedpane.txt +15 -0
- data/lib/canis/core/docs/table.txt +31 -0
- data/lib/canis/core/docs/textpad.txt +48 -0
- data/lib/canis/core/docs/tree.txt +23 -0
- data/lib/canis/core/include/.DS_Store +0 -0
- data/lib/canis/core/include/action.rb +83 -0
- data/lib/canis/core/include/actionmanager.rb +49 -0
- data/lib/canis/core/include/appmethods.rb +179 -0
- data/lib/canis/core/include/bordertitle.rb +49 -0
- data/lib/canis/core/include/canisparser.rb +100 -0
- data/lib/canis/core/include/colorparser.rb +437 -0
- data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
- data/lib/canis/core/include/io.rb +320 -0
- data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
- data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
- data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
- data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
- data/lib/canis/core/include/listbindings.rb +89 -0
- data/lib/canis/core/include/listeditable.rb +319 -0
- data/lib/canis/core/include/listoperations.rb +61 -0
- data/lib/canis/core/include/listselectionmodel.rb +388 -0
- data/lib/canis/core/include/multibuffer.rb +173 -0
- data/lib/canis/core/include/ractionevent.rb +73 -0
- data/lib/canis/core/include/rchangeevent.rb +27 -0
- data/lib/canis/core/include/rhistory.rb +95 -0
- data/lib/canis/core/include/rinputdataevent.rb +47 -0
- data/lib/canis/core/include/textdocument.rb +111 -0
- data/lib/canis/core/include/vieditable.rb +175 -0
- data/lib/canis/core/include/widgetmenu.rb +66 -0
- data/lib/canis/core/system/colormap.rb +165 -0
- data/lib/canis/core/system/keydefs.rb +32 -0
- data/lib/canis/core/system/ncurses.rb +237 -0
- data/lib/canis/core/system/panel.rb +129 -0
- data/lib/canis/core/system/window.rb +1081 -0
- data/lib/canis/core/util/ansiparser.rb +119 -0
- data/lib/canis/core/util/app.rb +696 -0
- data/lib/canis/core/util/basestack.rb +412 -0
- data/lib/canis/core/util/defaultcolorparser.rb +84 -0
- data/lib/canis/core/util/extras/README +5 -0
- data/lib/canis/core/util/extras/bottomline.rb +1815 -0
- data/lib/canis/core/util/extras/padreader.rb +192 -0
- data/lib/canis/core/util/focusmanager.rb +31 -0
- data/lib/canis/core/util/helpmanager.rb +160 -0
- data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
- data/lib/canis/core/util/promptmenu.rb +235 -0
- data/lib/canis/core/util/rcommandwindow.rb +933 -0
- data/lib/canis/core/util/rdialogs.rb +520 -0
- data/lib/canis/core/util/textutils.rb +74 -0
- data/lib/canis/core/util/viewer.rb +238 -0
- data/lib/canis/core/util/widgetshortcuts.rb +508 -0
- data/lib/canis/core/widgets/applicationheader.rb +103 -0
- data/lib/canis/core/widgets/box.rb +58 -0
- data/lib/canis/core/widgets/divider.rb +310 -0
- data/lib/canis/core/widgets/extras/README.md +12 -0
- data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
- data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
- data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
- data/lib/canis/core/widgets/listbox.rb +326 -0
- data/lib/canis/core/widgets/listfooter.rb +86 -0
- data/lib/canis/core/widgets/rcombo.rb +210 -0
- data/lib/canis/core/widgets/rcontainer.rb +415 -0
- data/lib/canis/core/widgets/rlink.rb +30 -0
- data/lib/canis/core/widgets/rmenu.rb +970 -0
- data/lib/canis/core/widgets/rmenulink.rb +30 -0
- data/lib/canis/core/widgets/rmessagebox.rb +400 -0
- data/lib/canis/core/widgets/rprogress.rb +118 -0
- data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
- data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/canis/core/widgets/rwidget.rb +3634 -0
- data/lib/canis/core/widgets/scrollbar.rb +147 -0
- data/lib/canis/core/widgets/statusline.rb +113 -0
- data/lib/canis/core/widgets/table.rb +1072 -0
- data/lib/canis/core/widgets/tabular.rb +264 -0
- data/lib/canis/core/widgets/textpad.rb +1674 -0
- data/lib/canis/core/widgets/tree.rb +690 -0
- data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
- data/lib/canis/version.rb +3 -0
- metadata +229 -0
@@ -0,0 +1,320 @@
|
|
1
|
+
#*******************************************************
|
2
|
+
# Some common io routines for getting data or putting
|
3
|
+
# at some point
|
4
|
+
# Current are:
|
5
|
+
# * rb_gets - get a string at bottom of screen
|
6
|
+
# * get_file
|
7
|
+
# * rb_getchar - get a char
|
8
|
+
#
|
9
|
+
# * Promptmenu creation
|
10
|
+
# requires rcommandwindow
|
11
|
+
#
|
12
|
+
# *
|
13
|
+
# * rb_getstr (and those it calls) (old and for backward compat)
|
14
|
+
# - rb_getstr is used by vieditable for edit_line and insert_line
|
15
|
+
# * display_cmenu and create_mitem
|
16
|
+
# Changes:
|
17
|
+
# 2011-12-6 : removed many old, outdated methods.
|
18
|
+
# 2014-04-25 - 12:36 moved Promptmenu to util/promptmenu.rb
|
19
|
+
#*******************************************************#
|
20
|
+
require 'pathname'
|
21
|
+
module Canis
|
22
|
+
module Io
|
23
|
+
|
24
|
+
# create a 2 line window at bottom to accept user input
|
25
|
+
#
|
26
|
+
def __create_footer_window h = 2 , w = Ncurses.COLS, t = Ncurses.LINES-2, l = 0
|
27
|
+
ewin = Canis::Window.new(h, w , t, l)
|
28
|
+
end
|
29
|
+
# 2011-11-27 I have replaced the getting of chars with a field
|
30
|
+
|
31
|
+
# get a string at the bottom of the screen
|
32
|
+
#
|
33
|
+
# @param [String] prompt - label to show
|
34
|
+
# @param [Hash] config - :default, :width of Field, :help_text, :tab_completion
|
35
|
+
# help_text is displayed on F1
|
36
|
+
# tab_completion is a proc which helps to complete user input
|
37
|
+
# @yield [Field] for overriding or customization
|
38
|
+
# @return [String, nil] String if entered, nil if canceled
|
39
|
+
def rb_gets(prompt, config={}) # yield field
|
40
|
+
if config.is_a? Hash
|
41
|
+
# okay
|
42
|
+
#
|
43
|
+
elsif config.is_a? Array
|
44
|
+
# an array is supplied, and tabbing helps complete from that
|
45
|
+
# array.
|
46
|
+
options = config
|
47
|
+
completion_proc = Proc.new{|str|
|
48
|
+
options.dup.grep Regexp.new("^#{str}");
|
49
|
+
}
|
50
|
+
config = {}
|
51
|
+
config[:tab_completion] = completion_proc
|
52
|
+
elsif config == Pathname
|
53
|
+
# we need to return a pathname TODO and prepend dirname
|
54
|
+
# allow user to specify startdir else take current
|
55
|
+
completion_proc = Proc.new {|str| Dir.glob(str +"*").collect { |f| File.directory?(f) ? f+"/" : f } }
|
56
|
+
help_text = "Enter start of filename and tab to get completion"
|
57
|
+
config = {}
|
58
|
+
config[:tab_completion] = completion_proc
|
59
|
+
config[:help_text] = help_text
|
60
|
+
elsif config == Integer
|
61
|
+
config = {}
|
62
|
+
config[:datatype] = 1.class
|
63
|
+
config[:type] = :integer
|
64
|
+
elsif config == Float
|
65
|
+
config = {}
|
66
|
+
v = 0.11
|
67
|
+
config[:datatype] = v.class
|
68
|
+
config[:type] = :float
|
69
|
+
elsif config == :phone
|
70
|
+
|
71
|
+
config = {}
|
72
|
+
end
|
73
|
+
begin
|
74
|
+
win = __create_footer_window
|
75
|
+
form = Form.new win
|
76
|
+
r = 0; c = 1;
|
77
|
+
default = config[:default] || ""
|
78
|
+
prompt = "#{prompt} [#{default}]:" if default.size > 0
|
79
|
+
_max = FFI::NCurses.COLS-1-prompt.size-4
|
80
|
+
displen = config[:width] || [config[:maxlen] || 999, _max].min
|
81
|
+
maxlen = config[:maxlen] || _max
|
82
|
+
field = LabeledField.new form, :row => r, :col => c, :maxlen => maxlen, :default => default, :label => prompt,
|
83
|
+
:width => displen
|
84
|
+
field.datatype(config[:datatype]) if config[:datatype]
|
85
|
+
field.type(config[:type]) if config[:type]
|
86
|
+
bg = Ncurses.COLORS >= 236 ? 233 : :blue
|
87
|
+
field.bgcolor = bg
|
88
|
+
field.cursor_end if default.size > 0
|
89
|
+
def field.default=(x); default(x);end
|
90
|
+
|
91
|
+
# if user wishes to use the yield and say "field.history = [x,y,z] then
|
92
|
+
# we should alredy have extended this, so lets make it permanent
|
93
|
+
require 'canis/core/include/rhistory'
|
94
|
+
field.extend(FieldHistory)
|
95
|
+
field.history = config[:history]
|
96
|
+
|
97
|
+
yield field if block_given?
|
98
|
+
form.repaint
|
99
|
+
win.wrefresh
|
100
|
+
prevchar = 0
|
101
|
+
entries = nil
|
102
|
+
oldstr = nil # for tab completion, origal word entered by user
|
103
|
+
while ((ch = win.getchar()) != 999)
|
104
|
+
if ch == 10 || ch == 13 || ch == KEY_ENTER
|
105
|
+
begin
|
106
|
+
# validate in case ranges or other validation given
|
107
|
+
field.on_leave
|
108
|
+
break
|
109
|
+
rescue FieldValidationException => err # added 2011-10-2 v1.3.1 so we can rollback
|
110
|
+
#alert err.to_s
|
111
|
+
# unable to use alert now, since closing alert repaints root window and clears the
|
112
|
+
# window this was on (command window in numbered menu).
|
113
|
+
print_this(win, err.to_s, $errorcolor, 1, 0)
|
114
|
+
form.setpos
|
115
|
+
rescue => err
|
116
|
+
Ncurses.beep
|
117
|
+
break
|
118
|
+
end
|
119
|
+
end
|
120
|
+
#return -1, nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
|
121
|
+
return nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
|
122
|
+
#if ch == ?\M-h.getbyte(0) # HELP KEY
|
123
|
+
#help_text = config[:help_text] || "No help provided"
|
124
|
+
#color = $datacolor
|
125
|
+
#print_help(win, r, c, color, help_text)
|
126
|
+
## this will come over our text
|
127
|
+
#end
|
128
|
+
# tab completion and help_text print on F1
|
129
|
+
# that field objects can extend, same for tab completion and gmail completion
|
130
|
+
if ch == KEY_TAB
|
131
|
+
if config
|
132
|
+
str = field.text
|
133
|
+
# tab_completion
|
134
|
+
# if previous char was not tab, execute tab_completion_proc and push first entry
|
135
|
+
# else push the next entry
|
136
|
+
if prevchar == KEY_TAB
|
137
|
+
if !entries.nil? && !entries.empty?
|
138
|
+
str = entries.delete_at(0)
|
139
|
+
else
|
140
|
+
str = oldstr if oldstr
|
141
|
+
prevchar = ch = nil # so it can start again completing
|
142
|
+
end
|
143
|
+
else
|
144
|
+
tabc = config[:tab_completion] unless tabc
|
145
|
+
next unless tabc
|
146
|
+
oldstr = str.dup
|
147
|
+
entries = tabc.call(str).dup
|
148
|
+
$log.debug " tab got #{entries} for str=#{str}"
|
149
|
+
str = entries.delete_at(0) unless entries.nil? || entries.empty?
|
150
|
+
str = str.to_s.dup
|
151
|
+
end
|
152
|
+
if str
|
153
|
+
field.text = str
|
154
|
+
field.cursor_end
|
155
|
+
field.set_form_col # shit why are we doign this, text sets curpos to 0
|
156
|
+
end
|
157
|
+
form.repaint
|
158
|
+
win.wrefresh
|
159
|
+
end
|
160
|
+
|
161
|
+
elsif ch == KEY_F1
|
162
|
+
help_text = config[:help_text] || "No help provided. C-c/C-g aborts. <TAB> completion. Alt-h history. C-a/e"
|
163
|
+
print_status_message help_text, :wait => 7
|
164
|
+
else
|
165
|
+
form.handle_key ch
|
166
|
+
end
|
167
|
+
prevchar = ch
|
168
|
+
win.wrefresh
|
169
|
+
end
|
170
|
+
rescue => err
|
171
|
+
Ncurses.beep
|
172
|
+
textdialog [err.to_s, *err.backtrace], :title => "Exception"
|
173
|
+
$log.error "EXC in rb_getstr #{err} "
|
174
|
+
$log.error(err.backtrace.join("\n"))
|
175
|
+
ensure
|
176
|
+
win.destroy if win
|
177
|
+
end
|
178
|
+
config[:history] << field.text if config[:history] && field.text
|
179
|
+
return field.text
|
180
|
+
end
|
181
|
+
|
182
|
+
# get a character.
|
183
|
+
# unlike rb_gets allows user to enter control or alt or function character too.
|
184
|
+
# @param [String] prompt or label to show.
|
185
|
+
# @param [Hash] configuration such as default or regexp for validation
|
186
|
+
# @return [Fixnum] nil if canceled, or ret value of getchar which is numeric
|
187
|
+
# If default provided, then ENTER returns the default
|
188
|
+
def rb_getchar(prompt, config={}) # yield field
|
189
|
+
begin
|
190
|
+
win = __create_footer_window
|
191
|
+
#form = Form.new win
|
192
|
+
r = 0; c = 1;
|
193
|
+
default = config[:default]
|
194
|
+
prompt = "#{prompt} [#{default}] " if default
|
195
|
+
win.mvprintw(r, c, "%s: " % prompt);
|
196
|
+
bg = Ncurses.COLORS >= 236 ? 236 : :blue
|
197
|
+
color_pair = get_color($reversecolor, :white, bg)
|
198
|
+
win.printstring r, c + prompt.size + 2, " ", color_pair
|
199
|
+
|
200
|
+
win.wrefresh
|
201
|
+
prevchar = 0
|
202
|
+
entries = nil
|
203
|
+
while ((ch = win.getchar()) != 999)
|
204
|
+
return default.ord if default && (ch == 13 || ch == KEY_ENTER)
|
205
|
+
return nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
|
206
|
+
if ch == KEY_F1
|
207
|
+
help_text = config[:help_text] || "No help provided. C-c/C-g aborts."
|
208
|
+
print_status_message help_text, :wait => 7
|
209
|
+
win.wrefresh # nevr had to do this with ncurses, but have to with ffi-ncurses ??
|
210
|
+
next
|
211
|
+
end
|
212
|
+
if config[:regexp]
|
213
|
+
reg = config[:regexp]
|
214
|
+
if ch > 0 && ch < 256
|
215
|
+
chs = ch.chr
|
216
|
+
return ch if chs =~ reg
|
217
|
+
alert "Wrong character. #{reg} "
|
218
|
+
else
|
219
|
+
alert "Wrong character. #{reg} "
|
220
|
+
end
|
221
|
+
else
|
222
|
+
return ch
|
223
|
+
end
|
224
|
+
#form.handle_key ch
|
225
|
+
win.wrefresh
|
226
|
+
end
|
227
|
+
rescue => err
|
228
|
+
Ncurses.beep
|
229
|
+
$log.error "EXC in rb_getstr #{err} "
|
230
|
+
$log.error(err.backtrace.join("\n"))
|
231
|
+
ensure
|
232
|
+
win.destroy if win
|
233
|
+
end
|
234
|
+
return nil
|
235
|
+
end
|
236
|
+
|
237
|
+
# This is just experimental, trying out tab_completion
|
238
|
+
# Prompt user for a file name, allowing him to tab to complete filenames
|
239
|
+
# @see #choose_file from rcommandwindow.rb
|
240
|
+
# @param [String] label to print before field
|
241
|
+
# @param [Fixnum] max length of field
|
242
|
+
# @return [String] filename or blank if user cancelled
|
243
|
+
def get_file prompt, config={} #:nodoc:
|
244
|
+
maxlen = 70
|
245
|
+
tabc = Proc.new {|str| Dir.glob(str +"*") }
|
246
|
+
config[:tab_completion] ||= tabc
|
247
|
+
config[:maxlen] ||= maxlen
|
248
|
+
#config[:default] = "test"
|
249
|
+
#ret, str = rb_getstr(nil,0,0, prompt, maxlen, config)
|
250
|
+
# 2014-04-25 - 12:42 removed call to deprecated method
|
251
|
+
str = rb_gets(prompt, config)
|
252
|
+
#$log.debug " get_file returned #{ret} , #{str} "
|
253
|
+
str ||= ""
|
254
|
+
return str
|
255
|
+
end
|
256
|
+
def clear_this win, r, c, color, len
|
257
|
+
print_this(win, "%-*s" % [len," "], color, r, c)
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
##
|
263
|
+
# prints given text to window, in color at x and y coordinates
|
264
|
+
# @param [Window] window to write to
|
265
|
+
# @param [String] text to print
|
266
|
+
# @param [int] color pair such as $datacolor or $promptcolor
|
267
|
+
# @param [int] x row
|
268
|
+
# @param [int] y col
|
269
|
+
# @see Window#printstring
|
270
|
+
def print_this(win, text, color, x, y)
|
271
|
+
raise "win nil in print_this" unless win
|
272
|
+
color=Ncurses.COLOR_PAIR(color);
|
273
|
+
win.attron(color);
|
274
|
+
#win.mvprintw(x, y, "%-40s" % text);
|
275
|
+
win.mvprintw(x, y, "%s" % text);
|
276
|
+
win.attroff(color);
|
277
|
+
win.refresh
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
#
|
282
|
+
# warn user: currently flashes and places error in log file
|
283
|
+
# experimental, may change interface later
|
284
|
+
# it does not say anything on screen
|
285
|
+
# @param [String] text of error/warning to put in log
|
286
|
+
# @since 1.1.5
|
287
|
+
def warn string
|
288
|
+
$log.warn string
|
289
|
+
Ncurses.beep
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
# routine to get a string at bottom of window.
|
294
|
+
# The first 3 params are no longer required since we create a window
|
295
|
+
# of our own.
|
296
|
+
# @param [String] prompt - label to show
|
297
|
+
# @param [Fixnum] maxlen - max length of input
|
298
|
+
# @param [Hash] config - :default, :width of Field, :help_text, :tab_completion
|
299
|
+
# help_text is displayed on F1
|
300
|
+
# tab_completion is a proc which helps to complete user input
|
301
|
+
# NOTE : This method is now only for **backward compatibility**
|
302
|
+
# rb_getstr had various return codes based on whether user asked for help
|
303
|
+
# possibly mimicking alpine, or because i could do nothing about it.
|
304
|
+
# Now, rb_getstr handles that and only returns if the user cancels or enters
|
305
|
+
# a string, so rb_getstr does not need to return other codes.
|
306
|
+
# @deprecated
|
307
|
+
def rb_getstr(nolongerused, r, c, prompt, maxlen, config={})
|
308
|
+
config[:maxlen] = maxlen
|
309
|
+
str = rb_gets(prompt, config)
|
310
|
+
if str
|
311
|
+
return 0, str
|
312
|
+
else
|
313
|
+
return -1, nil
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
|
319
|
+
end # module
|
320
|
+
end # module
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
2
|
+
# File: SplitLayout.rb
|
3
|
+
# Description:
|
4
|
+
# Author: j kepler http://github.com/mare-imbrium/canis/
|
5
|
+
# Date: 2014-05-10 - 13:48
|
6
|
+
# License: MIT
|
7
|
+
# Last update: 2014-05-10 20:19
|
8
|
+
# ----------------------------------------------------------------------------- #
|
9
|
+
# SplitLayout.rb Copyright (C) 2012-2014 j kepler
|
10
|
+
# ----
|
11
|
+
# This layout allows for complex arrangements of stacks and flows. One can divide the layout
|
12
|
+
# into splits (vertical or horizontal) and keep dividing a split, or placing a component in it.
|
13
|
+
# However, to keep it simple and reduce the testing, I am insisting that a weightage be specified
|
14
|
+
# with a split.
|
15
|
+
#
|
16
|
+
# layout = SplitLayout.new :height => -1, :top_margin => 1, :bottom_margin => 1, :left_margin => 1
|
17
|
+
# x, y = layout.vsplit( 0.30, 0.70)
|
18
|
+
# x.component = mylist
|
19
|
+
# y1, y2 = y.split( 0.40, 0.60 )
|
20
|
+
# y2.component = mytable
|
21
|
+
# y11,y12,y13 = y1.vsplit( 0.3, 0.3, 0.4)
|
22
|
+
# y11 = list1
|
23
|
+
# y12 = list2
|
24
|
+
# y13 = list3
|
25
|
+
#
|
26
|
+
# Or hopefully:
|
27
|
+
#
|
28
|
+
# layout.split(0.3, 0.7) do |x,y|
|
29
|
+
# x.component = mylist
|
30
|
+
# y.split(0.4, 0.6) do |a,b|
|
31
|
+
# b.component = mytable
|
32
|
+
# a.vsplit( 0.3, 0.3, 0.4) do | p,q,r |
|
33
|
+
# p.component = list1
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
#
|
39
|
+
class Split
|
40
|
+
|
41
|
+
attr_reader :component
|
42
|
+
attr_accessor :name
|
43
|
+
attr_reader :splits
|
44
|
+
attr_accessor :height, :width, :top, :left
|
45
|
+
# link to parent
|
46
|
+
# own weight
|
47
|
+
attr_accessor :parent, :weight
|
48
|
+
# weights of child splits, given in cons
|
49
|
+
attr_accessor :split_wts
|
50
|
+
attr_reader :type
|
51
|
+
|
52
|
+
def initialize type, weight, parent
|
53
|
+
@type = type
|
54
|
+
@weight = weight
|
55
|
+
@parent = parent
|
56
|
+
end
|
57
|
+
def _split type, args, &block
|
58
|
+
@split_wts = args
|
59
|
+
@splits = []
|
60
|
+
args.each do |e|
|
61
|
+
@splits << Split.new(type, e, self)
|
62
|
+
end
|
63
|
+
if block_given?
|
64
|
+
yield @splits.flatten
|
65
|
+
else
|
66
|
+
return @splits.flatten
|
67
|
+
end
|
68
|
+
end
|
69
|
+
def split *args, &block
|
70
|
+
_split :h, args, &block
|
71
|
+
end
|
72
|
+
def vsplit *args, &block
|
73
|
+
_split :v, args, &block
|
74
|
+
end
|
75
|
+
|
76
|
+
# Set a component into a split.
|
77
|
+
# set name of component as name of split, more for debugging
|
78
|
+
def component=(c)
|
79
|
+
@component = c
|
80
|
+
@name = c.name || c.class.to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
# shorthand to place a component in a split.
|
84
|
+
alias :<< :component=
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
require 'canis/core/include/layouts/abstractlayout'
|
90
|
+
class SplitLayout < AbstractLayout
|
91
|
+
|
92
|
+
# @param [Form] optional give a form
|
93
|
+
# @param [Hash] optional give settings/attributes which will be set into variables
|
94
|
+
def initialize arg, config={}, &block
|
95
|
+
super
|
96
|
+
@splits = nil
|
97
|
+
end
|
98
|
+
def _split type, args, &block
|
99
|
+
@splits = []
|
100
|
+
@split_wts = args
|
101
|
+
args.each do |e|
|
102
|
+
@splits << Split.new(type, e, self)
|
103
|
+
end
|
104
|
+
if block_given?
|
105
|
+
yield @splits.flatten
|
106
|
+
else
|
107
|
+
return @splits.flatten
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def split *args, &block
|
112
|
+
raise "already split " if @splits
|
113
|
+
_split :h, args, &block
|
114
|
+
end
|
115
|
+
def vsplit *args, &block
|
116
|
+
raise "already split " if @splits
|
117
|
+
$log.debug " SPLIT GOT #{args} "
|
118
|
+
_split :v, args, &block
|
119
|
+
end
|
120
|
+
alias :top :top_margin
|
121
|
+
alias :left :left_margin
|
122
|
+
|
123
|
+
|
124
|
+
# This program lays out the widgets deciding their row and columm and height and weight.
|
125
|
+
# This program is called once at start of application, and again whenever a RESIZE event happens.
|
126
|
+
def do_layout
|
127
|
+
_init_layout
|
128
|
+
recalc @splits, @top_margin, @left_margin if @splits
|
129
|
+
#
|
130
|
+
$log.debug " layout finished "
|
131
|
+
end
|
132
|
+
def recalc splits, r, c
|
133
|
+
splits.each_with_index do |s,i|
|
134
|
+
$log.debug " recalc #{i}, #{s} "
|
135
|
+
p = s.parent
|
136
|
+
s.top = r
|
137
|
+
s.left = c
|
138
|
+
case s.type
|
139
|
+
when :v
|
140
|
+
s.width = (s.weight * p.width ).floor
|
141
|
+
s.height = p.height
|
142
|
+
c += s.width
|
143
|
+
when :h
|
144
|
+
s.height = (s.weight * p.height ).floor
|
145
|
+
s.width = p.width
|
146
|
+
r += s.height
|
147
|
+
end
|
148
|
+
if s.component
|
149
|
+
s.component.height = s.height
|
150
|
+
s.component.row = s.top
|
151
|
+
s.component.col = s.left
|
152
|
+
s.component.width = s.width
|
153
|
+
elsif s.splits
|
154
|
+
recalc s.splits, s.top, s.left if s.splits
|
155
|
+
else
|
156
|
+
raise "Neither splits nor a component placed in #{s} #{s.type}, #{s.weight} #{s.name}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|