rutui 0.3.1 → 0.4
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.
- data/lib/rutui.rb +38 -0
- data/lib/rutui/axx.rb +86 -0
- data/lib/rutui/figlet.rb +158 -0
- data/lib/rutui/objects.rb +285 -0
- data/lib/rutui/pixel.rb +22 -0
- data/lib/rutui/screen.rb +107 -0
- data/lib/rutui/screenmanager.rb +76 -0
- data/lib/rutui/sprites.rb +64 -0
- data/lib/rutui/table.rb +209 -0
- data/lib/rutui/textfield.rb +112 -0
- data/lib/rutui/theme.rb +55 -0
- data/lib/rutui/util.rb +78 -0
- metadata +15 -5
- data/rutui.rb +0 -684
data/lib/rutui/pixel.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
## Pixel Class
|
2
|
+
# Each pixel consinsts of foreground, background and
|
3
|
+
# a symbol. What it is, is self explainaring
|
4
|
+
#
|
5
|
+
# Colors can be numbers between 0 and 255
|
6
|
+
# (dunno how windows or OSX handles colors over 16)
|
7
|
+
#
|
8
|
+
# The Symbol may eats every in Ruby working Ascii Symbol
|
9
|
+
#
|
10
|
+
class Pixel
|
11
|
+
attr_accessor :fg, :bg, :symbol
|
12
|
+
|
13
|
+
def initialize foreground = 15, background = nil, symbol = " "
|
14
|
+
@fg = foreground
|
15
|
+
@bg = background
|
16
|
+
@symbol = symbol
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.random sym = "#"
|
20
|
+
Pixel.new(rand(255),rand(255),sym)
|
21
|
+
end
|
22
|
+
end
|
data/lib/rutui/screen.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# This File contains the Screen Class
|
2
|
+
|
3
|
+
## Screen Class
|
4
|
+
# The Screen is the root element of your app.
|
5
|
+
# Its basicly a map containing you screens pixels
|
6
|
+
#
|
7
|
+
class Screen
|
8
|
+
# Initialize me with a default pixel, if you want
|
9
|
+
def initialize default_pixel = Theme.get(:background)
|
10
|
+
size = Utils.winsize
|
11
|
+
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
12
|
+
@map = @smap.dup
|
13
|
+
@default = default_pixel
|
14
|
+
@objects = []
|
15
|
+
@statics = []
|
16
|
+
# Set as default if first screen
|
17
|
+
ScreenManager.add :default, self if ScreenManager.size == 0
|
18
|
+
end
|
19
|
+
|
20
|
+
# regen screen (size change?)
|
21
|
+
def rescreen
|
22
|
+
size = Utils.winsize
|
23
|
+
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
24
|
+
|
25
|
+
@statics.each do |s|
|
26
|
+
self.add_static s
|
27
|
+
end
|
28
|
+
|
29
|
+
@map = @smap.dup
|
30
|
+
end
|
31
|
+
|
32
|
+
# Set default/background pixel
|
33
|
+
# Ex.: screen.set_default Pixel.new(244,1,";")
|
34
|
+
def set_default pixel
|
35
|
+
@default = pixel
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Get default/background pixel
|
40
|
+
def get_default
|
41
|
+
@default
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# add object that doesnt change over time
|
46
|
+
def add_static object
|
47
|
+
@statics << object if !@statics.include? object
|
48
|
+
object.each do |ri,ci,pixel|
|
49
|
+
@smap[object.y+ri][object.x+ci] = pixel if !pixel.nil? and object.y+ri > 0 and object.y+ci > 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# add dynamic object
|
55
|
+
def add object
|
56
|
+
@objects << object
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# remove object
|
61
|
+
def delete object
|
62
|
+
@objects.delete(object)
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# draw the pixel-screen map
|
67
|
+
def draw
|
68
|
+
lastpixel = Pixel.new(rand(255), rand(255), ".")
|
69
|
+
@map = Marshal.load( Marshal.dump( @smap )) # Deep copy
|
70
|
+
|
71
|
+
# get all the objects
|
72
|
+
@objects.each do |o|
|
73
|
+
next if o.x.nil? or o.y.nil?
|
74
|
+
o.each do |ri,ci,pixel|
|
75
|
+
@map[o.y + ri][o.x + ci] = pixel if !pixel.nil? and o.y+ri > 0 and o.x+ci > 0 and o.y+ri < @map.size and o.x+ci < @map[0].size
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
out = "" # Color.go_home
|
80
|
+
# an DRAW!
|
81
|
+
@map.each do |line|
|
82
|
+
line.each do |pixel|
|
83
|
+
if pixel != lastpixel
|
84
|
+
out += Ansi.clear_color if lastpixel != 0
|
85
|
+
if pixel.nil?
|
86
|
+
lastpixel = pixel
|
87
|
+
out += "#{Ansi.bg(@default.bg)}#{Ansi.fg(@default.fg)}#{@default.symbol}"
|
88
|
+
else
|
89
|
+
lastpixel = pixel
|
90
|
+
out += "#{Ansi.bg(pixel.bg)}#{Ansi.fg(pixel.fg)}#{pixel.symbol}"
|
91
|
+
end
|
92
|
+
else
|
93
|
+
if pixel.nil?
|
94
|
+
out += @default.symbol
|
95
|
+
else
|
96
|
+
out += pixel.symbol
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# draw out
|
103
|
+
print out
|
104
|
+
$stdout.flush
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# This file contains the ScreenManager
|
2
|
+
|
3
|
+
## Screen Manager Class
|
4
|
+
# Static class to handle screens
|
5
|
+
#
|
6
|
+
class ScreenManager
|
7
|
+
@@screens = {}
|
8
|
+
@@current = :default
|
9
|
+
|
10
|
+
# Set a screen
|
11
|
+
# Ex.: ScreenManager.set :default, Screen.new
|
12
|
+
def self.add name, screen
|
13
|
+
@@screens[name] = screen
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get count of existing screens
|
17
|
+
def self.size
|
18
|
+
@@screens.size
|
19
|
+
end
|
20
|
+
|
21
|
+
# Delete screen by name
|
22
|
+
def self.delete name
|
23
|
+
@@screens.delete(name) if !@@screens[name].nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Set current screen
|
27
|
+
def self.set_current name
|
28
|
+
@@current = name
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get current screen
|
32
|
+
def self.get_current
|
33
|
+
# Fix size and others of screen here
|
34
|
+
@@current
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get the complete screen by name
|
38
|
+
def self.get_screen name
|
39
|
+
@@screens[name]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Refit screen size
|
43
|
+
def self.refit
|
44
|
+
size = Utils.winsize
|
45
|
+
if @autofit and size != @lastsize
|
46
|
+
@@screens[@@current].rescreen
|
47
|
+
@lastsize = size
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# draw current screen
|
52
|
+
def self.draw
|
53
|
+
print Ansi.go_home
|
54
|
+
@@screens[@@current].draw
|
55
|
+
end
|
56
|
+
|
57
|
+
# Raw Game Loop
|
58
|
+
# Ex.: ScreenManager.loop({ :autodraw => true, :autofit => true }){ |key| p key }
|
59
|
+
def self.loop options
|
60
|
+
autodraw = options[:autodraw]
|
61
|
+
@autofit = options[:autofit]
|
62
|
+
@autofit = true if @autofit.nil?
|
63
|
+
@lastsize = nil
|
64
|
+
print Ansi.clear
|
65
|
+
print Ansi.set_start
|
66
|
+
Utils.init
|
67
|
+
ScreenManager.draw
|
68
|
+
|
69
|
+
while true
|
70
|
+
key = Utils.gets
|
71
|
+
yield key
|
72
|
+
ScreenManager.refit if @autofit
|
73
|
+
ScreenManager.draw if autodraw
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Sprite < BaseObject
|
2
|
+
attr_accessor :tick, :current, :sprites, :ticks, :object
|
3
|
+
@@spr = []
|
4
|
+
|
5
|
+
def initialize options
|
6
|
+
@x = options[:x]
|
7
|
+
@y = options[:y]
|
8
|
+
@x = 0 if @x.nil?
|
9
|
+
@y = 0 if @y.nil?
|
10
|
+
|
11
|
+
@tick = 0
|
12
|
+
@object = options[:obj]
|
13
|
+
@file = options[:file]
|
14
|
+
@current = nil
|
15
|
+
|
16
|
+
@@spr << self
|
17
|
+
|
18
|
+
@sprites = {}
|
19
|
+
|
20
|
+
create_from_file if !@file.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_from_file
|
24
|
+
if File.exists? @file
|
25
|
+
data = File.open(@file).read
|
26
|
+
# AXX Format
|
27
|
+
if data.include? '---' and data.include? '| :'
|
28
|
+
out = []
|
29
|
+
data = data.split("---")
|
30
|
+
while data.size > 0
|
31
|
+
while data[0].match(/^#/)
|
32
|
+
data.shift
|
33
|
+
end
|
34
|
+
name = data.shift
|
35
|
+
content = data.shift
|
36
|
+
@sprites[name] = [] if @sprites[name].nil?
|
37
|
+
@sprites[name] << Axx.parse(content)
|
38
|
+
@current = name if @current.nil? # first sprite gets default
|
39
|
+
@obj = @sprites[@current][0]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# set current animation
|
46
|
+
def set_current name
|
47
|
+
@current = name
|
48
|
+
@obj = @sprites[@current][0]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Add sprite
|
52
|
+
def add name, images
|
53
|
+
@current = name if @current.nil? # first sprite gets default
|
54
|
+
@sprites[name] = images
|
55
|
+
end
|
56
|
+
|
57
|
+
# Update ticker
|
58
|
+
def update
|
59
|
+
@tick += 1
|
60
|
+
@tick = 0 if @tick >= ( @sprites[@current].size )
|
61
|
+
@obj = @sprites[@current][@tick]
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
data/lib/rutui/table.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
## Table Object Class
|
2
|
+
# Creates an Table element
|
3
|
+
#
|
4
|
+
# Attributes (all accessible):
|
5
|
+
# :x MUST
|
6
|
+
# :y MUST
|
7
|
+
# :table - the tabular data in an array (like: [[1,"A"], [2, "B"]])
|
8
|
+
# :background - Background color (0-255)
|
9
|
+
# :foreground - Foreground color (0-255)
|
10
|
+
# :hover - Hover color (0-255)
|
11
|
+
# :ascii - Draw ASCII decoration
|
12
|
+
# :highlight - To highlight line
|
13
|
+
# :highlight_direction - Highlight direction
|
14
|
+
# :cols - Header and meta definitions (see example)
|
15
|
+
# :pixel - Default pixel (colors) for border
|
16
|
+
#
|
17
|
+
class Table < BaseObject
|
18
|
+
attr_accessor :table, :ascii, :highlight, :highlight_direction, :cols
|
19
|
+
|
20
|
+
def initialize options
|
21
|
+
@bg = options[:background]
|
22
|
+
@hover = options[:hover]
|
23
|
+
@fg = options[:foreground]
|
24
|
+
@bg = Theme.get(:background).bg if @bg.nil?
|
25
|
+
@fg = Theme.get(:textcolor) if @fg.nil?
|
26
|
+
@bg2 = @bg if @bg2.nil?
|
27
|
+
@ascii = options[:ascii]
|
28
|
+
@ascii = true if @ascii.nil?
|
29
|
+
|
30
|
+
@pixel = options[:pixel]
|
31
|
+
@pixel = Theme.get(:border) if @pixel.nil?
|
32
|
+
|
33
|
+
@table = options[:table]
|
34
|
+
@table = [] if @table.nil?
|
35
|
+
|
36
|
+
@cols = options[:cols]
|
37
|
+
@cols = [] if @cols.nil?
|
38
|
+
|
39
|
+
@highlight = options[:highlight]
|
40
|
+
@highlight = 0 if @highlight.nil?
|
41
|
+
|
42
|
+
@highlight_direction = options[:highlight_direction]
|
43
|
+
@highlight_direction = :horizontal if @highlight_direction.nil?
|
44
|
+
|
45
|
+
@x = options[:x]
|
46
|
+
@x = 1 if @x.nil?
|
47
|
+
@y = options[:y]
|
48
|
+
@y = 1 if @y.nil?
|
49
|
+
|
50
|
+
@reverse = false
|
51
|
+
@header = false
|
52
|
+
@header = true if options[:header] == true
|
53
|
+
|
54
|
+
@meta = { :height => @table.size, :cols => 0 }
|
55
|
+
index_col_widths
|
56
|
+
|
57
|
+
create
|
58
|
+
|
59
|
+
@height = @table.size
|
60
|
+
#@height += 2 if @ascii
|
61
|
+
@width = @table[0].size
|
62
|
+
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Set data
|
68
|
+
def set_table table
|
69
|
+
@table = table
|
70
|
+
index_col_widths
|
71
|
+
create
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Add line to table
|
76
|
+
def add line
|
77
|
+
@table << line
|
78
|
+
@height += 1
|
79
|
+
index_col_widths
|
80
|
+
create
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Delete line from table by index
|
85
|
+
def delete line_id
|
86
|
+
if !@table[line_id].nil?
|
87
|
+
@table.delete_at(line_id)
|
88
|
+
@height -= 1
|
89
|
+
index_col_widths
|
90
|
+
create
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# highlight line
|
96
|
+
def highlight line_id
|
97
|
+
return highlight if line_id.nil?
|
98
|
+
@highlight = line_id
|
99
|
+
@reverse = false
|
100
|
+
create
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# create or recreate the table object
|
105
|
+
def create
|
106
|
+
obj = []
|
107
|
+
if @header
|
108
|
+
obj << ascii_table_line if @ascii
|
109
|
+
_obj = []
|
110
|
+
_obj << Pixel.new(@pixel.fg,@bg,"|") if @ascii
|
111
|
+
@cols.each_with_index do |col, index|
|
112
|
+
fg = @pixel.fg
|
113
|
+
fg = @cols[index][:title_color] if !@cols[index].nil? and !@cols[index][:title_color].nil?
|
114
|
+
chars = "".to_s.split("")
|
115
|
+
chars = " #{ col[:title] }".to_s.split("") if !col.nil? and !col[:title].nil?
|
116
|
+
chars.each_with_index do |e, char_count|
|
117
|
+
_obj << Pixel.new(fg,@bg,e)
|
118
|
+
end
|
119
|
+
(@meta[:max_widths][index]-chars.size+2).times do |i|
|
120
|
+
_obj << Pixel.new(@pixel.fg,@bg," ")
|
121
|
+
end
|
122
|
+
_obj << Pixel.new(@pixel.fg,@bg,"|") if @ascii
|
123
|
+
end
|
124
|
+
obj << _obj
|
125
|
+
end
|
126
|
+
obj << ascii_table_line if @ascii
|
127
|
+
@table.each_with_index do |line, lindex|
|
128
|
+
bg = @bg
|
129
|
+
bg = @hover if lindex == @highlight and @highlight_direction == :horizontal
|
130
|
+
_obj = []
|
131
|
+
_obj << Pixel.new(@pixel.fg,bg,"|") if @ascii
|
132
|
+
line.each_with_index do |col, index|
|
133
|
+
fg = @fg
|
134
|
+
fg = @cols[index][:color] if !@cols[index].nil? and !@cols[index][:color].nil?
|
135
|
+
|
136
|
+
if @highlight_direction == :vertical
|
137
|
+
if index == @highlight
|
138
|
+
bg = @hover
|
139
|
+
else
|
140
|
+
bg = @bg
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
chars = col.to_s.split("")
|
146
|
+
_obj << Pixel.new(@pixel.fg,bg," ")
|
147
|
+
max_chars = nil
|
148
|
+
max_chars = @cols[index][:max_length]+1 if !@cols[index].nil? and !@cols[index][:max_length].nil?
|
149
|
+
max_chars = @cols[index][:length]+1 if !@cols[index].nil? and !@cols[index][:length].nil?
|
150
|
+
chars.each_with_index do |e, char_count|
|
151
|
+
break if !max_chars.nil? and char_count >= max_chars
|
152
|
+
_obj << Pixel.new(fg,bg,e)
|
153
|
+
end
|
154
|
+
(@meta[:max_widths][index]-chars.size+1).times do |i|
|
155
|
+
_obj << Pixel.new(@pixel.fg,bg," ")
|
156
|
+
end
|
157
|
+
|
158
|
+
bg = @bg if @highlight_direction == :vertical
|
159
|
+
_obj << Pixel.new(@pixel.fg,bg,"|") if @ascii
|
160
|
+
end
|
161
|
+
obj << _obj
|
162
|
+
end
|
163
|
+
obj << ascii_table_line if @ascii
|
164
|
+
@obj = obj
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# sort by column
|
169
|
+
def sort col
|
170
|
+
@table.sort! { |a,b| a[col] <=> b[col] }
|
171
|
+
@table.reverse! if @reverse
|
172
|
+
if @reverse == false
|
173
|
+
@reverse = true
|
174
|
+
else
|
175
|
+
@reverse = false
|
176
|
+
end
|
177
|
+
create
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
def ascii_table_line
|
182
|
+
_obj = []
|
183
|
+
_obj << Pixel.new(@pixel.fg,@bg,"+")
|
184
|
+
@meta[:max_widths].each do |index,mw|
|
185
|
+
(mw+2).times do |i|
|
186
|
+
_obj << Pixel.new(@pixel.fg,@bg,"-")
|
187
|
+
end
|
188
|
+
_obj << Pixel.new(@pixel.fg,@bg,"+")
|
189
|
+
end
|
190
|
+
_obj
|
191
|
+
end
|
192
|
+
|
193
|
+
def index_col_widths
|
194
|
+
@meta[:cols] = 0
|
195
|
+
@meta[:max_widths] = {}
|
196
|
+
@table.each do |line|
|
197
|
+
cols = 0
|
198
|
+
if !line.nil?
|
199
|
+
line.each_with_index do |col, index|
|
200
|
+
@meta[:max_widths][index] = col.size if @meta[:max_widths][index].nil?
|
201
|
+
@meta[:max_widths][index] = col.size if @meta[:max_widths][index] < col.size
|
202
|
+
@meta[:max_widths][index] = @cols[index][:max_length] if !@cols.nil? and !@cols[index].nil? and !@cols[index][:max_length].nil?
|
203
|
+
@meta[:max_widths][index] = @cols[index][:length] if !@cols.nil? and !@cols[index].nil? and !@cols[index][:length].nil?
|
204
|
+
end
|
205
|
+
@meta[:cols] = cols if cols > @meta[:cols]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|