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.
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
@@ -0,0 +1,45 @@
1
+ module RETerm
2
+ module Components
3
+ # Alpha List CDK Component
4
+ class AlphaList < Component
5
+ include CDKComponent
6
+ include ItemHelpers
7
+
8
+ # Initialize the AlphaList component
9
+ #
10
+ # @param [Hash] args list params
11
+ # @option args [String] :title title of list
12
+ # @option args [String] :label title of list
13
+ # @option args [Array<String>] :items items to
14
+ # populate list with
15
+ def initialize(args={})
16
+ super
17
+ @title = args[:title] || ""
18
+ @label = args[:label] || ""
19
+ @items = args[:items] || []
20
+ end
21
+
22
+ def requested_rows
23
+ [@items.size + 5, 10].min
24
+ end
25
+
26
+ def requested_cols
27
+ [@title.size, @label.size, max_item_size, 20].max + 2
28
+ end
29
+
30
+ private
31
+
32
+ def _component
33
+ CDK::ALPHALIST.new(window.cdk_scr,
34
+ 2, 1, # x, y
35
+ window.rows - 2, # height
36
+ window.cols - 2, # width
37
+ @title, @label,
38
+ @items, @items.size,
39
+ '_', # filler char
40
+ Ncurses::A_REVERSE, # highlight
41
+ true, false) # box, shadow
42
+ end
43
+ end # AlphaList
44
+ end # module Components
45
+ end # module RETerm
@@ -12,10 +12,19 @@ module RETerm
12
12
  # default empty string
13
13
  # @option args [String] :font font to use
14
14
  def initialize(args={})
15
+ super
15
16
  @text = args[:text] || ""
16
17
  @font = args[:font]
17
18
  end
18
19
 
20
+ def requested_rows
21
+ lines.size + 1
22
+ end
23
+
24
+ def requested_cols
25
+ lines.max { |l1, l2| l1.size <=> l2.size }.size + 1
26
+ end
27
+
19
28
  def draw!
20
29
  refresh_win
21
30
  end
@@ -31,9 +40,13 @@ module RETerm
31
40
  end
32
41
  end
33
42
 
43
+ def lines
44
+ @lines ||= atext.split("\n")
45
+ end
46
+
34
47
  def refresh_win
35
48
  y = 1
