reterm 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/designer/src/ComponentParams.rb +89 -42
  3. data/designer/src/ComponentsList.rb +26 -25
  4. data/designer/src/CreatedList.rb +9 -0
  5. data/designer/src/Designer.rb +23 -1
  6. data/designer/src/ToggleArea.rb +20 -3
  7. data/designer/src/about.rb +35 -0
  8. data/designer/src/component_factory.rb +18 -0
  9. data/designer/src/component_map.rb +7 -0
  10. data/designer/src/file_chooser.rb +25 -0
  11. data/designer/src/glade/Designer.glade +1 -19
  12. data/designer/src/images/{slist.png → scroll_list.png} +0 -0
  13. data/lib/reterm.rb +10 -1
  14. data/lib/reterm/color_pair.rb +166 -10
  15. data/lib/reterm/component.rb +89 -2
  16. data/lib/reterm/components.rb +16 -1
  17. data/lib/reterm/components/alphalist.rb +45 -0
  18. data/lib/reterm/components/ascii_text.rb +14 -1
  19. data/lib/reterm/components/asciimator.rb +1 -0
  20. data/lib/reterm/components/button.rb +35 -5
  21. data/lib/reterm/components/button_box.rb +108 -0
  22. data/lib/reterm/components/close_button.rb +22 -0
  23. data/lib/reterm/components/cmd_output.rb +69 -0
  24. data/lib/reterm/components/dial.rb +11 -2
  25. data/lib/reterm/components/dialog.rb +41 -1
  26. data/lib/reterm/components/drop_down_menu.rb +140 -0
  27. data/lib/reterm/components/entry.rb +42 -14
  28. data/lib/reterm/components/histogram.rb +55 -0
  29. data/lib/reterm/components/hslider.rb +9 -0
  30. data/lib/reterm/components/image.rb +9 -0
  31. data/lib/reterm/components/isometric.rb +38 -0
  32. data/lib/reterm/components/label.rb +20 -3
  33. data/lib/reterm/components/matrix.rb +9 -0
  34. data/lib/reterm/components/multi_line_entry.rb +54 -0
  35. data/lib/reterm/components/password_entry.rb +15 -0
  36. data/lib/reterm/components/radio.rb +10 -0
  37. data/lib/reterm/components/revealing_label.rb +126 -0
  38. data/lib/reterm/components/rocker.rb +21 -11
  39. data/lib/reterm/components/scroll_list.rb +96 -0
  40. data/lib/reterm/components/scrolling_area.rb +50 -0
  41. data/lib/reterm/components/select_list.rb +67 -0
  42. data/lib/reterm/components/splash.rb +85 -0
  43. data/lib/reterm/components/template.rb +12 -1
  44. data/lib/reterm/components/treeview.rb +1 -0
  45. data/lib/reterm/components/vslider.rb +11 -2
  46. data/lib/reterm/components/youtube.rb +20 -0
  47. data/lib/reterm/config.rb +22 -0
  48. data/lib/reterm/init.rb +131 -6
  49. data/lib/reterm/layout.rb +147 -11
  50. data/lib/reterm/layouts.rb +1 -0
  51. data/lib/reterm/layouts/grid.rb +69 -0
  52. data/lib/reterm/layouts/horizontal.rb +25 -4
  53. data/lib/reterm/layouts/vertical.rb +26 -5
  54. data/lib/reterm/loader.rb +2 -2
  55. data/lib/reterm/mixins/button_helpers.rb +7 -0
  56. data/lib/reterm/mixins/cdk_component.rb +66 -2
  57. data/lib/reterm/mixins/common_controls.rb +15 -0
  58. data/lib/reterm/mixins/common_keys.rb +20 -0
  59. data/lib/reterm/mixins/component_input.rb +62 -14
  60. data/lib/reterm/mixins/event_dispatcher.rb +2 -0
  61. data/lib/reterm/mixins/item_helpers.rb +8 -0
  62. data/lib/reterm/mixins/key_bindings.rb +23 -0
  63. data/lib/reterm/mixins/log_helpers.rb +13 -0
  64. data/lib/reterm/mixins/mouse_input.rb +58 -0
  65. data/lib/reterm/mixins/nav_controls.rb +33 -0
  66. data/lib/reterm/mixins/nav_input.rb +161 -69
  67. data/lib/reterm/terminal.rb +6 -2
  68. data/lib/reterm/util.rb +121 -0
  69. data/lib/reterm/version.rb +1 -1
  70. data/lib/reterm/window.rb +295 -29
  71. metadata +33 -17
  72. data/designer/src/images/orig/Check.png +0 -0
  73. data/designer/src/images/orig/ascii_text.png +0 -0
  74. data/designer/src/images/orig/button.png +0 -0
  75. data/designer/src/images/orig/dial.png +0 -0
  76. data/designer/src/images/orig/entry.png +0 -0
  77. data/designer/src/images/orig/hslider.png +0 -0
  78. data/designer/src/images/orig/label.png +0 -0
  79. data/designer/src/images/orig/matrix.png +0 -0
  80. data/designer/src/images/orig/radio.png +0 -0
  81. data/designer/src/images/orig/rocker.png +0 -0
  82. data/designer/src/images/orig/slist.png +0 -0
  83. data/designer/src/images/orig/vslider.png +0 -0
  84. data/lib/reterm/components/slist.rb +0 -32
  85. data/lib/reterm/menu.rb +0 -81
@@ -1,3 +1,3 @@
1
1
  module RETerm
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end # module RETerm
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
- c.window = self
52
- c.colors = @colors if colored?
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 registery for subsequent tracking.
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
- @rows = args[:rows] || (Terminal.rows - 1)
85
- @cols = args[:cols] || (Terminal.cols - 1)
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
- self.component = args[:component] if args.key?(:component)
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
- @children = []
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
- @@wid ||= 0
110
- @@wid += 1
178
+ @fill = !!args[:fill]
179
+ end
111
180
 
112
- @window_id = @@wid
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 #add_child, this is used internally
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
- @win.werase
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
- @dimensions ||=
230
- begin
231
- rows = []
232
- cols = []
233
- @win.getmaxyx(rows, cols)
234
- rows = rows.first
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 rows
507
+ def actual_rows
242
508
  dimensions[0]
243
509
  end
244
510
 
245
511
  # Return window cols
246
- def cols
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