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,19 +1,40 @@
1
1
  module RETerm
2
2
  module Layouts
3
- # Layout which arrainges items horizontally across screen cols
3
+ # Layout which arainges items horizontally across screen cols
4
4
  class Horizontal < Layout
5
+ def current_rows
6
+ return 1 if empty?
7
+ child_windows.max { |w1, w2| w1.rows <=> w2.rows }.rows
8
+ end
9
+
5
10
  def current_cols
6
- children.sum { |c| c.cols } + 1
11
+ return 1 if empty?
12
+ child_windows.sum { |c| c.cols } + 1
7
13
  end
8
14
 
9
- def exceeds_bounds?(child)
10
- child.rows > window.rows || (current_cols + child.cols) > window.cols
15
+ def exceeds_bounds_with?(child)
16
+ rows = child.is_a?(Hash) ?
17
+ [current_rows, child[:rows]].compact.max :
18
+ [current_rows, child.rows].max
19
+
20
+ cols = child.is_a?(Hash) ?
21
+ current_cols + child[:cols] :
22
+ current_cols + child.cols
23
+
24
+ rows > window.rows ||
25
+ cols > window.cols
11
26
  end
12
27
 
13
28
  def add_child(h={})
14
29
  # set x/y to next appropriate location
15
30
  super(h.merge(:y => 1, :x => current_cols))
16
31
  end
32
+
33
+ def valid_input?(ch, from_parent)
34
+ return true unless from_parent
35
+ !((UP_CONTROLS.include?(ch) && window.first_child?) ||
36
+ (DOWN_CONTROLS.include?(ch) && window.last_child?))
37
+ end
17
38
  end # class Horizontal
18
39
  end # module Layouts
19
40
  end # module RETerm
@@ -1,19 +1,40 @@
1
1
  module RETerm
2
2
  module Layouts
3
- # Layout which arrainges items vertically down screen rows
3
+ # Layout which arainges items vertically down screen rows
4
4
  class Vertical < Layout
5
5
  def current_rows
6
- children.sum { |c| c.rows } + 1
6
+ return 1 if empty?
7
+ child_windows.sum { |c| c.rows } + 1
7
8
  end
8
9
 
9
- def exceeds_bounds?(child)
10
- child.cols > window.cols || (current_rows + child.rows) > window.rows
10
+ def current_cols
11
+ return 1 if empty?
12
+ child_windows.max { |w1, w2| w1.cols <=> w2.cols }.cols
13
+ end
14
+
15
+ def exceeds_bounds_with?(child)
16
+ cols = child.is_a?(Hash) ?
17
+ [current_cols, child[:cols]].compact.max :
18
+ [current_cols, child.cols].max
19
+
20
+ rows = child.is_a?(Hash) ?
21
+ current_rows + child[:rows] :
22
+ current_rows + child.rows
23
+
24
+ cols > window.cols ||
25
+ rows > window.rows
11
26
  end
12
27
 
13
28
  def add_child(h={})
14
29
  # set x/y to next appropriate location
15
30
  super(h.merge(:y => current_rows, :x => 1))
16
31
  end
17
- end # class Horizontal
32
+
33
+ def valid_input?(ch, from_parent)
34
+ return true unless from_parent
35
+ !((LEFT_CONTROLS.include?(ch) && window.first_child?) ||
36
+ (RIGHT_CONTROLS.include?(ch) && window.last_child?))
37
+ end
38
+ end # class Vertical
18
39
  end # module Layouts
19
40
  end # module RETerm
data/lib/reterm/loader.rb CHANGED
@@ -49,7 +49,7 @@ module RETerm
49
49
  parse_child(w, win)
50
50
 
51
51
  w.border! if win.key?('border') && !!win['border']
52
- w.colors = ColorPair.for(win['colors']) if win.key?('colors')
52
+ w.colors = ColorPair.for(win['colors']).first if win.key?('colors')
53
53
 
54
54
  w
55
55
  end
@@ -113,7 +113,7 @@ module RETerm
113
113
  :cols => cols
114
114
 
115
115
  cw.border! if child.key?('border') && !!child['border']
116
- cw.colors = ColorPair.for(child['colors']) if child.key?('colors')
116
+ cw.colors = ColorPair.for(child['colors']).first if child.key?('colors')
117
117
 
118
118
  cw.component = parse_child(cw, child)
