reterm 0.4.2

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +131 -0
  4. data/designer/main.rb +10 -0
  5. data/designer/src/ComponentParams.rb +120 -0
  6. data/designer/src/ComponentsList.rb +90 -0
  7. data/designer/src/CreatedList.rb +156 -0
  8. data/designer/src/Designer.rb +114 -0
  9. data/designer/src/ToggleArea.rb +67 -0
  10. data/designer/src/common.rb +1 -0
  11. data/designer/src/component_factory.rb +30 -0
  12. data/designer/src/component_map.rb +116 -0
  13. data/designer/src/glade/ComponentParams.glade +96 -0
  14. data/designer/src/glade/Designer.glade +184 -0
  15. data/designer/src/images/add.png +0 -0
  16. data/designer/src/images/asciitext.png +0 -0
  17. data/designer/src/images/blank.png +0 -0
  18. data/designer/src/images/blank_sm.png +0 -0
  19. data/designer/src/images/button.png +0 -0
  20. data/designer/src/images/dial.png +0 -0
  21. data/designer/src/images/entry.png +0 -0
  22. data/designer/src/images/hslider.png +0 -0
  23. data/designer/src/images/label.png +0 -0
  24. data/designer/src/images/matrix.png +0 -0
  25. data/designer/src/images/orig/Check.png +0 -0
  26. data/designer/src/images/orig/ascii_text.png +0 -0
  27. data/designer/src/images/orig/button.png +0 -0
  28. data/designer/src/images/orig/dial.png +0 -0
  29. data/designer/src/images/orig/entry.png +0 -0
  30. data/designer/src/images/orig/hslider.png +0 -0
  31. data/designer/src/images/orig/label.png +0 -0
  32. data/designer/src/images/orig/matrix.png +0 -0
  33. data/designer/src/images/orig/radio.png +0 -0
  34. data/designer/src/images/orig/rocker.png +0 -0
  35. data/designer/src/images/orig/slist.png +0 -0
  36. data/designer/src/images/orig/vslider.png +0 -0
  37. data/designer/src/images/radio.png +0 -0
  38. data/designer/src/images/remove.png +0 -0
  39. data/designer/src/images/rocker.png +0 -0
  40. data/designer/src/images/slist.png +0 -0
  41. data/designer/src/images/vslider.png +0 -0
  42. data/lib/reterm.rb +22 -0
  43. data/lib/reterm/color_pair.rb +66 -0
  44. data/lib/reterm/component.rb +40 -0
  45. data/lib/reterm/components.rb +32 -0
  46. data/lib/reterm/components/ascii_text.rb +46 -0
  47. data/lib/reterm/components/button.rb +31 -0
  48. data/lib/reterm/components/dial.rb +95 -0
  49. data/lib/reterm/components/dialog.rb +34 -0
  50. data/lib/reterm/components/entry.rb +38 -0
  51. data/lib/reterm/components/hslider.rb +32 -0
  52. data/lib/reterm/components/image.rb +55 -0
  53. data/lib/reterm/components/label.rb +20 -0
  54. data/lib/reterm/components/matrix.rb +43 -0
  55. data/lib/reterm/components/radio.rb +33 -0
  56. data/lib/reterm/components/rocker.rb +71 -0
  57. data/lib/reterm/components/slist.rb +32 -0
  58. data/lib/reterm/components/template.rb +23 -0
  59. data/lib/reterm/components/vslider.rb +61 -0
  60. data/lib/reterm/init.rb +95 -0
  61. data/lib/reterm/layout.rb +63 -0
  62. data/lib/reterm/layouts.rb +16 -0
  63. data/lib/reterm/layouts/horizontal.rb +19 -0
  64. data/lib/reterm/layouts/vertical.rb +19 -0
  65. data/lib/reterm/loader.rb +126 -0
  66. data/lib/reterm/menu.rb +81 -0
  67. data/lib/reterm/mixins/cdk_component.rb +45 -0
  68. data/lib/reterm/mixins/component_input.rb +37 -0
  69. data/lib/reterm/mixins/event_dispatcher.rb +20 -0
  70. data/lib/reterm/mixins/nav_input.rb +126 -0
  71. data/lib/reterm/panel.rb +37 -0
  72. data/lib/reterm/resize.rb +27 -0
  73. data/lib/reterm/terminal.rb +33 -0
  74. data/lib/reterm/version.rb +3 -0
  75. data/lib/reterm/window.rb +260 -0
  76. metadata +155 -0
