reterm 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/designer/src/ComponentParams.rb +89 -42
- data/designer/src/ComponentsList.rb +26 -25
- data/designer/src/CreatedList.rb +9 -0
- data/designer/src/Designer.rb +23 -1
- data/designer/src/ToggleArea.rb +20 -3
- data/designer/src/about.rb +35 -0
- data/designer/src/component_factory.rb +18 -0
- data/designer/src/component_map.rb +7 -0
- data/designer/src/file_chooser.rb +25 -0
- data/designer/src/glade/Designer.glade +1 -19
- data/designer/src/images/{slist.png → scroll_list.png} +0 -0
- data/lib/reterm.rb +10 -1
- data/lib/reterm/color_pair.rb +166 -10
- data/lib/reterm/component.rb +89 -2
- data/lib/reterm/components.rb +16 -1
- data/lib/reterm/components/alphalist.rb +45 -0
- data/lib/reterm/components/ascii_text.rb +14 -1
- data/lib/reterm/components/asciimator.rb +1 -0
- data/lib/reterm/components/button.rb +35 -5
- data/lib/reterm/components/button_box.rb +108 -0
- data/lib/reterm/components/close_button.rb +22 -0
- data/lib/reterm/components/cmd_output.rb +69 -0
- data/lib/reterm/components/dial.rb +11 -2
- data/lib/reterm/components/dialog.rb +41 -1
- data/lib/reterm/components/drop_down_menu.rb +140 -0
- data/lib/reterm/components/entry.rb +42 -14
- data/lib/reterm/components/histogram.rb +55 -0
- data/lib/reterm/components/hslider.rb +9 -0
- data/lib/reterm/components/image.rb +9 -0
- data/lib/reterm/components/isometric.rb +38 -0
- data/lib/reterm/components/label.rb +20 -3
- data/lib/reterm/components/matrix.rb +9 -0
- data/lib/reterm/components/multi_line_entry.rb +54 -0
- data/lib/reterm/components/password_entry.rb +15 -0
- data/lib/reterm/components/radio.rb +10 -0
- data/lib/reterm/components/revealing_label.rb +126 -0
- data/lib/reterm/components/rocker.rb +21 -11
- data/lib/reterm/components/scroll_list.rb +96 -0
- data/lib/reterm/components/scrolling_area.rb +50 -0
- data/lib/reterm/components/select_list.rb +67 -0
- data/lib/reterm/components/splash.rb +85 -0
- data/lib/reterm/components/template.rb +12 -1
- data/lib/reterm/components/treeview.rb +1 -0
- data/lib/reterm/components/vslider.rb +11 -2
- data/lib/reterm/components/youtube.rb +20 -0
- data/lib/reterm/config.rb +22 -0
- data/lib/reterm/init.rb +131 -6
- data/lib/reterm/layout.rb +147 -11
- data/lib/reterm/layouts.rb +1 -0
- data/lib/reterm/layouts/grid.rb +69 -0
- data/lib/reterm/layouts/horizontal.rb +25 -4
- data/lib/reterm/layouts/vertical.rb +26 -5
- data/lib/reterm/loader.rb +2 -2
- data/lib/reterm/mixins/button_helpers.rb +7 -0
- data/lib/reterm/mixins/cdk_component.rb +66 -2
- data/lib/reterm/mixins/common_controls.rb +15 -0
- data/lib/reterm/mixins/common_keys.rb +20 -0
- data/lib/reterm/mixins/component_input.rb +62 -14
- data/lib/reterm/mixins/event_dispatcher.rb +2 -0
- data/lib/reterm/mixins/item_helpers.rb +8 -0
- data/lib/reterm/mixins/key_bindings.rb +23 -0
- data/lib/reterm/mixins/log_helpers.rb +13 -0
- data/lib/reterm/mixins/mouse_input.rb +58 -0
- data/lib/reterm/mixins/nav_controls.rb +33 -0
- data/lib/reterm/mixins/nav_input.rb +161 -69
- data/lib/reterm/terminal.rb +6 -2
- data/lib/reterm/util.rb +121 -0
- data/lib/reterm/version.rb +1 -1
- data/lib/reterm/window.rb +295 -29
- metadata +33 -17
- data/designer/src/images/orig/Check.png +0 -0
- data/designer/src/images/orig/ascii_text.png +0 -0
- data/designer/src/images/orig/button.png +0 -0
- data/designer/src/images/orig/dial.png +0 -0
- data/designer/src/images/orig/entry.png +0 -0
- data/designer/src/images/orig/hslider.png +0 -0
- data/designer/src/images/orig/label.png +0 -0
- data/designer/src/images/orig/matrix.png +0 -0
- data/designer/src/images/orig/radio.png +0 -0
- data/designer/src/images/orig/rocker.png +0 -0
- data/designer/src/images/orig/slist.png +0 -0
- data/designer/src/images/orig/vslider.png +0 -0
- data/lib/reterm/components/slist.rb +0 -32
- data/lib/reterm/menu.rb +0 -81
data/lib/reterm/version.rb
CHANGED
data/lib/reterm/window.rb
CHANGED
@@ -25,6 +25,9 @@ module RETerm
|
|
25
25
|
#
|
26
26
|
class Window
|
27
27
|
include EventDispatcher
|
28
|
+
include LogHelpers
|
29
|
+
|
30
|
+
attr_reader :window_id
|
28
31
|
|
29
32
|
attr_accessor :rows, :cols
|
30
33
|
attr_accessor :x, :y
|
@@ -48,8 +51,10 @@ module RETerm
|
|
48
51
|
# Assign component to window. This will autoassign local
|
49
52
|
# window to component as well.
|
50
53
|
def component=(c)
|
51
|
-
|
52
|
-
|
54
|
+
clear!
|
55
|
+
|
56
|
+
c.window = self
|
57
|
+
c.colors = @colors if colored?
|
53
58
|
@component = c
|
54
59
|
end
|
55
60
|
|
@@ -58,12 +63,44 @@ module RETerm
|
|
58
63
|
!!@parent
|
59
64
|
end
|
60
65
|
|
66
|
+
# Return boolean indicating if this window has children
|
67
|
+
def children?
|
68
|
+
!@children.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return boolean indicating if this window is the
|
72
|
+
# first child of its parent
|
73
|
+
def first_child?
|
74
|
+
return true unless parent?
|
75
|
+
parent.children.index(self) == 0
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return boolean indicating if this window is the
|
79
|
+
# last child of its parent
|
80
|
+
def last_child?
|
81
|
+
return true unless parent?
|
82
|
+
parent.children.index(self) == (parent.children.size - 1)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Return root window (recusively), self if parent is not set
|
86
|
+
def root
|
87
|
+
parent? ? parent.root : self
|
88
|
+
end
|
89
|
+
|
90
|
+
def total_x
|
91
|
+
@tx ||= parent? ? (parent.total_x + x) : x
|
92
|
+
end
|
93
|
+
|
94
|
+
def total_y
|
95
|
+
@ty ||= parent? ? (parent.total_y + y) : y
|
96
|
+
end
|
97
|
+
|
61
98
|
# Instantiate Window with given args. None are required, but
|
62
99
|
# unless :rows, :cols, :x, or :y is specified, window will be
|
63
100
|
# created in it's default position.
|
64
101
|
#
|
65
102
|
# This method will generate a unique id for each window
|
66
|
-
# and add it to a static
|
103
|
+
# and add it to a static registry for subsequent tracking.
|
67
104
|
#
|
68
105
|
# @param [Hash] args arguments used to instantiate window
|
69
106
|
# @option args [Integer] :rows number of rows to assign to window
|
@@ -76,13 +113,23 @@ module RETerm
|
|
76
113
|
# @option args [Window] :parent parent to assign to window, if
|
77
114
|
# set window will be created a a child, else it will be
|
78
115
|
# independently created & tracked.
|
116
|
+
# @options args [Boolean] :expand bool indicating
|
117
|
+
# if window can be expanded on request
|
118
|
+
# @options args [Boolean] :must_expand bool indicating
|
119
|
+
# if window must be expanded when requested. Failure
|
120
|
+
# to expand will result in an error
|
121
|
+
# @options args [Boolean] :fill bool indicating
|
122
|
+
# if window should fill remaining space
|
79
123
|
#
|
80
124
|
def initialize(args={})
|
81
125
|
@@registry ||= []
|
82
126
|
@@registry << self
|
83
127
|
|
84
|
-
|
85
|
-
|
128
|
+
@@wid ||= 0
|
129
|
+
@@wid += 1
|
130
|
+
@window_id = @@wid
|
131
|
+
|
132
|
+
@children = []
|
86
133
|
|
87
134
|
@x = args[:x] || 0
|
88
135
|
@y = args[:y] || 0
|
@@ -90,38 +137,147 @@ module RETerm
|
|
90
137
|
@vborder = args[:vborder] || 0
|
91
138
|
@hborder = args[:hborder] || 0
|
92
139
|
|
93
|
-
|
140
|
+
component = args[:component]
|
141
|
+
|
142
|
+
@rows = args[:rows] ||
|
143
|
+
(component ?
|
144
|
+
(component.requested_rows + component.extra_padding) :
|
145
|
+
Terminal.rows)
|
146
|
+
|
147
|
+
@cols = args[:cols] ||
|
148
|
+
(component ?
|
149
|
+
(component.requested_cols + component.extra_padding) :
|
150
|
+
Terminal.cols)
|
94
151
|
|
95
152
|
if args[:parent]
|
96
153
|
@parent = args[:parent]
|
154
|
+
|
155
|
+
@rows, @cols = *Window.adjust_proportional(@parent, @rows, @cols)
|
156
|
+
@x, @y = *Window.align(@parent, @x, @y, @rows, @cols)
|
157
|
+
|
97
158
|
@win = parent.win.derwin(@rows, @cols, @y, @x)
|
98
159
|
|
99
160
|
else
|
100
161
|
@parent = nil
|
162
|
+
|
163
|
+
@rows, @cols = *Window.adjust_proportional(Terminal, @rows, @cols)
|
164
|
+
@x, @y = *Window.align(Terminal, @x, @y, @rows, @cols)
|
165
|
+
|
101
166
|
@win = Ncurses::WINDOW.new(@rows, @cols, @y, @x)
|
102
167
|
end
|
103
168
|
|
169
|
+
self.component = component if !!component
|
170
|
+
|
104
171
|
Ncurses::keypad(@win, true)
|
105
172
|
|
106
|
-
@
|
173
|
+
@win.timeout(SYNC_TIMEOUT) if @win && sync_enabled? # XXX
|
107
174
|
|
175
|
+
@expand = !!args[:expand]
|
176
|
+
@must_expand = !!args[:must_expand]
|
108
177
|
|
109
|
-
|
110
|
-
|
178
|
+
@fill = !!args[:fill]
|
179
|
+
end
|
111
180
|
|
112
|
-
|
181
|
+
###
|
182
|
+
|
183
|
+
# Adjusts rows/cols in a context dependent manner
|
184
|
+
# TODO should proporational percentage be of remaining area?
|
185
|
+
def self.adjust_proportional(parent, rows, cols)
|
186
|
+
nr = rows
|
187
|
+
nc = cols
|
188
|
+
|
189
|
+
nr = parent.rows * nr if rows < 1
|
190
|
+
nc = parent.cols * nc if cols < 1
|
191
|
+
|
192
|
+
return nr, nc
|
193
|
+
end
|
194
|
+
|
195
|
+
# Adjusts x/y in context dependent manner
|
196
|
+
def self.align(parent, x, y, rows, cols)
|
197
|
+
nx = x
|
198
|
+
ny = y
|
199
|
+
|
200
|
+
nx = 1 if x == :left
|
201
|
+
ny = 1 if y == :top
|
202
|
+
|
203
|
+
nx = parent.cols - cols - 1 if x == :right
|
204
|
+
ny = parent.rows - rows - 1 if y == :bottom
|
205
|
+
|
206
|
+
nx = parent.cols / 2 - cols / 2 if x == :center
|
207
|
+
ny = parent.rows / 2 - rows / 2 if y == :center
|
208
|
+
|
209
|
+
return nx, ny
|
210
|
+
end
|
211
|
+
|
212
|
+
# Adjusts rows / cols so as to fill parent
|
213
|
+
def self.fill_parent(parent, x, y, rows, cols)
|
214
|
+
if (y + rows) < parent.rows
|
215
|
+
rows = parent.rows - y - 1
|
216
|
+
end
|
217
|
+
|
218
|
+
if (x + cols) < parent.cols
|
219
|
+
cols = parent.cols - x - 1
|
220
|
+
end
|
221
|
+
|
222
|
+
return rows, cols
|
113
223
|
end
|
114
224
|
|
225
|
+
###
|
226
|
+
|
115
227
|
# Invoke window finalization routine by destroying it
|
116
228
|
# and all children
|
117
229
|
def finalize!
|
230
|
+
erase
|
231
|
+
@@registry.delete(self)
|
232
|
+
|
118
233
|
children.each { |c|
|
119
234
|
del_child c
|
120
|
-
cdk_scr.destroy if cdk?
|
121
|
-
component.finalize! if component?
|
122
235
|
}
|
236
|
+
|
237
|
+
cdk_scr.destroy if cdk?
|
238
|
+
component.finalize! if component?
|
239
|
+
end
|
240
|
+
|
241
|
+
###
|
242
|
+
|
243
|
+
def expand?
|
244
|
+
!!@expand
|
245
|
+
end
|
246
|
+
|
247
|
+
def must_expand?
|
248
|
+
!!@must_expand
|
123
249
|
end
|
124
250
|
|
251
|
+
def request_expansion(r, c)
|
252
|
+
h = {:rows => r,
|
253
|
+
:cols => c,
|
254
|
+
:x => x,
|
255
|
+
:y => y}
|
256
|
+
|
257
|
+
if parent?
|
258
|
+
if parent.component.exceeds_bounds_with?(h)
|
259
|
+
if parent.component.expandable?
|
260
|
+
parent.component.expand(h)
|
261
|
+
|
262
|
+
else
|
263
|
+
raise ArgumentError, "cannot expand" if must_expand?
|
264
|
+
return false
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
else
|
269
|
+
unless Terminal.contains?(h)
|
270
|
+
raise ArgumentError, "terminal too small" if must_expand?
|
271
|
+
return false
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
resize(r, c)
|
276
|
+
true
|
277
|
+
end
|
278
|
+
|
279
|
+
###
|
280
|
+
|
125
281
|
# Return cdk screen (only used by CDK components)
|
126
282
|
def cdk_scr
|
127
283
|
enable_cdk!
|
@@ -133,6 +289,8 @@ module RETerm
|
|
133
289
|
!!@cdk_scr
|
134
290
|
end
|
135
291
|
|
292
|
+
###
|
293
|
+
|
136
294
|
# Static method returning all tracked windows
|
137
295
|
def self.all
|
138
296
|
@@registry ||= []
|
@@ -145,6 +303,8 @@ module RETerm
|
|
145
303
|
@@registry.select { |w| !w.parent? }
|
146
304
|
end
|
147
305
|
|
306
|
+
###
|
307
|
+
|
148
308
|
# Create child window, this method should not be invoked
|
149
309
|
# by end-user, rather it is is invoked the Layout#add_child
|
150
310
|
# is called.
|
@@ -155,7 +315,7 @@ module RETerm
|
|
155
315
|
c
|
156
316
|
end
|
157
317
|
|
158
|
-
# Remove child window, like #
|
318
|
+
# Remove child window, like #create_child, this is used internally
|
159
319
|
# and should not be invoked by the end user
|
160
320
|
def del_child(child)
|
161
321
|
@children.delete(child)
|
@@ -164,6 +324,41 @@ module RETerm
|
|
164
324
|
child.win.delwin
|
165
325
|
end
|
166
326
|
|
327
|
+
# Return child containing specified screen coordiantes, else nil
|
328
|
+
def child_containing(x, y, z)
|
329
|
+
found = nil
|
330
|
+
children.find { |c|
|
331
|
+
next if found
|
332
|
+
|
333
|
+
# recursively descend into layout children
|
334
|
+
if c.component.kind_of?(Layout)
|
335
|
+
found = c.child_containing(x, y, z)
|
336
|
+
|
337
|
+
else
|
338
|
+
found =
|
339
|
+
c.total_x <= x && c.total_y <= y && # c.z >= z
|
340
|
+
(c.total_x + c.cols) >= x && (c.total_y + c.rows) >= y
|
341
|
+
found = c if found
|
342
|
+
end
|
343
|
+
}
|
344
|
+
|
345
|
+
found
|
346
|
+
end
|
347
|
+
|
348
|
+
###
|
349
|
+
|
350
|
+
def resize(rows, cols)
|
351
|
+
r = win.resize rows, cols
|
352
|
+
raise ArgumentError, "could not resize window" if r == -1
|
353
|
+
|
354
|
+
@rows = rows
|
355
|
+
@cols = cols
|
356
|
+
|
357
|
+
self
|
358
|
+
end
|
359
|
+
|
360
|
+
###
|
361
|
+
|
167
362
|
# Clear window by removing all children and reinitializing window space
|
168
363
|
def clear!
|
169
364
|
children.each { |c|
|
@@ -176,7 +371,20 @@ module RETerm
|
|
176
371
|
|
177
372
|
# Erase window drawing area
|
178
373
|
def erase
|
179
|
-
|
374
|
+
children.each { |c|
|
375
|
+
c.erase
|
376
|
+
}
|
377
|
+
|
378
|
+
@win.werase if @win
|
379
|
+
|
380
|
+
component.component.erase if cdk?
|
381
|
+
end
|
382
|
+
|
383
|
+
# Erases window screen by overwriting it with blanks
|
384
|
+
def erase_scr
|
385
|
+
0.upto(rows) { |r|
|
386
|
+
mvaddstr(r, 1, " " * cols)
|
387
|
+
}
|
180
388
|
end
|
181
389
|
|
182
390
|
# Refresh / resynchronize window and all children
|
@@ -185,6 +393,17 @@ module RETerm
|
|
185
393
|
children.each { |c|
|
186
394
|
c.refresh
|
187
395
|
}
|
396
|
+
|
397
|
+
component.component.screen.refresh if cdk?
|
398
|
+
end
|
399
|
+
|
400
|
+
def noutrefresh
|
401
|
+
@win.noutrefresh
|
402
|
+
children.each { |c|
|
403
|
+
c.noutrefresh
|
404
|
+
}
|
405
|
+
|
406
|
+
component.component.screen.noutrefresh if cdk?
|
188
407
|
end
|
189
408
|
|
190
409
|
# Remove Border around window
|
@@ -202,11 +421,61 @@ module RETerm
|
|
202
421
|
@win.getch
|
203
422
|
end
|
204
423
|
|
424
|
+
# Normal getch unless sync enabled in which case,
|
425
|
+
# timeout will be checked & components synchronized
|
426
|
+
def sync_getch
|
427
|
+
return self.getch unless sync_enabled?
|
428
|
+
|
429
|
+
c = -1
|
430
|
+
while c == -1 && !shutdown?
|
431
|
+
c = self.getch
|
432
|
+
run_sync!
|
433
|
+
end
|
434
|
+
|
435
|
+
c
|
436
|
+
end
|
437
|
+
|
438
|
+
# Dispatch to component synchronization
|
439
|
+
def sync!
|
440
|
+
component.sync! if component?
|
441
|
+
children.each { |c|
|
442
|
+
c.sync!
|
443
|
+
}
|
444
|
+
end
|
445
|
+
|
205
446
|
# Write string at specified loc
|
206
447
|
def mvaddstr(*a)
|
207
448
|
@win.mvaddstr(*a)
|
208
449
|
end
|
209
450
|
|
451
|
+
# Enable bold formatting
|
452
|
+
def bold!
|
453
|
+
@win.attron(Ncurses::A_BOLD)
|
454
|
+
return unless block_given?
|
455
|
+
|
456
|
+
yield
|
457
|
+
@win.attroff(Ncurses::A_BOLD)
|
458
|
+
end
|
459
|
+
|
460
|
+
# Disable bold formatting
|
461
|
+
def no_bold!
|
462
|
+
@win.attroff(Ncurses::A_BOLD)
|
463
|
+
end
|
464
|
+
|
465
|
+
# Enable reverse formatting
|
466
|
+
def reverse!
|
467
|
+
@win.attron(Ncurses::A_REVERSE)
|
468
|
+
return unless block_given?
|
469
|
+
|
470
|
+
yield
|
471
|
+
@win.attroff(Ncurses::A_REVERSE)
|
472
|
+
end
|
473
|
+
|
474
|
+
# Disabled reverse formatting
|
475
|
+
def no_reverse!
|
476
|
+
@win.attroff(Ncurses::A_REVERSE)
|
477
|
+
end
|
478
|
+
|
210
479
|
# Return bool indiciating if colors are set
|
211
480
|
def colored?
|
212
481
|
!!@colors
|
@@ -214,8 +483,8 @@ module RETerm
|
|
214
483
|
|
215
484
|
# Set window color
|
216
485
|
def colors=(c)
|
217
|
-
@colors = c.is_a?(ColorPair) ? c : ColorPair.for(c)
|
218
|
-
@win.bkgd(Ncurses.COLOR_PAIR(@colors.id))
|
486
|
+
@colors = c.is_a?(ColorPair) ? c : ColorPair.for(c).first
|
487
|
+
@win.bkgd(Ncurses.COLOR_PAIR(@colors.id)) unless @win.nil?
|
219
488
|
|
220
489
|
component.colors = @colors if component?
|
221
490
|
|
@@ -226,24 +495,21 @@ module RETerm
|
|
226
495
|
|
227
496
|
# Return window dimensions as an array containing rows & cols
|
228
497
|
def dimensions
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
cols = cols.first
|
236
|
-
[rows, cols]
|
237
|
-
end
|
498
|
+
rows = []
|
499
|
+
cols = []
|
500
|
+
@win.getmaxyx(rows, cols)
|
501
|
+
rows = rows.first
|
502
|
+
cols = cols.first
|
503
|
+
[rows, cols]
|
238
504
|
end
|
239
505
|
|
240
506
|
# Return window rows
|
241
|
-
def
|
507
|
+
def actual_rows
|
242
508
|
dimensions[0]
|
243
509
|
end
|
244
510
|
|
245
511
|
# Return window cols
|
246
|
-
def
|
512
|
+
def actual_cols
|
247
513
|
dimensions[1]
|
248
514
|
end
|
249
515
|
|
@@ -253,8 +519,8 @@ module RETerm
|
|
253
519
|
end
|
254
520
|
|
255
521
|
# Activate window component
|
256
|
-
def activate!
|
257
|
-
component.activate!
|
522
|
+
def activate!(*input)
|
523
|
+
component.activate!(*input)
|
258
524
|
end
|
259
525
|
end
|
260
526
|
end # module RETerm
|