36
- atext.split("\n").each { |t|
49
+ lines.each { |t|
37
50
  window.mvaddstr(y, 1, t)
38
51
  y += 1
39
52
  }
@@ -0,0 +1 @@
1
+ # TODO https://www.asciimator.net integration
@@ -9,22 +9,52 @@ module RETerm
9
9
  # @param [Hash] args button params
10
10
  # @option args [String] :title title of button
11
11
  def initialize(args={})
12
+ super
12
13
  @title = args[:title] || ""
13
14
  end
14
15
 
16
+ attr_reader :title
17
+
18
+ def title=(t)
19
+ @title = t
20
+ component.setMessage(t)
21
+ end
22
+
23
+ def skip_formatting=(b)
24
+ component.skip_formatting = b
25
+ end
26
+
27
+ def requested_rows
28
+ 2
29
+ end
30
+
31
+ def requested_cols
32
+ @title.size + 1
33
+ end
34
+
35
+ def activate!
36
+ dispatch :clicked
37
+ deactivate!
38
+ end
39
+
40
+ def click!
41
+ activate!
42
+ end
43
+
15
44
  private
16
45
 
17
46
  def callback
18
47
  proc { |b|
19
- puts "Clicked"
48
+ dispatch :clicked
20
49
  }
21
50
  end
22
51
 
23
52
  def _component
24
- CDK::BUTTON.new(window.cdk_scr, # cdk screen
25
- 2, 1, @title, # x, y, title
26
- callback, # click callback
27
- false, false) # box, shadow
53
+ CDK::BUTTON.new(window.cdk_scr, # cdk screen
54
+ CDK::CENTER, CDK::CENTER, # x, y
55
+ @title, # title
56
+ callback, # click callback
57
+ false, false) # box, shadow
28
58
  end
29
59
  end # Button
30
60
  end # module Components
@@ -0,0 +1,108 @@
1
+ module RETerm
2
+ module Components
3
+ # CDK ButtonBox Component
4
+ class ButtonBox < Component
5
+ include CDKComponent
6
+ include ButtonHelpers
7
+
8
+ attr_accessor :widget
9
+
10
+ # Initialize the ButtonBox component
11
+ #
12
+ # @param [Hash] args button box params
13
+ # @option args [Component] :widget component
14
+ # to include in the button box
15
+ # @option args [String] :title title
16
+ # to assign to button box
17
+ # @option args [String, Array<String>] :buttons string
18
+ # buttons to assign to dialog
19
+ #
20
+ def initialize(args={})
21
+ super
22
+ @widget = args[:widget]
23
+ @title = args[:title] || ""
24
+ @buttons = [args[:buttons]].flatten.compact
25
+
26
+ @buttons = ["OK", "Cancel"] if @buttons.empty?
27
+ end
28
+
29
+ def requested_rows
30
+ @widget.requested_rows
31
+ end
32
+
33
+ def requested_cols
34
+ [@title.size, total_button_size, @widget.requested_cols].max
35
+ end
36
+
37
+ def close!
38
+ widget.erase
39
+ widget.finalize!
40
+
41
+ window.erase
42
+ window.finalize!
43
+ end
44
+
45
+ def window=(win)
46
+ super(win)
47
+ cw = win.create_child :rows => widget.requested_rows,
48
+ :cols => [widget.requested_cols, requested_cols].max
49
+ raise ArgumentError, "could not create child" if cw.win.nil?
50
+ cw.component = widget
51
+ end
52
+
53
+ def activate!(*input)
54
+ widget.draw!
55
+ component.draw(true)
56
+
57
+ if widget.activatable?
58
+ widget.activate!(*input)
59
+ else
60
+ super
61
+ end
62
+
63
+ @buttons[component.current_button]
64
+ end
65
+
66
+ def selected
67
+ @buttons[component.current_button]
68
+ end
69
+
70
+ private
71
+
72
+ def _component
73
+ w = CDK::BUTTONBOX.new(window.cdk_scr,
74
+ window.win.getbegx,
75
+ window.win.getbegy +
76
+ widget.window.rows - 1,
77
+ (@title.nil? || @title.empty?) ? 1 : 2, # height
78
+ widget.window.cols - 1, # width
79
+ @title,
80
+ 1, 2, # rows / cols
81
+ @buttons, @buttons.size,
82
+ Ncurses::A_REVERSE, # highligh
83
+ true, false) # box, shadow
84
+
85
+ widget.window.border!
86
+
87
+ widget.component.setLLchar(Ncurses::ACS_LTEE) if widget.cdk? && widget.component.respond_to?(:setLLchar)
88
+ widget.component.setLRchar(Ncurses::ACS_RTEE) if widget.cdk? && widget.component.respond_to?(:setLRchar)
89
+
90
+ w.setULchar(Ncurses::ACS_LTEE)
91
+ w.setURchar(Ncurses::ACS_RTEE)
92
+
93
+ # bind tab/left/right key to button box
94
+ widget_cb = lambda do |widget, key|
95
+ w.inject(key)
96
+ return true
97
+ end
98
+
99
+ # TODO allow specific keys overriding of specific keys to be disabled
100
+ widget.bind_key(CDK::KEY_TAB, widget_cb)
101
+ widget.bind_key(Ncurses::KEY_LEFT, widget_cb)
102
+ widget.bind_key(Ncurses::KEY_RIGHT, widget_cb)
103
+
104
+ w
105
+ end
106
+ end # Dialog
107
+ end # module Components
108
+ end # module RETerm
@@ -0,0 +1,22 @@
1
+ module RETerm
2
+ module Components
3
+ class CloseButton < Button
4
+ def initialize(args={})
5
+ super({:title => "X"}.merge(args))
6
+ end
7
+
8
+ def activate_focus?
9
+ true
10
+ end
11
+
12
+ private
13
+
14
+ def callback
15
+ proc { |b|
16
+ dispatch :clicked
17
+ shutdown!
18
+ }
19
+ end
20
+ end # CloseButton
21
+ end # module Components
22
+ end # module RETerm
@@ -0,0 +1,69 @@
1
+ require 'timeout'
2
+ require 'pty'
3
+
4
+ module RETerm
5
+ module Components
6
+ # Run command, capture and display output
7
+ class CmdOutput < ScrollingArea
8
+ # Initialize the CmdOutput component
9
+ #
10
+ # @param [Hash] args cmd output params
11
+ # @option args [String] :cmd command to run
12
+ def initialize(args={})
13
+ activate_sync!
14
+
15
+ super
16
+ @cmd = args[:cmd]
17
+ end
18
+
19
+ def running?
20
+ !!@pid && process_alive?(@pid)
21
+ end
22
+
23
+ def sync!
24
+ out = nil
25
+ begin
26
+ out = @stdout.gets
27
+ rescue Errno::EIO
28
+ end
29
+ self << out if out
30
+ end
31
+
32
+ def finalize!
33
+ if running?
34
+ Process.kill @pid
35
+ @stdout.close
36
+ @stdout.close
37
+ end
38
+ end
39
+
40
+ def start!
41
+ @stdout, @stdin, @pid = PTY.spawn(@cmd)
42
+ self
43
+ end
44
+
45
+ def wait
46
+ while running?
47
+ begin
48
+ Timeout.timeout(SYNC_TIMEOUT.to_f/1000) do
49
+ begin
50
+ Process.waitpid @pid
51
+ rescue
52
+ # rescue needed incase process exit between
53
+ # running? check and waitpid
54
+ end
55
+ end
56
+ rescue Timeout::Error
57
+ run_sync!
58
+ end
59
+ end
60
+
61
+ # NOTE: at this point process will be closed but
62
+ # there may still be unread data in stdout/stderr
63
+ # buffers!!!
64
+
65
+ self
66
+ end
67
+ end # CmdOutput
68
+ end # module Components
69
+ end # module RETerm
@@ -20,6 +20,7 @@ module RETerm
20
20
  # val = dial.activate!
21
21
  #
22
22
  def initialize(args={})
23
+ super
23
24
  @initial_value = 0
24
25
  @increment = 0.01
25
26
  @range = [0, 1]
@@ -27,6 +28,14 @@ module RETerm
27
28
  @value = initial_value
28
29
  end
29
30
 
31
+ def requested_rows
32
+ 7
33
+ end
34
+
35
+ def requested_cols
36
+ 7
37
+ end
38
+
30
39
  def draw!
31
40
  refresh_win
32
41
  end
@@ -35,9 +44,9 @@ module RETerm
35
44
  true
36
45
  end
37
46
 
38
- def activate!
47
+ def activate!(*input)
39
48
  refresh_win
40
- handle_input
49
+ handle_input(*input)
41
50
  @value
42
51
  end
43
52
 
@@ -4,6 +4,13 @@ module RETerm
4
4
  class Dialog < Component
5
5
  include CDKComponent
6
6
 
7
+ attr_reader :buttons
8
+
9
+ BUTTONS = {
10
+ :ok => ["</B/24>OK"],
11
+ :ok_cancel => ["</B/24>OK", "</B16>Cancel"]
12
+ }
13
+
7
14
  # Initialize the Dialog component
8
15
  #
9
16
  # @param [Hash] args dialog params
@@ -13,10 +20,43 @@ module RETerm
13
20
  # buttons to assign to dialog
14
21
  #
15
22
  def initialize(args={})
23
+ super
16
24
  @message = [args[:message]].flatten.compact
17
25
  @buttons = [args[:buttons]].flatten.compact
18
26
 
19
- @buttons = ["</B/24>OK", "</B16>Cancel"] if @buttons.empty?
27
+ @buttons = BUTTONS[:ok_cancel] if @buttons.empty?
28
+ end
29
+
30
+ def selected
31
+ strip_formatting(buttons[component.current_button])
32
+ end
33
+
34
+ # Client may invoke this to
35
+ # - create dialog and window
36
+ # - activate it
37
+ # - close / cleanup
38
+ def self.show(args={})
39
+ dlg = self.new args
40
+ win = Window.new
41
+ win.component = dlg
42
+ dlg.activate!
43
+ dlg.close!
44
+ return "" unless dlg.normal_exit?
45
+ dlg.selected
46
+ end
47
+
48
+ def requested_rows
49
+ 5
50
+ end
51
+
52
+ def requested_cols
53
+ [message.size, total_button_size].max
54
+ end
55
+
56
+ def close!
57
+ window.erase
58
+ window.finalize!
59
+ self
20
60
  end
21
61
 
22
62
  private
@@ -0,0 +1,140 @@
1
+ module RETerm
2
+ module Components
3
+ # CDK Drop Down Menu Component
4
+ class DropDownMenu < Component
5
+ include CDKComponent
6
+
7
+ # Initialize the Menu component
8
+ #
9
+ # @param [Hash] args menu params
10
+ # @option args [Array<Hash<String, Symbol>>] :menus array of menus,
11
+ # each an hash of item labels / values
12
+ # @option args [Array<Symbol>] :locs locations of menus
13
+ # @option args [Symbol] :pos menu position (default top)
14
+ # @option args [ColorPair] :color color to assign to drop down
15
+ # menu items
16
+ # @option args [ColorPair] :backound color pair to assign to
17
+ # menu bar background color
18
+ def initialize(args={})
19
+ super
20
+ @menus = args[:menus] || []
21
+ @locs = args[:locs] || 0.upto(size-1).collect { :left }
22
+ @pos = args[:pos] || :top
23
+ @color = args[:color]
24
+ @background = args[:background]
25
+
26
+ @prev = nil
27
+ end
28
+
29
+ def background?
30
+ !!@background
31
+ end
32
+
33
+ def finalize!
34
+ @bgwin.finalize! if background?
35
+ end
36
+
37
+ def menu_list
38
+ @menus.collect { |m| m.keys }
39
+ end
40
+
41
+ def colored_menu_list
42
+ return menu_list unless !!@color
43
+ menu_list.collect { |ms| ms.collect { |m| "#{@color.cdk_fmt}#{m}" }}
44
+ end
45
+
46
+ def size
47
+ @menus.size
48
+ end
49
+
50
+ def requested_cols
51
+ total_cols + total_sp + 3
52
+ end
53
+
54
+ def requested_rows
55
+ max_items + 2
56
+ end
57
+
58
+ def draw!
59
+ super
60
+ @bgwin.mvaddstr(0, 0, ' ' * requested_cols) if background?
61
+ end
62
+
63
+ def window=(w)
64
+ win = super(w)
65
+
66
+ # add a window to render menu bar background
67
+ if background?
68
+ c = win.create_child :x => 0,
69
+ :y => 0,
70
+ :rows => 1,
71
+ :cols => requested_cols - 2
72
+ c.colors = @background
73
+ @bgwin = c
74
+ end
75
+
76
+ win
77
+ end
78
+
79
+ def submenu_sizes
80
+ @menus.collect { |m| m.size }
81
+ end
82
+
83
+ def selected
84
+ @menus[component.current_title][@menus[component.current_title].keys[component.current_subtitle+1]]
85
+ end
86
+
87
+ def activate!(*input)
88
+ r = super
89
+ return nil if early_exit?
90
+ m = r / 100
91
+ i = r % 100
92
+
93
+ @menus[m][@menus[m].keys[i+1]]
94
+ end
95
+
96
+ def highlight_focus?
97
+ false
98
+ end
99
+
100
+ private
101
+
102
+ def total_cols
103
+ menu_list.sum { |m| m.first.size }
104
+ end
105
+
106
+ def total_sp
107
+ menu_list.size - 1
108
+ end
109
+
110
+ def max_items
111
+ @menus.max { |m1, m2| m1.size <=> m2.size }.size
112
+ end
113
+
114
+ def _component
115
+ locs = @locs.collect { |l| (l == :left) ? CDK::LEFT :
116
+ (l == :right ? CDK::RIGHT : l)}
117
+ pos = (@pos == :top) ? CDK::TOP :
118
+ (@pos == :bottom) ? CDK::BOTTOM : @pos
119
+
120
+ c = CDK::MENU.new(window.cdk_scr,
121
+ colored_menu_list, size,
122
+ submenu_sizes,
123
+ locs, pos,
124
+ Ncurses::A_UNDERLINE,
125
+ Ncurses::A_REVERSE)
126
+
127
+ m = self
128
+ callback = lambda do |cdktype, menu, component, key|
129
+ component.dispatch :changed
130
+ end
131
+
132
+ c.setPostProcess(callback, self)
133
+
134
+ c
135
+ end
136
+ end # class DropDownMenu
137
+
138
+ DropDown = DropDownMenu
139
+ end # module Components
140
+ end # module RETerm