rutui 0.3.1 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rutui.rb ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # https://github.com/b1nary/rutui
5
+ #
6
+ # Author: Roman Pramberger (roman@pramberger.ch)
7
+ # License: MIT
8
+ #
9
+ require 'rutui/util'
10
+ require 'rutui/pixel'
11
+ require 'rutui/theme'
12
+ require 'rutui/objects'
13
+ require 'rutui/screen'
14
+ require 'rutui/screenmanager'
15
+ require 'rutui/figlet'
16
+ require 'rutui/axx'
17
+ require 'rutui/sprites'
18
+ require 'rutui/table'
19
+ require 'rutui/textfield'
20
+
21
+ module RuTui
22
+ Ansi = ::Ansi
23
+ Utils = ::Utils
24
+ Pixel = ::Pixel
25
+ Theme = ::Theme
26
+ BaseObject = ::BaseObject
27
+ Box = ::Box
28
+ Line = ::Line
29
+ Circle = ::Circle
30
+ Text = ::Text
31
+ Screen = ::Screen
32
+ ScreenManager = ::ScreenManager
33
+ Figlet = ::Figlet
34
+ Axx = ::Axx
35
+ Sprite = ::Sprite
36
+ Table = ::Table
37
+ Textfield = ::Textfield
38
+ end
data/lib/rutui/axx.rb ADDED
@@ -0,0 +1,86 @@
1
+ ## Basic Ascii Image format Axx
2
+ # First implemented: here :3
3
+ #
4
+ # Example:
5
+ # # Comments ...
6
+ # nil|A:1:0|A|A:2
7
+ #
8
+ # nil empty pixel
9
+ # A:1:0 Char is A, 1 is foreground, 0 is background
10
+ # A Char only (colors default)
11
+ # A:2 Char A, Foreground 2, Background default
12
+ #
13
+ class Axx < BaseObject
14
+ def initialize options
15
+ @file = options[:file]
16
+ @x = options[:x]
17
+ @y = options[:y]
18
+
19
+ return if @file.nil?
20
+ return if !File.exists? @file
21
+
22
+ @img = File.open(@file).read
23
+
24
+ parse
25
+ end
26
+
27
+ def parse
28
+ out = []
29
+ @img.split("\n").each_with_index do |line,li|
30
+ if !line.match(/^#/)
31
+ out[li] = []
32
+ line.split("|").each_with_index do |elem,ei|
33
+ ele = elem.split(":")
34
+ if ele.size == 3
35
+ out[li][ei] = Pixel.new(ele[1].to_i,ele[2].to_i,ele[0])
36
+ elsif ele.size == 2
37
+ out[li][ei] = Pixel.new(ele[1].to_i,nil,ele[0])
38
+ else
39
+ if ele[0] == "nil"
40
+ out[li][ei] = nil
41
+ else
42
+ out[li][ei] = Pixel.new(nil,nil,ele[0])
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ out.each do |o|
50
+ out.delete(o) if o.nil?
51
+ end
52
+ @obj = out
53
+ @height = out.size
54
+ @width = out.size
55
+ end
56
+
57
+ def self.parse data
58
+ out = []
59
+ data.split("\n").each_with_index do |line,li|
60
+ if !line.match(/^#/)
61
+ out[li] = []
62
+ line.split("|").each_with_index do |elem,ei|
63
+ ele = elem.split(":")
64
+ if ele.size == 3
65
+ out[li][ei] = Pixel.new(ele[1].to_i,ele[2].to_i,ele[0])
66
+ elsif ele.size == 2
67
+ out[li][ei] = Pixel.new(ele[1].to_i,nil,ele[0])
68
+ else
69
+ if ele[0] == "nil"
70
+ out[li][ei] = nil
71
+ else
72
+ out[li][ei] = Pixel.new(nil,nil,ele[0])
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ out.each do |o|
80
+ out.delete(o) if o.nil? or o == []
81
+ end
82
+ return out
83
+ end
84
+
85
+ end
86
+
@@ -0,0 +1,158 @@
1
+ # encoding: UTF-8
2
+ ## Figlet Class
3
+ # parse Figlet Font files
4
+ #
5
+ # Attributes (All accessable):
6
+ # :x MUST
7
+ # :y MUST
8
+ # :text Your text
9
+ # :font Use a loaded font file
10
+ # :rainbow true|any
11
+ # :colors Array of example pixels used for colors
12
+ #
13
+ #
14
+ # Example:
15
+ # Figlet.add :test, "path/to/font.flf"
16
+ # Figlet.new({ :text => "Meh", :font => :test, :rainbow => true })
17
+ #
18
+ # Config content (just to remember what the figlet slug means)
19
+ # 0 - name
20
+ # 1 - height of a character
21
+ # 2 - height of a character, not including descenders
22
+ # 3 - max line length (excluding comment lines) + a fudge factor
23
+ # 4 - default smushmode for this font (like "-m 0" on command line)
24
+ # 5 - number of comment lines
25
+ # 6 - rtol
26
+ #
27
+ class Figlet < BaseObject
28
+ attr_accessor :text, :rainbow, :font, :colors
29
+ # Figlet font: '!" #$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz[|]~ÄÖÜäöüß'
30
+ @@chars = '!!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz[|]~ÄÖÜäöüß'.split("")
31
+ @@rainbow = nil
32
+ @@fonts = {}
33
+
34
+ # Initialize (see above)
35
+ def initialize options
36
+ @x = options[:x]
37
+ @y = options[:y]
38
+
39
+ @@rainbow = Theme.get(:rainbow) if @@rainbow.nil?
40
+
41
+ return if @x.nil? or @y.nil?
42
+
43
+ @font = options[:font]
44
+ @text = options[:text]
45
+ @rainbow = options[:rainbow]
46
+ @space = options[:space]
47
+ @space = 0 if @space.nil?
48
+ @colors = options[:colors]
49
+ @colors = [Pixel.new(Theme.get(:textcolor), Theme.get(:background).bg, Theme.get(:background).symbol)] if @colors.nil?
50
+
51
+ create
52
+ end
53
+
54
+ # Create Figlet text object
55
+ # Recall it any time when attributes have changed
56
+ def create
57
+ obj = []
58
+ @@fonts[@font]['n'].size.times do
59
+ obj << []
60
+ end
61
+ current = 0
62
+
63
+ count = 0
64
+ @text.each_byte do |c|
65
+ if @@chars.include? c.chr
66
+ @@fonts[@font][c.chr].each_with_index do |fr,ri|
67
+ fr.each do |fc|
68
+ if @rainbow
69
+ obj[ri] << Pixel.new(@@rainbow[current], @colors[0].bg,fc)
70
+ else
71
+ obj[ri] << Pixel.new(@colors[current].fg,@colors[current].bg,fc)
72
+ end
73
+
74
+ if @rainbow != true
75
+ current += 1 if @colors.size > 1
76
+ current = 0 if current > @colors.size
77
+ end
78
+ end
79
+ end
80
+
81
+ if @rainbow
82
+ current += 1
83
+ current = 0 if current >= @@rainbow.size
84
+ end
85
+
86
+ if count < @text.size-1
87
+ @@fonts[@font]['n'].size.times do |ri|
88
+ @space.times do
89
+ if @rainbow
90
+ obj[ri] << Pixel.new(@@rainbow[current], @colors[0].bg,Theme.get(:background).symbol)
91
+ else
92
+ obj[ri] << Pixel.new(@colors[current].fg,@colors[current].bg,Theme.get(:background).symbol)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ # SPace
98
+ else
99
+ @@fonts[@font]['n'].size.times do |ri|
100
+ 3.times do
101
+ if @rainbow
102
+ obj[ri] << Pixel.new(@@rainbow[current], @colors[0].bg, Theme.get(:background).symbol)
103
+ else
104
+ obj[ri] << Pixel.new(@colors[current].fg,@colors[current].bg, Theme.get(:background).symbol)
105
+ end
106
+ end
107
+ end
108
+ end
109
+ count += 1
110
+ end
111
+ @obj = obj
112
+ end
113
+
114
+ # Static methods to add/load new Fonts
115
+ def self.add name, file
116
+ if File.exists?(file)
117
+
118
+ data = File.new(file, "r").read.split("\n")
119
+ config = data[0].split(" ")
120
+
121
+ # Remove Comments (Size is in info line)
122
+ config[5].to_i.times do
123
+ data.delete_at(0)
124
+ end
125
+
126
+ # Remove empty line if exist
127
+ data.delete_at(0) if data[0].strip() == ""
128
+
129
+ height = config[2].to_i
130
+ rest = config[1].to_i - height
131
+
132
+ @@fonts[name] = {}
133
+
134
+ @@chars.each do |i|
135
+ out = []
136
+
137
+ (data.delete_at(0); rest -= 1) if data.size > 0 and data[0].gsub('$@','').gsub(' ','') == ''
138
+
139
+ height.times do |x|
140
+ break if data.size < 1
141
+ xdata = data[0].gsub("$"," ").gsub("@","").gsub("\r","").split("")
142
+ out << xdata if xdata.size > 0
143
+ data.delete_at(0)
144
+ end
145
+
146
+ rest.times do
147
+ data.delete_at(0)
148
+ end
149
+
150
+ @@fonts[name][i] = out
151
+ end
152
+ return true
153
+ else
154
+ return false
155
+ end
156
+ end
157
+ end
158
+
@@ -0,0 +1,285 @@
1
+ # This class contains different Objects
2
+
3
+ ## Base Object Class
4
+ # Dynamic Objects that get drawn on the Screen
5
+ # This class is used as basic class for other objects
6
+ #
7
+ class BaseObject
8
+ attr_accessor :x, :y, :width, :height, :obj
9
+ # Ex.: BaseObject.new({ :x => 1, :y => 20, :obj => [[Pixel.new(1),Pixel.new(2,4,"#")]] })
10
+ def initialize options
11
+ @obj = options[:obj]
12
+ @obj = Array.new(height){ Array.new(width) } if @obj.nil?
13
+
14
+ @x = options[:x]
15
+ @y = options[:y]
16
+ @x = 1 if @x.nil?
17
+ @y = 1 if @y.nil?
18
+
19
+ @height = @obj.size
20
+ @width = @obj[0].size
21
+ end
22
+
23
+ # Move object X and Y (modifiers like: -2, 2)
24
+ def move x, y; @x += x; @y += y; end
25
+ # Set object position X Y
26
+ def set_position x, y; @x = x; @y = y; end
27
+ # Set pixel on position on object
28
+ def set_pixel x, y, pixel
29
+ @obj[x][y] = pixel if !@obj[x].nil? and !@obj[x][y].nil?
30
+ end
31
+ # Get pixel by position
32
+ def get_pixel x, y
33
+ @obj[x][y] if !@obj[x].nil? and !@obj[x][y].nil?
34
+ end
35
+
36
+ # "special" each methods for objects
37
+ def each
38
+ @obj.each_with_index do |row,row_count|
39
+ row.each_with_index do |pixel,col_count|
40
+ yield row_count, col_count, pixel
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ ## Box Class
47
+ # draw a box with borders
48
+ #
49
+ # Attributes (all accessible):
50
+ # :width * Box width
51
+ # :height * Box height
52
+ # :x * Box X MUST
53
+ # :y * Box Y MUST
54
+ # :horizontal Horizontal Pixel
55
+ # :vertical Vertical Pixel
56
+ # :corner Corner Pixel
57
+ # :fill Between the border lines (Color)
58
+ #
59
+ # Example:
60
+ # Box.new({ :x => 1, :y => 42, :width => 10, :height => 5, :corner => Pixel.new(1,2,"#"), :fill => Pixel.new(4,6,":") })
61
+ #
62
+ class Box < BaseObject
63
+ attr_accessor :fill, :width, :height, :vertical, :horizontal, :corner
64
+
65
+ # initialize object (see above)
66
+ def initialize options
67
+ @x = options[:x]
68
+ @y = options[:y]
69
+ @width = options[:width]
70
+ @height = options[:height]
71
+
72
+ return if @x.nil? or @y.nil? or @width.nil? or @height.nil?
73
+
74
+ @fill = options[:fill]
75
+
76
+ @vertical = options[:vertical]
77
+ @horizontal = options[:horizontal]
78
+ @corner = options[:corner]
79
+ ref = Theme.get(:border)
80
+ @horizontal = Pixel.new(ref.fg,ref.bg,"-") if options[:horizontal].nil?
81
+ @vertical = Pixel.new(ref.fg,ref.bg,"|") if options[:vertical].nil?
82
+ @corner = Pixel.new(ref.fg,ref.bg,"*") if options[:corner].nil?
83
+
84
+ @width = 3 if @width < 3
85
+ @height = 3 if @height < 3
86
+
87
+ create
88
+ end
89
+
90
+ # Create Box
91
+ # can be recalled any time on attribute changes
92
+ def create
93
+ if !@fill.nil?
94
+ backpixel = Pixel.new(@fill.fg,@fill.bg,@fill.symbol)
95
+ obj = Array.new(@height){ Array.new(@width) { backpixel } }
96
+ else
97
+ obj = Array.new(@height){ Array.new(@width) }
98
+ end
99
+
100
+ (@width-2).times do |i|
101
+ obj[0][i+1] = @horizontal
102
+ obj[@height-1][i+1] = @horizontal
103
+ end
104
+
105
+ (@height-2).times do |i|
106
+ obj[i+1][0] = @vertical
107
+ obj[i+1][@width-1] = @vertical
108
+ end
109
+
110
+ obj[0][0] = @corner
111
+ obj[0][@width-1] = @corner
112
+ obj[@height-1][0] = @corner
113
+ obj[@height-1][@width-1] = @corner
114
+
115
+ @height = obj.size
116
+ @width = obj[0].size
117
+ @obj = obj
118
+ end
119
+ end
120
+
121
+
122
+ ## Line Class
123
+ # draw a straight line
124
+ #
125
+ # Attributes (all accessible)
126
+ # :x MUST
127
+ # :y MUST
128
+ # :direction :vertical|:horizontal (Default: :horizontal)
129
+ # :length
130
+ # :pixel
131
+ # :endpixel
132
+ #
133
+ class Line < BaseObject
134
+ attr_accessor :length, :pixel, :endpixel, :direction
135
+
136
+ def initialize options
137
+ @x = options[:x]
138
+ @y = options[:y]
139
+ @length = options[:length]
140
+ @direction = options[:direction]
141
+ @direction = :horizontal if @direction.nil?
142
+
143
+ return if @x.nil? or @y.nil? or @width.nil?
144
+ @pixel = options[:pixel]
145
+ @endpixel = options[:endpixel]
146
+
147
+ @pixel = Theme.get(:border) if @pixel.nil?
148
+
149
+ create
150
+ end
151
+
152
+ # Create Line
153
+ # can be recalled any time on attribute changes
154
+ def create
155
+ if @direction == :horizontal
156
+ @obj = [Array.new(@length){ @pixel }]
157
+ else
158
+ @obj = Array.new(@length){ [@pixel] }
159
+ end
160
+ if !@endpixel.nil?
161
+ @obj[0][0] = @endpixel
162
+ @obj[0][@length-1] = @endpixel
163
+ end
164
+ end
165
+ end
166
+
167
+ ## Circle Class
168
+ # draw a circle
169
+ #
170
+ # thx to: http://rubyquiz.strd6.com/quizzes/166-circle-drawing
171
+ #
172
+ # Attributes (all accessible):
173
+ # :x MUST
174
+ # :y MUST
175
+ # :radius - Circle radius
176
+ # :pixel - Circle Pixel
177
+ # :fill - Actually just fills the box not the circle...
178
+ #
179
+ class Circle < BaseObject
180
+ attr_accessor :radius, :pixel, :fill
181
+ # Initialize circle (see above)
182
+ def initialize options
183
+ @x = options[:x]
184
+ @y = options[:y]
185
+ @radius = options[:radius]
186
+ @pixel = options[:pixel]
187
+ @fill = options[:fill_pixel]
188
+
189
+ @pixel = Theme.get(:border) if @pixel.nil?
190
+
191
+ return if @x.nil? or @y.nil? or @radius.nil?
192
+
193
+ @width = options[:radius]*2 # needed?
194
+ @height = @width # needed?
195
+
196
+ create
197
+ end
198
+
199
+ # Create Circle
200
+ # can be recalled any time on attribute changes
201
+ def create
202
+ obj = []
203
+ (0..(@radius*2)).each do |x|
204
+ (0..(@radius*2)).each do |y|
205
+ obj[y] = [] if obj[y].nil?
206
+ obj[y][x] = distance_from_center(x,y).round == @radius ? @pixel : @fill
207
+ end
208
+ end
209
+ @obj = obj
210
+ end
211
+
212
+ private
213
+ def distance_from_center(x,y)
214
+ a = calc_side(x)
215
+ b = calc_side(y)
216
+ return Math.sqrt(a**2 + b**2)
217
+ end
218
+
219
+ def calc_side(z)
220
+ z < @radius ? (@radius - z) : (z - @radius)
221
+ end
222
+
223
+ end
224
+
225
+ ## Text Object Class
226
+ # Creates an Text element
227
+ #
228
+ # Attributes (all accessible):
229
+ # :x MUST
230
+ # :y MUST
231
+ # :text - the text to draw
232
+ # :background - Background color (0-255)
233
+ # :foreground - Foreground color (0-255)
234
+ # :rainbow - true|false|none Rainbow text
235
+ #
236
+ class Text < BaseObject
237
+ attr_accessor :bg, :fg, :text, :do_rainbow
238
+ @@rainbow = nil
239
+
240
+ def initialize options
241
+ @@rainbow = Theme.get(:rainbow) if @@rainbow.nil?
242
+ @do_rainbow = options[:rainbow]
243
+ @text = options[:text]
244
+ @x = options[:x]
245
+ @y = options[:y]
246
+ @bg = options[:background]
247
+ @fg = options[:foreground]
248
+ @bg = Theme.get(:background).bg if @bg.nil?
249
+ @fg = Theme.get(:textcolor) if @fg.nil?
250
+ return if @x.nil? or @y.nil?
251
+
252
+ @height = 1
253
+ create
254
+ end
255
+
256
+ # Create Text
257
+ # can be recalled any time on attribute changes
258
+ def create
259
+ if @do_rainbow
260
+ rainbow = 0
261
+ end
262
+ @width = @text.size
263
+ @obj = []
264
+ tmp = []
265
+ @text.split("").each do |t|
266
+ if @do_rainbow
267
+ tmp << Pixel.new(@@rainbow[rainbow],@bg,t)
268
+ rainbow += 1
269
+ rainbow = 0 if rainbow >= @@rainbow.size
270
+ else
271
+ tmp << Pixel.new(@fg,@bg,t)
272
+ end
273
+ end
274
+ @obj << tmp
275
+ end
276
+
277
+ def set_text text
278
+ @text = text
279
+ create
280
+ end
281
+
282
+ def get_text
283
+ @text
284
+ end
285
+ end