119
119
  }
@@ -0,0 +1,7 @@
1
+ module RETerm
2
+ module ButtonHelpers
3
+ def total_button_size
4
+ @buttons.sum { |b| b.size }
5
+ end
6
+ end # module ButtonHelpers
7
+ end # module RETerm
@@ -1,6 +1,20 @@
1
1
  module RETerm
2
2
  # Mixin used by CDK based component defining cdk-specific helpers
3
3
  module CDKComponent
4
+ def init_cdk(args={})
5
+ self.title_attrib = args[:title_attrib] if args.key?(:title_attrib)
6
+ end
7
+
8
+ def title_attrib=(a)
9
+ @title_attrib = a
10
+ component.title_attrib = a if defined?(@component)
11
+ end
12
+
13
+ # Boolean indicating this component is a cdk component
14
+ def cdk?
15
+ true
16
+ end
17
+
4
18
  # Should be implemented in subclass to initialize component
5
19
  def _component
6
20
  raise "NotImplemented"
@@ -12,10 +26,28 @@ module RETerm
12
26
  @component ||= begin
13
27
  c = _component
14
28
  c.setBackgroundColor("</#{@colors.id}>") if colored?
29
+ c.timeout(SYNC_TIMEOUT) if sync_enabled? # XXX
30
+ c.title_attrib = @title_attrib if @title_attrib
15
31
  c
16
32
  end
17
33
  end
18
34
 
35
+ # Return boolean indicating if escape was hit
36
+ def escape_hit?
37
+ component.exit_type == :ESCAPE_HIT
38
+ end
39
+
40
+ # Return boolean indicating early exit occurred
41
+ def early_exit?
42
+ component.exit_type == :EARLY_EXIT
43
+ end
44
+
45
+ # Return boolean indicating if user selection made / normal
46
+ # exit was invoked
47
+ def normal_exit?
48
+ component.exit_type == :NORMAL
49
+ end
50
+
19
51
  # Assign {ColorPair} to component
20
52
  def colors=(c)
21
53
  super
@@ -27,19 +59,51 @@ module RETerm
27
59
  component.draw([])
28
60
  end
29
61
 
62
+ def erase
63
+ component.erase
64
+ end
65
+
30
66
  # CDK components may be activated
31
67
  def activatable?
32
68
  true
33
69
  end
34
70
 
35
71
  # Invoke CDK activation routine
36
- def activate!
37
- component.activate([])
72
+ def activate!(*input)
73
+ dispatch :activated
74
+ component.resetExitType
75
+
76
+ r = nil
77
+
78
+ while [:EARLY_EXIT, :NEVER_ACTIVATED, :TIMEOUT].include?(component.exit_type) &&
79
+ !shutdown?
80
+ r = component.activate(input)
81
+ run_sync! if sync_enabled?
82
+ end
83
+
84
+ dispatch :deactivated
85
+ r
86
+ end
87
+
88
+ def deactivate!
89
+ component.activate [CDK::KEY_ESC]
90
+ dispatch :deactivated
38
91
  end
39
92
 
40
93
  # Return stored value of cdk component
41
94
  def value
42
95
  component.getValue
43
96
  end
97
+
98
+ # Override bind_key to use cdk bindings mechanism
99
+ def bind_key(key, kcb=nil, &bl)
100
+ kcb = bl if kcb.nil? && !bl.nil?
101
+
102
+ cb = lambda do |cdktype, widget, component, key|
103
+ kcb.call component, key
104
+ end
105
+
106
+ component.bind(:ENTRY, key, cb, self)
107
+ end
44
108
  end # module CDKComponent
45
109
  end # module RETerm
