reterm 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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