simple_gui_creator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +70 -0
- data/Rakefile +13 -0
- data/TODO +4 -0
- data/VERSION +1 -0
- data/bin/simple_gui_creator +88 -0
- data/examples/absolute_positioning.rb +12 -0
- data/ext/jl1.0.1.jar +0 -0
- data/lib/simple_gui_creator/drive_info.rb +162 -0
- data/lib/simple_gui_creator/mouse_control.rb +149 -0
- data/lib/simple_gui_creator/parse_template.rb +207 -0
- data/lib/simple_gui_creator/play_audio.rb +79 -0
- data/lib/simple_gui_creator/play_mp3_audio.rb +42 -0
- data/lib/simple_gui_creator/ruby_clip.rb +33 -0
- data/lib/simple_gui_creator/simple_gui_creator.rb +542 -0
- data/lib/simple_gui_creator/storage.rb +124 -0
- data/lib/simple_gui_creator.rb +18 -0
- data/spec/common.rb +5 -0
- data/spec/diesel.mp3 +0 -0
- data/spec/drive_info.spec.rb +75 -0
- data/spec/mouse.spec.rb +67 -0
- data/spec/parse_template.spec.rb +179 -0
- data/spec/play_mp3_audio.spec.rb +31 -0
- data/spec/ruby_clip.spec.rb +11 -0
- data/spec/run_drive_info.rb +4 -0
- data/spec/static.wav +0 -0
- data/spec/swing_helpers.spec.rb +140 -0
- data/vendor/dvdid.exe +0 -0
- data/vendor/mac_dvdid/bin/dvdid +0 -0
- data/vendor/mac_dvdid/include/dvdid/dvdid.h +67 -0
- data/vendor/mac_dvdid/include/dvdid/dvdid2.h +131 -0
- data/vendor/mac_dvdid/include/dvdid/export.h +32 -0
- data/vendor/mac_dvdid/lib/libdvdid.0.dylib +0 -0
- data/vendor/mac_dvdid/lib/libdvdid.a +0 -0
- data/vendor/mac_dvdid/lib/libdvdid.dylib +0 -0
- data/vendor/mac_dvdid/lib/libdvdid.la +41 -0
- metadata +110 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/simple_gui_creator.rb' # for JFrame#close, etc., basically required as of today..
|
4
|
+
|
5
|
+
# for docs, see the README/specs
|
6
|
+
module ParseTemplate
|
7
|
+
|
8
|
+
def _dgb
|
9
|
+
require 'rubygems'
|
10
|
+
require 'ruby-debug'
|
11
|
+
debugger
|
12
|
+
end
|
13
|
+
|
14
|
+
include_package 'javax.swing'; [JFrame, JPanel, JButton, JTextArea, JLabel, UIManager, JScrollPane]
|
15
|
+
java_import java.awt.Font
|
16
|
+
|
17
|
+
class JFramer < JFrame
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super()
|
21
|
+
@panel = JPanel.new
|
22
|
+
@elements = {}
|
23
|
+
@panel.set_layout nil
|
24
|
+
add @panel # why can't I just slap these down? panel? huh?
|
25
|
+
show # this always bites me...I new it up an it just doesn't appear...
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :panel
|
29
|
+
attr_reader :elements
|
30
|
+
attr_accessor :original_title
|
31
|
+
attr_accessor :frame
|
32
|
+
|
33
|
+
def parse_setup_filename filename
|
34
|
+
parse_setup_string File.read(filename)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# "matches" whatever the template string looks like...
|
39
|
+
def parse_setup_string string
|
40
|
+
@frame = self # LODO refactor
|
41
|
+
@current_y = 10
|
42
|
+
@window_max_x = 100
|
43
|
+
all_lines = string.lines.to_a
|
44
|
+
all_lines.each_with_index{|line, idx|
|
45
|
+
begin
|
46
|
+
@current_x = 10
|
47
|
+
if line =~ /\t/
|
48
|
+
raise "sorry, tabs arent allowed, but you can request it"
|
49
|
+
end
|
50
|
+
button_line_regex = /\[(.*?)\]/
|
51
|
+
#>> "| [Setup Preferences:preferences] [Start:start] [Stop:stop] |" .scan button_line_regex
|
52
|
+
#=> [["Setup Preferences:preferences"], ["Start:start"], ["Stop:stop"]]
|
53
|
+
|
54
|
+
text_regex = /"([^"]+)"/ # "some text:name"
|
55
|
+
blank_line_regex = /^\s*(|\|)\s+(|\|)\s*$/ # " | | " or just empty...
|
56
|
+
title_regex = /\s*[-]+([\w ]+)[-]+\s*$/ # ----(a Title)---
|
57
|
+
@current_line_height = 25
|
58
|
+
|
59
|
+
if line =~ title_regex
|
60
|
+
@frame.set_title $1 # done :)
|
61
|
+
@frame.original_title = $1.dup.freeze # freeze...LOL
|
62
|
+
elsif line =~ blank_line_regex
|
63
|
+
@current_y += @current_line_height
|
64
|
+
elsif line =~ button_line_regex
|
65
|
+
# button, or TextArea
|
66
|
+
cur_x = 0
|
67
|
+
while cur_spot = (line[cur_x..-1] =~ button_line_regex)
|
68
|
+
cur_spot += cur_x# we had only acted on a partial line, above, so add in the part we didn't do
|
69
|
+
name = $1
|
70
|
+
end_spot = cur_spot + name.length
|
71
|
+
count_lines_below = 0
|
72
|
+
matching_blank_text_area_string = '[' + ' '*(end_spot-cur_spot) + ']'
|
73
|
+
empty_it_out = matching_blank_text_area_string.gsub(/[\[\]]/, '_') # can't actually blank it out...
|
74
|
+
for line2 in all_lines[idx+1..-1]
|
75
|
+
if line2[cur_spot..(end_spot+1)] == matching_blank_text_area_string
|
76
|
+
line2[cur_spot, end_spot-cur_spot+2] = empty_it_out # :)
|
77
|
+
count_lines_below += 1
|
78
|
+
else
|
79
|
+
break
|
80
|
+
end
|
81
|
+
end
|
82
|
+
if count_lines_below > 0
|
83
|
+
rows = count_lines_below + 1
|
84
|
+
text_area = JTextArea.new(rows, name.split(':')[0].length)
|
85
|
+
text_area.text="\n"*rows
|
86
|
+
# width?
|
87
|
+
scrollPane = JScrollPane.new(text_area)
|
88
|
+
setup_element(scrollPane, name, scrollPane.getPreferredSize.height, text_area)
|
89
|
+
else
|
90
|
+
button = JButton.new
|
91
|
+
setup_element(button, name)
|
92
|
+
end
|
93
|
+
cur_x = end_spot # creep forward within this line...
|
94
|
+
end
|
95
|
+
@current_y += @current_line_height
|
96
|
+
elsif line =~ text_regex
|
97
|
+
for name in line.scan(text_regex)
|
98
|
+
label = JLabel.new
|
99
|
+
setup_element(label, name[0])
|
100
|
+
end
|
101
|
+
@current_y += @current_line_height
|
102
|
+
end
|
103
|
+
# build in realtime LOL
|
104
|
+
@frame.set_size @window_max_x + 25, @current_y + 40
|
105
|
+
rescue
|
106
|
+
puts "Parsing failed on line #{line.inspect} number: #{idx+1}!"
|
107
|
+
raise
|
108
|
+
end
|
109
|
+
}
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def get_text_width text
|
116
|
+
get_text_dimentia(text).width
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_text_dimentia text
|
120
|
+
font = UIManager.getFont("Label.font")
|
121
|
+
frc = java.awt.font.FontRenderContext.new(font.transform, true, true)
|
122
|
+
textLayout = java.awt.font.TextLayout.new(text, font, frc)
|
123
|
+
textLayout.bounds # has #height and #width
|
124
|
+
end
|
125
|
+
|
126
|
+
def setup_element element, name, height=nil, set_text_on_this = element
|
127
|
+
abs_x = nil
|
128
|
+
abs_y = nil
|
129
|
+
#height = nil
|
130
|
+
width = nil
|
131
|
+
if name.include?(':') && !name.end_with?(':') # like "Start:start_button" or "start:button:code_name,attribs" but not "Hello:" let that through
|
132
|
+
text = name.split(':')[0..-2].join(':') # only accept last colon, so they can have text with colons in it
|
133
|
+
code_name_with_attrs = name.split(':')[-1]
|
134
|
+
if code_name_with_attrs.split(',')[0] !~ /=/
|
135
|
+
# like code_name,width=250,x=y
|
136
|
+
code_name, *attributes = code_name_with_attrs.split(',')
|
137
|
+
else
|
138
|
+
code_name = nil
|
139
|
+
attributes = code_name_with_attrs.split(',')
|
140
|
+
end
|
141
|
+
attributes_hashed = {}
|
142
|
+
attributes.each{|attr|
|
143
|
+
key, value = attr.split('=')
|
144
|
+
attributes_hashed[key.strip] = value.strip
|
145
|
+
}
|
146
|
+
if type = attributes_hashed.delete('font')
|
147
|
+
if type == "fixed_width"
|
148
|
+
set_text_on_this.font=Font.new("Monospaced", Font::PLAIN, 14)
|
149
|
+
else
|
150
|
+
raise "all we support is fixed_width font as of yet #{type} #{name}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
for name in ['abs_x', 'abs_y', 'width', 'height']
|
155
|
+
var = attributes_hashed.delete(name)
|
156
|
+
if var
|
157
|
+
if var =~ /chars$/
|
158
|
+
count = var[0..-5].to_i
|
159
|
+
var = get_text_width('m'*count) # TODO fails for height 30chars
|
160
|
+
elsif var =~ /px$/
|
161
|
+
var = var[0..-3].to_i
|
162
|
+
else
|
163
|
+
#raise "need to specify like 10px #{var} #{name}"
|
164
|
+
var = var.to_i # allow it to be clean :P
|
165
|
+
end
|
166
|
+
raise "#{var} has value of zero?" if var == 0
|
167
|
+
eval("#{name} = #{var}") # ugh
|
168
|
+
end
|
169
|
+
end
|
170
|
+
raise "unknown attributes found: #{attributes_hashed.keys.inspect} #{attributes_hashed.inspect} #{code_name}" if attributes_hashed.length > 0
|
171
|
+
else
|
172
|
+
# no code name
|
173
|
+
text = name
|
174
|
+
end
|
175
|
+
if !width
|
176
|
+
if text.blank?
|
177
|
+
raise 'cannot have blank original text without some size specifier:' + name
|
178
|
+
end
|
179
|
+
if text.strip != text
|
180
|
+
# let blank space count as "space" for now, but don't actually set it LOL
|
181
|
+
# is this good for variable spaced fonts, though?
|
182
|
+
width = get_text_width("|" + text + "|") + 35
|
183
|
+
text.strip!
|
184
|
+
else
|
185
|
+
width = get_text_width(text) + 35
|
186
|
+
end
|
187
|
+
end
|
188
|
+
set_text_on_this.text=text
|
189
|
+
abs_x ||= @current_x
|
190
|
+
abs_y ||= @current_y
|
191
|
+
height ||= 20
|
192
|
+
element.set_bounds(abs_x, abs_y, width, height)
|
193
|
+
@frame.panel.add element
|
194
|
+
if code_name
|
195
|
+
code_name.rstrip!
|
196
|
+
raise "double name not allowed #{name} #{code_name}" if @frame.elements[code_name.to_sym]
|
197
|
+
@frame.elements[code_name.to_sym] = set_text_on_this # just symbol access for now...
|
198
|
+
end
|
199
|
+
@current_x = [@current_x, abs_x + width + 5].max
|
200
|
+
@current_line_height = [@current_line_height, (abs_y + height + 5)-@current_y].max # LODO + 5 magic number? 25 - 20 hard coded? hmm...
|
201
|
+
|
202
|
+
@window_max_x = [@window_max_x, @current_x].max # have to track x, but not y
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
# only plays wav/pcm and midi
|
4
|
+
|
5
|
+
class PlayAudio
|
6
|
+
include_package 'javax.sound.sampled'
|
7
|
+
import java.io.File;
|
8
|
+
import java.io.IOException;
|
9
|
+
Type = javax.sound.sampled.LineEvent::Type
|
10
|
+
|
11
|
+
def initialize filename
|
12
|
+
raise 'no filename?' unless filename
|
13
|
+
@filename = filename
|
14
|
+
@done = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def warmup
|
18
|
+
@audioInputStream = AudioSystem.getAudioInputStream(java.io.File.new @filename)
|
19
|
+
@clip = AudioSystem.getClip
|
20
|
+
@done = false
|
21
|
+
@clip.add_line_listener { |line_event|
|
22
|
+
if (line_event.get_type == Type::STOP || line_event.get_type == Type::CLOSE)
|
23
|
+
@done = true;
|
24
|
+
shutdown
|
25
|
+
end
|
26
|
+
}
|
27
|
+
@clip.open(@audioInputStream)
|
28
|
+
end
|
29
|
+
|
30
|
+
def start
|
31
|
+
warmup
|
32
|
+
@clip.start
|
33
|
+
end
|
34
|
+
|
35
|
+
alias play_non_blocking start
|
36
|
+
|
37
|
+
def loop
|
38
|
+
warmup
|
39
|
+
@clip.loop(Clip::LOOP_CONTINUOUSLY)
|
40
|
+
end
|
41
|
+
|
42
|
+
def join_finish
|
43
|
+
while !@done
|
44
|
+
sleep 0.01
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def play_till_end
|
49
|
+
start
|
50
|
+
join_finish
|
51
|
+
end
|
52
|
+
|
53
|
+
def shutdown
|
54
|
+
@clip.close
|
55
|
+
@audioInputStream.close
|
56
|
+
end
|
57
|
+
|
58
|
+
def stop
|
59
|
+
@done = true
|
60
|
+
shutdown
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
if $0 == __FILE__
|
65
|
+
p = PlayAudio.new ARGV[0]
|
66
|
+
p.start
|
67
|
+
p 'playing'
|
68
|
+
sleep 2
|
69
|
+
p.stop
|
70
|
+
p.join_finish
|
71
|
+
p 'silence'
|
72
|
+
sleep 2
|
73
|
+
p 'looping'
|
74
|
+
p.loop
|
75
|
+
sleep 2
|
76
|
+
p.stop
|
77
|
+
p 'silence'
|
78
|
+
sleep 2
|
79
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# translation from http://introcs.cs.princeton.edu/java/faq/mp3/MP3.java.html
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
require File.dirname(__FILE__) + '/../../ext/jl1.0.1.jar' # third party jlayer mp3 jar <sigh>
|
5
|
+
|
6
|
+
class PlayMp3Audio
|
7
|
+
java_import "javazoom.jl.player.Player"
|
8
|
+
|
9
|
+
def initialize filename # does not work with .wav, unfortunately...
|
10
|
+
@filename = filename
|
11
|
+
end
|
12
|
+
|
13
|
+
def start
|
14
|
+
raise 'file not found?' unless File.exist? @filename
|
15
|
+
fis = java.io.FileInputStream.new(@filename)
|
16
|
+
bstream = java.io.BufferedInputStream.new(fis)
|
17
|
+
@player = Player.new(bstream)
|
18
|
+
@thread = Thread.new {
|
19
|
+
@player.play
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def join
|
24
|
+
@thread.join
|
25
|
+
end
|
26
|
+
|
27
|
+
def play_till_end
|
28
|
+
start
|
29
|
+
join
|
30
|
+
end
|
31
|
+
|
32
|
+
alias play_non_blocking start
|
33
|
+
|
34
|
+
def stop
|
35
|
+
if @player
|
36
|
+
@player.close # at least they give us this method yikes
|
37
|
+
@player = nil
|
38
|
+
end
|
39
|
+
# raising here means you didn't call
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
class RubyClip
|
4
|
+
import java.awt.datatransfer.StringSelection;
|
5
|
+
import java.awt.Toolkit;
|
6
|
+
|
7
|
+
include java.awt.datatransfer.ClipboardOwner
|
8
|
+
|
9
|
+
def self.set_clipboard to_this
|
10
|
+
stringSelection = StringSelection.new( to_this.to_s )
|
11
|
+
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
|
12
|
+
clipboard.setContents( stringSelection, self );
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.lostOwnership(aClipboard, aContents)
|
16
|
+
# ignore...
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.get_clipboard_contents
|
20
|
+
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
|
21
|
+
data = clipboard.get_contents self
|
22
|
+
data.getTransferData java.awt.datatransfer.DataFlavor::stringFlavor
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
if $0 == __FILE__
|
28
|
+
RubyClip.set_clipboard "from jruby1"
|
29
|
+
puts 'set clipboard contents...'
|
30
|
+
RubyClip.set_clipboard "from jruby2"
|
31
|
+
RubyClip.set_clipboard "from jruby3"
|
32
|
+
STDIN.getc
|
33
|
+
end
|