@@ -0,0 +1,32 @@
1
+ module RETerm
2
+ module Components
3
+ # Horizontal Slider, implemented using Slider CDK component
4
+ class HSlider < Component
5
+ include CDKComponent
6
+
7
+ # Initialize the HSlider component
8
+ #
9
+ # @param [Hash] args slider params
10
+ # @option args [String] :title title of slider
11
+ # @option args [String] :label label of slider
12
+ def initialize(args={})
13
+ @title = args[:title] || " "
14
+ @label = args[:label] || " "
15
+
16
+ @increment = 1
17
+ @range = [0, 100]
18
+ end
19
+
20
+ private
21
+
22
+ def _component
23
+ CDK::SLIDER.new(window.cdk_scr, # cdkscreen,
24
+ CDK::CENTER, CDK::CENTER, # xplace, yplace
25
+ @title, @label, '#'.ord, # title, label, filler,
26
+ window.cols-6, @range[0], @range[0], # field_width, start, low,
27
+ @range[1], @increment, @increment*2, # high, inc, fast_inc,
28
+ false, false) # box, shadow
29
+ end
30
+ end # VSlider
31
+ end # module Components
32
+ end # module RETerm
@@ -0,0 +1,55 @@
1
+ module RETerm
2
+ module Components
3
+ # Renders and image to the screen using drawille and chunkpng.
4
+ class Image < Component
5
+
6
+ # Initialize the Image component
7
+ #
8
+ # @param [Hash] args image params
9
+ # @option args [String] :file path to the file containing
10
+ # the image
11
+ def initialize(args={})
12
+ @file = args[:file]
13
+ end
14
+
15
+ def draw!
16
+ refresh_win
17
+ end
18
+
19
+ protected
20
+
21
+ def canvas
22
+ require 'drawille'
23
+ @canvas ||= Drawille::Canvas.new
24
+ end
25
+
26
+ def image
27
+ require 'chunky_png'
28
+ @image ||= ChunkyPNG::Image.from_file(@file)
29
+ end
30
+
31
+ def refresh_win
32
+ w = [image.dimension.width-1, window.cols].min
33
+ h = [image.dimension.height-1, window.rows].min
34
+
35
+ (0..w).each do |x|
36
+ (0..h).each do |y|
37
+ r = ChunkyPNG::Color.r(image[x,y])
38
+ g = ChunkyPNG::Color.g(image[x,y])
39
+ b = ChunkyPNG::Color.b(image[x,y])
40
+ canvas.set(x, y) if (r + b + g) > 100
41
+ end
42
+ end
43
+
44
+ y = 1
45
+ canvas.frame.split("\n").each { |line|
46
+ window.mvaddstr(y, 1, line)
47
+ y += 1
48
+ }
49
+
50
+ window.refresh
51
+ update_reterm
52
+ end
53
+ end # class Canvas
54
+ end # module Components
55
+ end # module RETerm
@@ -0,0 +1,20 @@
1
+ module RETerm
2
+ module Components
3
+ # Simply renders text to window
4
+ class Label < Component
5
+
6
+ # Initialize the Label component
7
+ #
8
+ # @param [Hash] args label params
9
+ # @option args [String] :text text of button
10
+ def initialize(args={})
11
+ @text = args[:text] || ""
12
+ end
13
+
14
+ def draw!
15
+ window.mvaddstr(1, 1, @text)
16
+ update_reterm
17
+ end
18
+ end # Label
19
+ end # module Components
20
+ end # module RETerm
@@ -0,0 +1,43 @@
1
+ module RETerm
2
+ module Components
3
+ # CDK Matrix Component
4
+ class Matrix < Component
5
+ include CDKComponent
6
+
7
+ # Initialize the Matrix component
8
+ #
9
+ # @param [Hash] args matrix params
10
+ def initialize(args={})
11
+ @rows = args[:rows]
12
+ @cols = args[:cols]
13
+ @title = args[:title]
14
+
15
+ @rowtitles = args[:rowtitles] || args[:row_titles] || Array.new(@rows) { "" }
16
+ @coltitles = args[:coltitles] || args[:col_titles] || Array.new(@cols+1) { "" }
17
+ @colwidths = args[:colwidths] || args[:col_widths] || Array.new(@cols+1) { 5 }
18
+ @coltypes = args[:coltypes] || args[:col_types] || Array.new(@cols+1) { :UMIXED }
19
+ end
20
+
21
+ def get(x, y)
22
+ component.getCell(x, y)
23
+ end
24
+
25
+ private
26
+
27
+ def _component
28
+ CDK::MATRIX.new(window.cdk_scr,
29
+ 2, 2, # xpos, ypos
30
+ @rows, @cols, # matrix rows, cols
31
+ [(window.rows - 2), @rows].min, # screen rows
32
+ [(window.cols - 2), @cols].min, # screen cols
33
+ @title, # title
34
+ @rowtitles, @coltitles, # row/col titles
35
+ @colwidths, @coltypes, # col widths and types
36
+ -1, -1, # row/col spacing
37
+ '.', # filler
38
+ 2, # dominant attribute
39
+ true, true, false) # box matrix, box cell, shadow
40
+ end
41
+ end # Matrix
42
+ end # module Components
43
+ end # module RETerm
@@ -0,0 +1,33 @@
1
+ module RETerm
2
+ module Components
3
+ # CDK Radio Component
4
+ class Radio < Component
5
+ include CDKComponent
6
+
7
+ # Initialize the Radio component
8
+ #
9
+ # @param [Hash] args radio params
10
+ # @option args [String] :title title of radio
11
+ # @option args [Array<String>] :items items to
12
+ # populate radio with
13
+ def initialize(args={})
14
+ @title = args[:title] || ""
15
+ @items = args[:items] || []
16
+ end
17
+
18
+ private
19
+
20
+ def _component
21
+ CDK::RADIO.new(window.cdk_scr, # cdkscreen,
22
+ 2, 1, CDK::RIGHT, # xplace, yplace, scroll pos
23
+ window.rows - 2, # widget height
24
+ window.cols - 2, # widget width
25
+ @title, @items, @items.size, # title and items
26
+ '#'.ord | Ncurses::A_REVERSE, # choice char
27
+ true, # default item
28
+ Ncurses::A_REVERSE, # highlight
29
+ true, false) # box, shadow
30
+ end
31
+ end # Radio
32
+ end # module Components
33
+ end # module RETerm
@@ -0,0 +1,71 @@
1
+ module RETerm
2
+ module Components
3
+ # Rocker component, allowing use to select one of several values
4
+ class Rocker < Component
5
+ include ComponentInput
6
+
7
+ attr_accessor :values, :index, :labels
8
+
9
+ # Initialize the Rocker component
10
+ #
11
+ # @param [Hash] args rocker params
12
+ #
13
+ # @example using the Rocker
14
+ # win = Window.new
15
+ # rocker = Rocker.new
16
+ # win.component = rocker
17
+ # rocker.values = ['Foo', 'Bar', 'Baz']
18
+ # val = rocker.activate!
19
+ #
20
+ def initialize(args={})
21
+ @values = []
22
+ @index = nil
23
+ @labels = true
24
+ @index = 0
25
+ end
26
+
27
+ def draw!
28
+ refresh_win
29
+ end
30
+
31
+ def activatable?
32
+ true
33
+ end
34
+
35
+ def activate!
36
+ refresh_win
37
+ handle_input
38
+ @values[@index]
39
+ end
40
+
41
+ private
42
+
43
+ def on_inc
44
+ @index += 1
45
+ @index = @values.size - 1 if @index == @values.size
46
+ refresh_win
47
+ end
48
+
49
+ def on_dec
50
+ @index -= 1
51
+ @index = 0 if @index < 0
52
+ refresh_win
53
+ end
54
+
55
+ def refresh_win
56
+ pre = post = ' '
57
+ pre = '-' if @labels
58
+ post = '+' if @labels
59
+
60
+ window.mvaddstr(1, 1, " |#{pre}|")
61
+ @values.each_with_index { |v, i|
62
+ sel = @index == i ? "#" : " "
63
+ window.mvaddstr(i+2, 1, " |" + sel + "|" + @values[i])
64
+ }
65
+ window.mvaddstr(@values.size+2, 1, " |#{post}|")
66
+ window.refresh
67
+ update_reterm
68
+ end
69
+ end # Rocker
70
+ end # module Components
71
+ end # module RETerm
@@ -0,0 +1,32 @@
1
+ module RETerm
2
+ module Components
3
+ # Scrolling List CDK Component
4
+ class SList < Component
5
+ include CDKComponent
6
+
7
+ # Initialize the SList component
8
+ #
9
+ # @param [Hash] args list params
10
+ # @option args [String] :title title of list
11
+ # @option args [Array<String>] :items items to
12
+ # populate list with
13
+ def initialize(args={})
14
+ @title = args[:title] || ""
15
+ @items = args[:items] || []
16
+ end
17
+
18
+ private
19
+
20
+ def _component
21
+ CDK::SCROLL.new(window.cdk_scr, # cdkscreen,
22
+ 2, 1, CDK::RIGHT, # xplace, yplace, scroll pos
23
+ window.rows - 2, # widget height
24
+ window.cols - 2, # widget width
25
+ @title, @items, @items.size, # title and items
26
+ false, # prefix numbers
27
+ Ncurses::A_REVERSE, # highlight
28
+ true, false) # box, shadow
29
+ end
30
+ end # SList
31
+ end # module Components
32
+ end # module RETerm
@@ -0,0 +1,23 @@
1
+ module RETerm
2
+ module Components
3
+ # Template which may be used as the basis for other components
4
+ class Template < Component
5
+ # All components must accept args hash (specified via loader)
6
+ def initialize(args={})
7
+ end
8
+
9
+ # Override this method to draw component on screen
10
+ def draw!
11
+ end
12
+
13
+ # Return true if the user should be able to focus and
14
+ # interact with this component, default to false
15
+ def activatable?
16
+ end
17
+
18
+ # Method call when this component is activated
19
+ def activate!
20
+ end
21
+ end # class Template
22
+ end # module Components
23
+ end # module RETerm
@@ -0,0 +1,61 @@
1
+ module RETerm
2
+ module Components
3
+ # Vertical Slider Component
4
+ class VSlider < Component
5
+ include ComponentInput
6
+
7
+ attr_accessor :initial_value, :increment, :range, :labels
8
+
9
+ # Initialize the slider component
10
+ #
11
+ # @param [Hash] args slider params
12
+ def initialize(args={})
13
+ @initial_value = 0
14
+ @increment = 0.01
15
+ @range = [0, 1]
16
+ @labels = true
17
+ @value = initial_value
18
+ end
19
+
20
+ def draw!
21
+ refresh_win
22
+ end
23
+
24
+ def activatable?
25
+ true
26
+ end
27
+
28
+ def activate!
29
+ refresh_win
30
+ handle_input
31
+ (range[1] - range[0]) * @value
32
+ end
33
+
34
+ private
35
+
36
+ def on_inc
37
+ @value += increment
38
+ @value = 1 if @value > 1
39
+ refresh_win
40
+ end
41
+
42
+ def on_dec
43
+ @value -= increment
44
+ @value = 0 if @value < 0
45
+ refresh_win
46
+ end
47
+
48
+ def refresh_win
49
+ 0.upto(window.rows) do |l|
50
+ pre = " "
51
+ pre = "+" if @labels && l == 0
52
+ pre = "-" if @labels && l == (window.rows-1)
53
+ fill = (l.to_f / window.rows) >= (1-@value)
54
+ window.mvaddstr(l, 0, pre + (fill ? "#" : " ") + "\n")
55
+ end
56
+
57
+ window.refresh
58
+ end
59
+ end # VSlider
60
+ end # module Components
61
+ end # module RETerm
@@ -0,0 +1,95 @@
1
+ require 'ncursesw'
2
+ require_relative './resize'
3
+
4
+ module RETerm
5
+ # Initializes the RETerm subsystem before invoking block.
6
+ # After block is finished regardless of execution state
7
+ # (return, exception, etc) this will cleanup the terminal
8
+ # environment before returning control to the TTY.
9
+ #
10
+ # This method is the first method the user should invoke
11
+ # after requiring the reterm library.
12
+ #
13
+ # @example
14
+ # init_reterm {
15
+ # win = Window.new :rows => 20, :cols => 40
16
+ # # ... more UI logic
17
+ # }
18
+ #
19
+ def init_reterm(opts={}, &bl)
20
+ begin
21
+ Terminal.load # XXX: not sure why but loading terminal
22
+ # info after changing terminal settings via
23
+ # ncurses seems to corrupt the terminal
24
+ # state to the point it cannot be restored
25
+ # without a 'reset' (see below).
26
+ # So just preload terminal info here.
27
+
28
+ stdscr = Ncurses::initscr
29
+ Ncurses::start_color
30
+ Ncurses::noecho
31
+ Ncurses::cbreak
32
+ Ncurses::curs_set(0)
33
+ Ncurses::keypad(stdscr, true)
34
+
35
+ track_resize if opts[:resize]
36
+
37
+ bl.call
38
+
39
+ #ensure
40
+ stop_track_resize
41
+ Ncurses.curs_set(1)
42
+ Window.all.each { |w| w.finalize! }
43
+ CDK::SCREEN.endCDK if cdk_enabled?
44
+ Ncurses.endwin()
45
+ #`reset -Q` # XXX only way to guarantee a full reset (see above)
46
+ end
47
+ end
48
+
49
+ # This method resyncs the visible terminal with the internal
50
+ # RETerm environment. It should be called any time the user
51
+ # needs to update the UI after making changes.
52
+ #
53
+ # @example
54
+ # init_reterm {
55
+ # win = Window.new
56
+ # win.border! # draw window border
57
+ # update_rti # resync terminal ouput
58
+ # win.getch # wait for input
59
+ # }
60
+ #
61
+ def update_reterm
62
+ Window.top.each { |w| w.refresh }
63
+ Ncurses::Panel.update_panels
64
+ Ncurses.doupdate
65
+ end
66
+
67
+ # XXX Ncurses is exposed so that users
68
+ # may employ any constants if desired.
69
+ # This should not be needed though and
70
+ # is discouraged to maintain portability
71
+ NC = Ncurses
72
+
73
+ # Enable the CDK subsystem. Used by CDKbased components
74
+ #
75
+ # @see #cdk_enabled?
76
+ def enable_cdk!
77
+ return if @cdk_enabled
78
+
79
+ @cdk_enabled = true
80
+ require 'cdk'
81
+
82
+ # XXX defines standard color pairs, but we use our own
83
+ # for standarization across components, but we need
84
+ # to set cdk components to the correct color scheme
85
+ # manually
86
+ # CDK::Draw.initCDKColor
87
+ end
88
+
89
+ # Return boolean indicating if the CDK subsystem is enabled.
90
+ # CDK is a library used by various components providing
91
+ # many various ready to use ncurses widgets.
92
+ def cdk_enabled?
93
+ !!@cdk_enabled
94
+ end
95
+ end # module RETerm