@@ -0,0 +1,15 @@
1
+ module RETerm
2
+ # XXX copied from CDK
3
+ module CommonControls
4
+ attr_reader :quit_on_enter
5
+
6
+ def quit_on_enter=(v)
7
+ @quit_on_enter_set = true
8
+ @quit_on_enter = v
9
+ end
10
+
11
+ def quit_on_enter?
12
+ @quit_on_enter_set ? @quit_on_enter : true
13
+ end
14
+ end # module CommonControls
15
+ end # module CDK
@@ -0,0 +1,20 @@
1
+ module RETerm
2
+ module CommonKeys
3
+ # Key which if pressed cause the component to
4
+ # lose focus / become deactivated
5
+ QUIT_CONTROLS = [10, 27, Ncurses::KEY_ENTER] # 10 = enter, 27 = ESC,
6
+
7
+ # \033 = CDK::KEY_ESC
8
+ # 343 = NCURSES::KEY_ENTER
9
+
10
+ ENTER_CONTROLS = [10, Ncurses::KEY_ENTER] # quit controls with out esc
11
+
12
+ # Keys if pressed invoked the increment operation
13
+ INC_CONTROLS = ['+'.ord, Ncurses::KEY_UP, Ncurses::KEY_RIGHT]
14
+
15
+ # Keys if pressed invoked the decrement operation
16
+ DEC_CONTROLS = ['-'.ord, Ncurses::KEY_DOWN, Ncurses::KEY_LEFT]
17
+
18
+ # TODO add page/scroll controls
19
+ end # module CommonKeys
20
+ end # module CDK
@@ -3,35 +3,83 @@ module RETerm
3
3
  # components. 'In House' components included in the project
4
4
  # may used this to standarding their usage.
5
5
  module ComponentInput
6
- # Key which if pressed cause the component to
7
- # lose focus / become deactivated
8
- QUIT_CONTROLS = [10, 27] # 10 = enter, 27 = ESC
6
+ include CommonControls
7
+ include CommonKeys
9
8
 
10
- # Keys if pressed invoked the increment operation
11
- INC_CONTROLS = ['+'.ord, Ncurses::KEY_UP, Ncurses::KEY_RIGHT]
9
+ # TODO include / incorporate MouseInput mixin
10
+ # (scroll sliders/dials, click buttons, etc) ...
12
11
 
13
- # Keys if pressed invoked the decrement operation
14
- DEC_CONTROLS = ['-'.ord, Ncurses::KEY_DOWN, Ncurses::KEY_LEFT]
15
-
16
- # May be overrideen in subclass, invoked when the user requests
12
+ # May be overridden in subclass, invoked when the user requests
17
13
  # an 'increment'
18
14
  def on_inc
19
15
  end
20
16
 
21
- # May be overrideen in subclass, invoked when the user
17
+ # May be overridden in subclass, invoked when the user
22
18
  # requests a decrement
23
19
  def on_dec
24
20
  end
25
21
 
22
+ # May be overridden in subclass, invoked when the user inputs
23
+ # the enter key (unless quit_on_enter is true)
24
+ def on_enter
25
+ end
26
+
27
+ # May be overridden in subclass, invoked with every key entered
28
+ def on_key(ch)
29
+ end
30
+
26
31
  # Helper to be internally invoked by component on activation
27
- def handle_input
28
- while(!QUIT_CONTROLS.include?((ch = window.getch)))
29
- if INC_CONTROLS.include?(ch)
32
+ def handle_input(*input)
33
+ while ch = next_ch(input)
34
+ quit = QUIT_CONTROLS.include?(ch)
35
+ enter = ENTER_CONTROLS.include?(ch)
36
+ inc = INC_CONTROLS.include?(ch)
37
+ dec = DEC_CONTROLS.include?(ch)
38
+
39
+ break if shutdown? ||
40
+ (quit && (!enter || quit_on_enter?))
41
+
42
+ if enter
43
+ on_enter
44
+
45
+ elsif inc
30
46
  on_inc
31
- elsif DEC_CONTROLS.include?(ch)
47
+
48
+ elsif dec
32
49
  on_dec
33
50
  end
51
+
52
+ if key_bound?(ch)
53
+ invoke_key_bindings(ch)
54
+ end
55
+
56
+ on_key(ch)
34
57
  end
58
+
59
+ ch
60
+ end
61
+
62
+ def bind_key(key, kcb)
63
+ @bound_keys ||= {}
64
+ @bound_keys[key] ||= []
65
+ @bound_keys[key] << kcb
66
+ nil
67
+ end
68
+
69
+ def key_bound?(key)
70
+ @bound_keys ||= {}
71
+ @bound_keys.key?(key)
72
+ end
73
+
74
+ private
75
+
76
+ def next_ch(input)
77
+ return sync_getch if input.empty?
78
+ input.shift
79
+ end
80
+
81
+ def invoke_key_bindings(key)
82
+ @bound_keys[key].each { |b| b.call self, key }
35
83
  end
36
84
  end # module ComponentInput
