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
@@ -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