simple_gui_creator 0.1.0

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