37
85
  end # module RETerm
@@ -9,6 +9,8 @@ module RETerm
9
9
  @event_handlers[e].each { |eh|
10
10
  eh.call h
11
11
  } if @event_handlers.key?(e)
12
+
13
+ nil # return last handler return value or perhaps all ?
12
14
  end
13
15
 
14
16
  def handle(e, &bl)
@@ -0,0 +1,8 @@
1
+ module RETerm
2
+ module ItemHelpers
3
+ def max_item_size
4
+ return 0 if @items.empty?
5
+ @items.max { |i1, i2| i1.size <=> i2.size }.size
6
+ end
7
+ end # module ItemHelpers
8
+ end # module RETerm
@@ -0,0 +1,23 @@
1
+ module RETerm
2
+ # Similar to the bindings mixin in the CDK library
3
+ module KeyBindings
4
+ def key_bindings
5
+ @key_bindings ||= {}
6
+ end
7
+
8
+ def bind_key(key, kcb=nil, &bl)
9
+ key_bindings[key] ||= []
10
+ kcb = bl if kcb.nil? && !bl.nil?
11
+ key_bindings[key] << kcb
12
+ end
13
+
14
+ def key_bound?(key)
15
+ key_bindings.key?(key)
16
+ end
17
+
18
+ def invoke_key_bindings(key)
19
+ o = self
20
+ key_bindings[key].all? { |kcb| kcb.call(o, key) }
21
+ end
22
+ end # module ButtonBindings
23
+ end # module RETerm
@@ -0,0 +1,13 @@
1
+ module RETerm
2
+ # Helpers defin
3
+ module LogHelpers
4
+ LOG_FILE = './reterm.log'
5
+
6
+ def logger
7
+ require 'logger'
8
+ @@logger ||= Logger.new LOG_FILE
9
+ end
10
+
11
+ alias :log :logger
12
+ end # module LogHelpers
13
+ end # module RETerm
@@ -0,0 +1,58 @@
1
+ module RETerm
2
+ module MouseInput
3
+ ALL_EVENTS = Ncurses::ALL_MOUSE_EVENTS |
4
+ Ncurses::REPORT_MOUSE_POSITION
5
+
6
+ MOUSE_MAP = {
7
+ :PRESSED => :pressed,
8
+ :RELEASED => :released,
9
+ :CLICKED => :click,
10
+ :DOUBLE_CLICKED => :dclick,
11
+ :TRIPLE_CLICKED => :tclick,
12
+ }
13
+
14
+ def mouse_paste?
15
+ !!reterm_opts[:mouse_paste]
16
+ end
17
+
18
+ # May be overridden in subclass, invoked when
19
+ # the user interacts with a button.
20
+ #
21
+ # @param [Integer] b number of the button that was invoked
22
+ # @param [Symbol] evnt button event, may be :press, :release,
23
+ # :click, :dclick (double click), :tclick (triple click)
24
+ def on_button(b, evnt, coords)
25
+ #puts "B#{b} #{evnt}, #{coords}"
26
+ end
27
+
28
+ def process_mouse(ch)
29
+ return nil unless ch == Ncurses::KEY_MOUSE
30
+
31
+ mev = Ncurses::MEVENT.new
32
+ Ncurses.getmouse(mev)
33
+
34
+ if mev.bstate == Ncurses::BUTTON2_CLICKED && mouse_paste?
35
+ # TODO grab clipboard buffer & return character array
36
+ # (need to handle seperately in invoker)
37
+ #
38
+ # use https://github.com/janlelis/clipboard
39
+ # but note this requires external programs!
40
+ end
41
+
42
+ # TODO 5 button support (requiest "--enable-ext-mouse" ncurses flag
43
+ # which is not specified in many major distrubtions)
44
+ 1.upto(4).each { |b|
45
+ MOUSE_MAP.each { |n, e|
46
+ if mev.bstate == Ncurses.const_get("BUTTON#{b}_#{n}")
47
+ x,y,z = mev.x, mev.y, mev.z
48
+ on_button(b, e, [x,y,z])
49
+ end
50
+ }
51
+ }
52
+
53
+ # TODO wrap MEVENT w/ our own class,
54
+ # w/ high levels helpers for buttons, coords, etc
55
+ mev
56
+ end
57
+ end # module MouseInput
58
+ end # module RETerm