purple_shoes 0.0.101

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. data/README.md +56 -0
  2. data/VERSION +1 -0
  3. data/bin/pshoes +23 -0
  4. data/bin/pshoes.bat +2 -0
  5. data/lib/plugins/video.rb +88 -0
  6. data/lib/purple_shoes.rb +51 -0
  7. data/lib/shoes/anim.rb +47 -0
  8. data/lib/shoes/app.rb +688 -0
  9. data/lib/shoes/basic.rb +254 -0
  10. data/lib/shoes/colors.rb +149 -0
  11. data/lib/shoes/download.rb +26 -0
  12. data/lib/shoes/help.rb +473 -0
  13. data/lib/shoes/helper_methods.rb +295 -0
  14. data/lib/shoes/main.rb +96 -0
  15. data/lib/shoes/manual.rb +6 -0
  16. data/lib/shoes/ruby.rb +61 -0
  17. data/lib/shoes/slot.rb +104 -0
  18. data/lib/shoes/style.rb +41 -0
  19. data/lib/shoes/text.rb +46 -0
  20. data/lib/shoes/url.rb +14 -0
  21. data/lib/shoes/widget.rb +23 -0
  22. data/samples/class-book.yaml +387 -0
  23. data/samples/cy.png +0 -0
  24. data/samples/loogink.png +0 -0
  25. data/samples/potato_chopping/1258_s001.gif +0 -0
  26. data/samples/potato_chopping/1258_s002.gif +0 -0
  27. data/samples/potato_chopping/1258_s003.gif +0 -0
  28. data/samples/potato_chopping/1258_s004.gif +0 -0
  29. data/samples/potato_chopping/1258_s005.gif +0 -0
  30. data/samples/potato_chopping/1258_s006.gif +0 -0
  31. data/samples/potato_chopping/1258_s007.gif +0 -0
  32. data/samples/potato_chopping/1258_s008.gif +0 -0
  33. data/samples/potato_chopping/1258_s009.gif +0 -0
  34. data/samples/potato_chopping/1258_s010.gif +0 -0
  35. data/samples/potato_chopping/1258_s011.gif +0 -0
  36. data/samples/potato_chopping/1258_s012.gif +0 -0
  37. data/samples/potato_chopping/1258_s013.gif +0 -0
  38. data/samples/potato_chopping/1258_s014.gif +0 -0
  39. data/samples/potato_chopping/1258_s015.gif +0 -0
  40. data/samples/potato_chopping/1258_s016.gif +0 -0
  41. data/samples/potato_chopping/1258_s017.gif +0 -0
  42. data/samples/potato_chopping/1258_s018.gif +0 -0
  43. data/samples/potato_chopping/1258_s019.gif +0 -0
  44. data/samples/potato_chopping/1258_s020.gif +0 -0
  45. data/samples/potato_chopping/1258_s021.gif +0 -0
  46. data/samples/potato_chopping/1258_s022.gif +0 -0
  47. data/samples/potato_chopping/1258_s023.gif +0 -0
  48. data/samples/potato_chopping/1258_s024.gif +0 -0
  49. data/samples/potato_chopping/1258_s025.gif +0 -0
  50. data/samples/potato_chopping/1258_s026.gif +0 -0
  51. data/samples/potato_chopping/1258_s027.gif +0 -0
  52. data/samples/potato_chopping/1258_s028.gif +0 -0
  53. data/samples/potato_chopping/1258_s029.gif +0 -0
  54. data/samples/potato_chopping/1258_s030.gif +0 -0
  55. data/samples/potato_chopping/1258_s031.gif +0 -0
  56. data/samples/potato_chopping/1258_s032.gif +0 -0
  57. data/samples/potato_chopping/1258_s033.gif +0 -0
  58. data/samples/potato_chopping/1258_s034.gif +0 -0
  59. data/samples/potato_chopping/1258_s035.gif +0 -0
  60. data/samples/potato_chopping/1258_s036.gif +0 -0
  61. data/samples/potato_chopping/1258_s037.gif +0 -0
  62. data/samples/potato_chopping/1258_s038.gif +0 -0
  63. data/samples/potato_chopping/1258_s039.gif +0 -0
  64. data/samples/potato_chopping/1258_s040.gif +0 -0
  65. data/samples/potato_chopping/1258_s041.gif +0 -0
  66. data/samples/potato_chopping/1258_s042.gif +0 -0
  67. data/samples/potato_chopping/1258_s043.gif +0 -0
  68. data/samples/potato_chopping/1258_s044.gif +0 -0
  69. data/samples/potato_chopping/1258_s045.gif +0 -0
  70. data/samples/potato_chopping/1258_s046.gif +0 -0
  71. data/samples/potato_chopping/1258_s047.gif +0 -0
  72. data/samples/potato_chopping/1258_s048.gif +0 -0
  73. data/samples/potato_chopping/1258_s049.gif +0 -0
  74. data/samples/potato_chopping/1258_s050.gif +0 -0
  75. data/samples/potato_chopping/1258_s051.gif +0 -0
  76. data/samples/potato_chopping/1258_s052.gif +0 -0
  77. data/samples/potato_chopping/1258_s053.gif +0 -0
  78. data/samples/potato_chopping/1258_s054.gif +0 -0
  79. data/samples/potato_chopping/1258_s055.gif +0 -0
  80. data/samples/potato_chopping/1258_s056.gif +0 -0
  81. data/samples/potato_chopping/1258_s057.gif +0 -0
  82. data/samples/potato_chopping/1258_s058.gif +0 -0
  83. data/samples/potato_chopping/1258_s059.gif +0 -0
  84. data/samples/sample1.rb +30 -0
  85. data/samples/sample10.rb +11 -0
  86. data/samples/sample11.rb +12 -0
  87. data/samples/sample12.rb +22 -0
  88. data/samples/sample13.rb +15 -0
  89. data/samples/sample14.rb +75 -0
  90. data/samples/sample15.rb +20 -0
  91. data/samples/sample16.rb +12 -0
  92. data/samples/sample17.rb +12 -0
  93. data/samples/sample18.rb +24 -0
  94. data/samples/sample19.rb +39 -0
  95. data/samples/sample2.rb +16 -0
  96. data/samples/sample20.rb +26 -0
  97. data/samples/sample21.rb +7 -0
  98. data/samples/sample22.rb +13 -0
  99. data/samples/sample23.rb +10 -0
  100. data/samples/sample24.rb +22 -0
  101. data/samples/sample25.rb +22 -0
  102. data/samples/sample27.rb +19 -0
  103. data/samples/sample28.rb +64 -0
  104. data/samples/sample29.rb +12 -0
  105. data/samples/sample3.rb +10 -0
  106. data/samples/sample30.rb +30 -0
  107. data/samples/sample31.rb +24 -0
  108. data/samples/sample34.rb +29 -0
  109. data/samples/sample35.rb +33 -0
  110. data/samples/sample36.rb +48 -0
  111. data/samples/sample37.rb +10 -0
  112. data/samples/sample38.rb +14 -0
  113. data/samples/sample4.rb +9 -0
  114. data/samples/sample40.rb +19 -0
  115. data/samples/sample42.rb +15 -0
  116. data/samples/sample43.rb +26 -0
  117. data/samples/sample44.rb +57 -0
  118. data/samples/sample45.rb +12 -0
  119. data/samples/sample46.rb +35 -0
  120. data/samples/sample47.rb +20 -0
  121. data/samples/sample48.rb +33 -0
  122. data/samples/sample49.rb +33 -0
  123. data/samples/sample5.rb +8 -0
  124. data/samples/sample50.rb +326 -0
  125. data/samples/sample58.rb +19 -0
  126. data/samples/sample6.rb +11 -0
  127. data/samples/sample7.rb +5 -0
  128. data/samples/sample8.rb +9 -0
  129. data/samples/sample9.rb +12 -0
  130. data/samples/sample99.rb +4 -0
  131. data/samples/sounds/102719__sarge4267__explosion.mp3 +0 -0
  132. data/samples/sounds/145622__andybrannan__train-fog-horn-long-wyomming.aiff +0 -0
  133. data/samples/sounds/46492__phreaksaccount__shields1.ogg +0 -0
  134. data/samples/sounds/61847__simon-rue__boink-v3.wav +0 -0
  135. data/snapshots/sample1.png +0 -0
  136. data/snapshots/sample10.png +0 -0
  137. data/snapshots/sample11.png +0 -0
  138. data/snapshots/sample12.png +0 -0
  139. data/snapshots/sample13.png +0 -0
  140. data/snapshots/sample14.png +0 -0
  141. data/snapshots/sample15.png +0 -0
  142. data/snapshots/sample16.png +0 -0
  143. data/snapshots/sample17.png +0 -0
  144. data/snapshots/sample18.png +0 -0
  145. data/snapshots/sample19.png +0 -0
  146. data/snapshots/sample2.png +0 -0
  147. data/snapshots/sample20.png +0 -0
  148. data/snapshots/sample21.png +0 -0
  149. data/snapshots/sample22.png +0 -0
  150. data/snapshots/sample23.png +0 -0
  151. data/snapshots/sample24.png +0 -0
  152. data/snapshots/sample25.png +0 -0
  153. data/snapshots/sample27.png +0 -0
  154. data/snapshots/sample28.png +0 -0
  155. data/snapshots/sample29.png +0 -0
  156. data/snapshots/sample3-osx.png +0 -0
  157. data/snapshots/sample3.png +0 -0
  158. data/snapshots/sample30.png +0 -0
  159. data/snapshots/sample31.png +0 -0
  160. data/snapshots/sample33.png +0 -0
  161. data/snapshots/sample34.png +0 -0
  162. data/snapshots/sample35.png +0 -0
  163. data/snapshots/sample36.png +0 -0
  164. data/snapshots/sample37.png +0 -0
  165. data/snapshots/sample38.png +0 -0
  166. data/snapshots/sample4.png +0 -0
  167. data/snapshots/sample40.png +0 -0
  168. data/snapshots/sample42.png +0 -0
  169. data/snapshots/sample43.png +0 -0
  170. data/snapshots/sample44-linux.png +0 -0
  171. data/snapshots/sample44.png +0 -0
  172. data/snapshots/sample45.png +0 -0
  173. data/snapshots/sample46.png +0 -0
  174. data/snapshots/sample47.png +0 -0
  175. data/snapshots/sample48.png +0 -0
  176. data/snapshots/sample49.png +0 -0
  177. data/snapshots/sample5.png +0 -0
  178. data/snapshots/sample50.png +0 -0
  179. data/snapshots/sample58.png +0 -0
  180. data/snapshots/sample6.png +0 -0
  181. data/snapshots/sample7.png +0 -0
  182. data/snapshots/sample8.png +0 -0
  183. data/snapshots/sample9.png +0 -0
  184. data/snapshots/sample99.png +0 -0
  185. data/static/code_highlighter.js +188 -0
  186. data/static/code_highlighter_ruby.js +26 -0
  187. data/static/man-editor-notepad.png +0 -0
  188. data/static/man-editor-osx.png +0 -0
  189. data/static/man-ele-background.png +0 -0
  190. data/static/man-ele-border.png +0 -0
  191. data/static/man-ele-button.png +0 -0
  192. data/static/man-ele-check.png +0 -0
  193. data/static/man-ele-editbox.png +0 -0
  194. data/static/man-ele-editline.png +0 -0
  195. data/static/man-ele-image.png +0 -0
  196. data/static/man-ele-listbox.png +0 -0
  197. data/static/man-ele-progress.png +0 -0
  198. data/static/man-ele-radio.png +0 -0
  199. data/static/man-ele-shape.png +0 -0
  200. data/static/man-ele-textblock.png +0 -0
  201. data/static/man-ele-video.png +0 -0
  202. data/static/man-shot1.png +0 -0
  203. data/static/manual-en.txt +3969 -0
  204. data/static/manual-ja.txt +3882 -0
  205. data/static/manual.css +184 -0
  206. data/static/purple_shoes-icon.png +0 -0
  207. data/static/rshoes-icon.png +0 -0
  208. data/static/shoes-manual-apps.png +0 -0
  209. data/static/sound_jars/jl1.0.1.jar +0 -0
  210. data/static/sound_jars/jogg-0.0.7.jar +0 -0
  211. data/static/sound_jars/jorbis-0.0.15.jar +0 -0
  212. data/static/sound_jars/mp3spi1.9.5.jar +0 -0
  213. data/static/sound_jars/tritonus_share.jar +0 -0
  214. data/static/sound_jars/vorbisspi1.0.3.jar +0 -0
  215. metadata +271 -0
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ Purple Shoes
2
+ ==========
3
+
4
+ Porting [Green Shoes](https://github.com/ashbb/green_shoes) with **JRuby** and **SWT**.
5
+
6
+ Install JRuby and Purple Shoes for Windows
7
+ -----------------------------------------
8
+
9
+ - download and install [JRuby 1.6.7 Windows Executable](http://jruby.org/download)
10
+ - jruby --1.9 -S gem install purple_shoes
11
+
12
+ The [swt](http://rubygems.org/gems/swt) gem will be installed automatically.
13
+
14
+ Install JRuby and Purple Shoes for Linux and OS X
15
+ -----------------------------------------------
16
+
17
+ - install [rvm](http://beginrescueend.com/)
18
+ - rvm install jruby
19
+ - gem install purple_shoes
20
+
21
+ Look at the command line help
22
+ -----------------------------
23
+
24
+ ```
25
+ jruby --1.9 -S pshoes -h
26
+ ```
27
+
28
+ <pre>
29
+ Usage: pshoes (options or app.rb)
30
+ -m, -men Open the built-in English manual.
31
+ -mjp Open the built-in Japanese manual.
32
+ -v Display the version info.
33
+ -h Show this message.
34
+ </pre>
35
+
36
+ **Note**: If you set an environment variable like this: `set JRUBY_OPTS=--1.9`, you can do just only `pshoes -h`.
37
+
38
+
39
+ Note to OSX Users
40
+ -----------------
41
+
42
+ You'll need to pass an extra argument to JRuby's JVM for SWT to work on OSX. Your command line should look like this:
43
+
44
+ ```
45
+ jruby -J-XstartOnFirstThread --1.9 sample2.rb
46
+ ```
47
+
48
+
49
+ Open the built-in manual
50
+ -----------------------
51
+
52
+ ```
53
+ jruby --1.9 -S pshoes -m
54
+ ```
55
+
56
+ ![snapshot](https://github.com/ashbb/purple_shoes/raw/master/manual.png)
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.101
data/bin/pshoes ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../lib/purple_shoes'
3
+
4
+ arg = ARGV[0]
5
+ path = File.expand_path(arg.gsub(/\\/, "/")) if arg
6
+ ARGV[0] = path
7
+
8
+ case arg
9
+ when '-m', '-men'
10
+ Shoes.show_manual
11
+ when '-mjp'
12
+ Shoes.show_manual 'Japanese'
13
+ when '-h', nil
14
+ puts "Usage: pshoes (options or app.rb)
15
+ -m, -men Open the built-in English manual.
16
+ -mjp Open the built-in Japanese manual.
17
+ -v Display the version info.
18
+ -h Show this message."
19
+ when '-v'
20
+ puts IO.read File.join(DIR, '../VERSION')
21
+ else
22
+ load path
23
+ end
data/bin/pshoes.bat ADDED
@@ -0,0 +1,2 @@
1
+ @ECHO OFF
2
+ @pshoes %1
@@ -0,0 +1,88 @@
1
+ # Original code was written by pjfitzgibbons (Peter Fitzgibbons) in Brown Shoes
2
+ # Edited a little bit for Purple Shoes by ashbb
3
+
4
+ require File.join(DIR, '../static/sound_jars/tritonus_share.jar')
5
+ require File.join(DIR, '../static/sound_jars/mp3spi1.9.5.jar')
6
+ require File.join(DIR, '../static/sound_jars/jl1.0.1.jar')
7
+ require File.join(DIR, '../static/sound_jars/jogg-0.0.7.jar')
8
+ require File.join(DIR, '../static/sound_jars/jorbis-0.0.15.jar')
9
+ require File.join(DIR, '../static/sound_jars/vorbisspi1.0.3.jar')
10
+
11
+ class Shoes
12
+ class Video
13
+ JFile = java.io.File
14
+ import java.io.BufferedInputStream
15
+ import javax.sound.sampled
16
+ import java.io.IOException
17
+
18
+ BufferSize = 4096
19
+
20
+ def initialize args
21
+ @initials = args
22
+ args.each do |k, v|
23
+ instance_variable_set "@#{k}", v
24
+ end
25
+ Video.class_eval do
26
+ attr_accessor *args.keys
27
+ end
28
+ end
29
+
30
+ def play
31
+ Thread.new do
32
+ audio_input_stream = AudioSystem.getAudioInputStream JFile.new(@path)
33
+ audio_format = audio_input_stream.getFormat
34
+ rawplay *decode_input_stream(audio_format, audio_input_stream)
35
+ audio_input_stream.close
36
+ end
37
+ end
38
+
39
+ def decode_input_stream audio_format, audio_input_stream
40
+ case audio_format.encoding
41
+ when Java::JavazoomSpiVorbisSampledFile::VorbisEncoding, Java::JavazoomSpiMpegSampledFile::MpegEncoding
42
+ decoded_format = AudioFormat.new(AudioFormat::Encoding::PCM_SIGNED, audio_format.getSampleRate(), 16,
43
+ audio_format.getChannels(), audio_format.getChannels() * 2, audio_format.getSampleRate(), false)
44
+ decoded_audio_input_stream = AudioSystem.getAudioInputStream(decoded_format, audio_input_stream)
45
+ return decoded_format, decoded_audio_input_stream
46
+ else
47
+ return audio_format, audio_input_stream
48
+ end
49
+ end
50
+
51
+ def rawplay(decoded_audio_format, decoded_audio_input_stream)
52
+ sampled_data = Java::byte[BufferSize].new
53
+ line = getLine(decoded_audio_format)
54
+ if line != nil
55
+ line.start()
56
+ bytes_read = 0, bytes_written = 0
57
+ while bytes_read != -1
58
+ bytes_read = decoded_audio_input_stream.read(sampled_data, 0, sampled_data.length)
59
+ if bytes_read != -1
60
+ bytes_written = line.write(sampled_data, 0, bytes_read)
61
+ end
62
+ end
63
+ line.drain()
64
+ line.stop()
65
+ line.close()
66
+ decoded_audio_input_stream.close()
67
+ end
68
+ end
69
+
70
+ def getLine(audioFormat)
71
+ res = nil
72
+ info = DataLine::Info.new(SourceDataLine.java_class, audioFormat)
73
+ res = AudioSystem.getLine(info)
74
+ res.open(audioFormat)
75
+ res
76
+ end
77
+ end
78
+ end
79
+
80
+ class Shoes
81
+ class App
82
+ def video file
83
+ args = {}
84
+ args[:real], args[:app], args[:path] = nil, self, file
85
+ Video.new args
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,51 @@
1
+ require 'tmpdir'
2
+ require 'pathname'
3
+ require 'java'
4
+ require 'swt'
5
+
6
+ STDOUT.sync = true
7
+
8
+ Types = module Shoes; self end
9
+
10
+ module Shoes
11
+ DIR = Pathname.new(__FILE__).realpath.dirname.to_s
12
+ SHOES_VERSION = IO.read(File.join(DIR, '../VERSION')).chomp
13
+ BASIC_ATTRIBUTES_DEFAULT = {left: 0, top: 0, width: 0, height: 0, angle: 0, curve: 0}
14
+ SLOT_ATTRIBUTES_DEFAULT = {left: nil, top: nil, width: 1.0, height: 0}
15
+
16
+ KEY_NAMES = {}
17
+ %w[DEL ESC ALT SHIFT CTRL ARROW_UP ARROW_DOWN ARROW_LEFT ARROW_RIGHT
18
+ PAGE_UP PAGE_DOWN HOME END INSERT
19
+ F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15].each{|k| KEY_NAMES[eval("Swt::SWT::#{k}")] = k}
20
+ KEY_NAMES[Swt::SWT::CR] = "\n"
21
+ COLORS = {}
22
+ end
23
+
24
+ module Swt
25
+ include_package 'org.eclipse.swt'
26
+ include_package 'org.eclipse.swt.layout'
27
+ include_package 'org.eclipse.swt.widgets'
28
+ include_package 'org.eclipse.swt.graphics'
29
+ include_package 'org.eclipse.swt.events'
30
+ end
31
+
32
+ class Object
33
+ remove_const :Shoes
34
+ end
35
+
36
+ require_relative 'shoes/ruby'
37
+ require_relative 'shoes/helper_methods'
38
+ require_relative 'shoes/colors'
39
+ require_relative 'shoes/basic'
40
+ require_relative 'shoes/main'
41
+ require_relative 'shoes/app'
42
+ require_relative 'shoes/anim'
43
+ require_relative 'shoes/slot'
44
+ require_relative 'shoes/text'
45
+ require_relative 'shoes/widget'
46
+ require_relative 'shoes/url'
47
+ require_relative 'shoes/style'
48
+ require_relative 'shoes/download'
49
+ require_relative 'shoes/manual'
50
+
51
+ require_relative 'plugins/video'
data/lib/shoes/anim.rb ADDED
@@ -0,0 +1,47 @@
1
+ class Shoes
2
+ class Anim
3
+ def initialize cs, n=100, repaint=true, &blk
4
+ @cs, @n, @repaint, @i, @blk = cs, n, repaint, 0, blk
5
+ end
6
+
7
+ def run
8
+ if continue?
9
+ @blk[@i = pause? ? @i : @i+1]
10
+ if @cs.isDisposed
11
+ stop
12
+ return
13
+ elsif @repaint
14
+ @cs.redraw
15
+ end
16
+ Shoes.display.timerExec @n, self
17
+ end
18
+ end
19
+
20
+ def stop
21
+ @stop = true
22
+ end
23
+
24
+ def continue?
25
+ !@stop
26
+ end
27
+
28
+ def pause
29
+ @pause = !@pause
30
+ end
31
+
32
+ def pause?
33
+ @pause
34
+ end
35
+ end
36
+
37
+ class Timer
38
+ def initialize app, n=1000, &blk
39
+ @app, @n, @blk = app, n, blk
40
+ end
41
+
42
+ def run
43
+ @blk.call
44
+ @app.flush
45
+ end
46
+ end
47
+ end
data/lib/shoes/app.rb ADDED
@@ -0,0 +1,688 @@
1
+ class Shoes
2
+ class App
3
+ include Mod2
4
+
5
+ def initialize args={}
6
+ args.each do |k, v|
7
+ instance_variable_set "@#{k}", v
8
+ end
9
+ App.class_eval do
10
+ attr_accessor *(args.keys - [:width, :height, :title])
11
+ end
12
+ init_app_vars
13
+ @top_slot, @cslot = nil, self
14
+ end
15
+
16
+ attr_accessor :cslot, :top_slot, :contents, :mmcs, :mscs, :order, :mouse_pos, :hided
17
+ attr_writer :mouse_button
18
+ attr_reader :location
19
+
20
+ def visit url
21
+ if url =~ /^(http|https):\/\//
22
+ system "start #{url}"
23
+ else
24
+ $urls.each{|k, v| clear{init_app_vars; @location = url; v.call self, $1} if k =~ url}
25
+ end
26
+ end
27
+
28
+ def stack args={}, &blk
29
+ args[:app] = self
30
+ Stack.new slot_attributes(args), &blk
31
+ end
32
+
33
+ def flow args={}, &blk
34
+ args[:app] = self
35
+ Flow.new slot_attributes(args), &blk
36
+ end
37
+
38
+ def clear &blk
39
+ @top_slot.clear &blk
40
+ aflush
41
+ end
42
+
43
+ def click &blk
44
+ if blk
45
+ app = self
46
+ ln = Swt::Listener.new
47
+ class << ln; self end.
48
+ instance_eval do
49
+ define_method :handleEvent do |e|
50
+ blk[*app.mouse]
51
+ end
52
+ end
53
+ @cs.addListener Swt::SWT::MouseDown, ln unless @cs.isDisposed
54
+ end
55
+ end
56
+
57
+ def textblock klass, font_size, *msg
58
+ args = msg.last.class == Hash ? msg.pop : {}
59
+ args = basic_attributes args
60
+ args[:markup] = msg.map(&:to_s).join
61
+
62
+ styles = get_styles msg
63
+ args[:styles] = styles unless styles.empty?
64
+
65
+ args[:size] ||= font_size
66
+ args[:font] ||= (@font_family or 'sans')
67
+ args[:stroke] ||= black
68
+ args[:rotate] ||= rotate
69
+
70
+ unless args[:left].zero? and args[:top].zero?
71
+ args[:nocontrol], args[:width] = true, width
72
+ layout_control = false
73
+ else
74
+ layout_control = true
75
+ end
76
+
77
+ args[:real] = (args[:create_real] or !layout_control) ? :textblock : false
78
+ args[:app] = self
79
+
80
+ klass.new(args).tap do |s|
81
+ unless s.real and layout_control
82
+ tl = Swt::TextLayout.new Shoes.display
83
+ s.real = tl
84
+ pl = Swt::PaintListener.new
85
+ s.pl = pl
86
+ class << pl; self end.
87
+ instance_eval do
88
+ define_method :paintControl do |e|
89
+ gc = e.gc
90
+ s.dps << gc
91
+ tl.setText s.markup
92
+ s.app.set_styles s, args
93
+ tl.setWidth s.width if s.width > 0
94
+ unless s.hided
95
+ Shoes.set_rotate gc, *s.rotate do
96
+ tl.draw gc, s.left, s.top
97
+ end
98
+ end
99
+ end
100
+ end
101
+ @cs.addPaintListener pl unless @cs.isDisposed
102
+ end
103
+ end
104
+ end
105
+
106
+ def banner *msg; textblock Banner, 48, *msg; end
107
+ def title *msg; textblock Title, 34, *msg; end
108
+ def subtitle *msg; textblock Subtitle, 26, *msg; end
109
+ def tagline *msg; textblock Tagline, 18, *msg; end
110
+ def caption *msg; textblock Caption, 14, *msg; end
111
+ def para *msg; textblock Para, 12, *msg; end
112
+ def inscription *msg; textblock Para, 10, *msg; end
113
+
114
+ def image name, args={}, &blk
115
+ args = basic_attributes args
116
+ args[:rotate] ||= rotate
117
+ img = Swt::Image.new Shoes.display, name
118
+ args[:full_width], args[:full_height] = img.getImageData.width, img.getImageData.height
119
+ args[:real], args[:app] = img, self
120
+
121
+ Image.new(args).tap do |s|
122
+ pl = Swt::PaintListener.new
123
+ s.pl = pl
124
+ class << pl; self end.
125
+ instance_eval do
126
+ define_method :paintControl do |e|
127
+ gc = e.gc
128
+ s.dps << gc
129
+ unless s.hided
130
+ Shoes.set_rotate e.gc, *s.rotate do
131
+ if s.initials[:width].zero? and s.initials[:height].zero?
132
+ gc.drawImage img, s.left, s.top
133
+ else
134
+ s.width = s.full_width if s.width.zero?
135
+ s.height = s.full_height if s.height.zero?
136
+ gc.drawImage img, 0, 0, s.full_width, s.full_height, s.left, s.top, s.width, s.height
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ @cs.addPaintListener pl unless @cs.isDisposed
143
+ clickable s, &blk
144
+ end
145
+ end
146
+
147
+ def button name, args={}
148
+ args = basic_attributes args
149
+ b = Swt::Button.new @cs, Swt::SWT::NULL
150
+ b.setText name
151
+ b.setLocation args[:left], args[:top]
152
+ if args[:width] > 0 and args[:height] > 0
153
+ b.setSize args[:width], args[:height]
154
+ else
155
+ b.pack
156
+ end
157
+ args[:real], args[:text], args[:app] = b, name, self
158
+ Button.new(args).tap do |s|
159
+ b.addSelectionListener do |e|
160
+ yield s
161
+ end if block_given?
162
+ end
163
+ end
164
+
165
+ def radio args={}, &blk
166
+ args = basic_attributes args
167
+ args[:block] = blk
168
+ b = Swt::Button.new @cs, Swt::SWT::RADIO
169
+ b.setLocation args[:left], args[:top]
170
+ if args[:width] > 0 and args[:height] > 0
171
+ b.setSize args[:width], args[:height]
172
+ else
173
+ b.pack
174
+ end
175
+ args[:real], args[:app] = b, self
176
+ Radio.new(args).tap do |s|
177
+ b.addSelectionListener do |e|
178
+ blk[s] if b.getSelection
179
+ end if blk
180
+ end
181
+ end
182
+
183
+ def edit_text attrs
184
+ klass, w, h, style, blk, attrs = attrs
185
+ args = attrs.last.class == Hash ? attrs.pop : {}
186
+ txt = attrs.first unless attrs.empty?
187
+ args = basic_attributes args
188
+ args[:width] = w if args[:width].zero?
189
+ args[:height] = h if args[:height].zero?
190
+
191
+ el = Swt::Text.new @cs, Swt::SWT::BORDER | style
192
+ el.setText txt || args[:text].to_s
193
+ el.setSize args[:width], args[:height]
194
+ args[:real], args[:app] = el, self
195
+ klass.new(args).tap do |s|
196
+ el.addModifyListener{|e| blk[s]} if blk
197
+ end
198
+ end
199
+
200
+ def edit_line *attrs, &blk
201
+ edit_text [EditLine, 200, 20, Swt::SWT::SINGLE, blk, attrs]
202
+ end
203
+
204
+ def edit_box *attrs, &blk
205
+ edit_text [EditBox, 200, 100, Swt::SWT::MULTI | Swt::SWT::WRAP, blk, attrs]
206
+ end
207
+
208
+ def list_box args={}
209
+ args = basic_attributes args
210
+ args[:width] = 200 if args[:width].zero?
211
+ args[:height] = 20 if args[:height].zero?
212
+ args[:items] ||= []
213
+ cb = Swt::Combo.new @cs, Swt::SWT::DROP_DOWN
214
+ cb.setSize args[:width], args[:height]
215
+ cb.setItems args[:items].map(&:to_s)
216
+ cb.setText args[:choose].to_s
217
+ args[:real], args[:app] = cb, self
218
+ ListBox.new(args).tap do |s|
219
+ cb.addSelectionListener do |e|
220
+ yield s
221
+ end if block_given?
222
+ end
223
+ end
224
+
225
+ def animate n=10, repaint=true, &blk
226
+ n, i = 1000 / n, 0
227
+ Anim.new(@cs, n, repaint, &blk).tap do |a|
228
+ Shoes.display.timerExec n, a
229
+ end
230
+ end
231
+
232
+ def every n=1, &blk
233
+ animate 1.0/n, &blk
234
+ end
235
+
236
+ def timer n=1, &blk
237
+ n *= 1000
238
+ Timer.new(self, n, &blk).tap{|t| Shoes.display.timerExec n, t}
239
+ end
240
+
241
+ def motion &blk
242
+ @mmcs << blk
243
+ end
244
+
245
+ def keypress &blk
246
+ kl = Swt::KeyListener.new
247
+ class << kl; self end.
248
+ instance_eval do
249
+ define_method(:keyPressed){|e| blk[KEY_NAMES[e.keyCode] || e.character.chr]}
250
+ define_method(:keyReleased){|e|}
251
+ end
252
+ @shell.addKeyListener kl
253
+ end
254
+
255
+ def mouse
256
+ [@mouse_button, @mouse_pos[0], @mouse_pos[1]]
257
+ end
258
+
259
+ def shape args={}, &blk
260
+ args = basic_attributes args
261
+ args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
262
+ args[:nocontrol] = args[:noorder] = true
263
+ args[:stroke] ||= stroke
264
+ args[:fill] ||= fill
265
+ args[:rotate] ||= rotate
266
+ args[:real], args[:app], args[:block] = :shape, self, blk
267
+ Shape.new(args).tap do |s|
268
+ pl = Swt::PaintListener.new
269
+ s.pl = pl
270
+ s.real = Swt::Path.new Shoes.display
271
+ class << pl; self end.
272
+ instance_eval do
273
+ define_method :paintControl do |e|
274
+ unless s.hided
275
+ gc = e.gc
276
+ s.dps << gc
277
+ gc.setAntialias Swt::SWT::ON
278
+ sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
279
+ Shoes.set_rotate gc, *s.rotate do
280
+ if pat2
281
+ Shoes.set_pattern s, gc, pat2
282
+ s.instance_eval &s.block
283
+ gc.fillPath s.real
284
+ end
285
+ if pat1
286
+ Shoes.set_pattern s, gc, pat1, :Foreground
287
+ if sw > 0
288
+ gc.setLineWidth sw
289
+ s.instance_eval &s.block
290
+ gc.drawPath s.real
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end
297
+ @cs.addPaintListener pl unless @cs.isDisposed
298
+ end
299
+ end
300
+
301
+ def oval *attrs, &blk
302
+ args = attrs.last.class == Hash ? attrs.pop : {}
303
+ case attrs.length
304
+ when 0, 1
305
+ when 2; args[:left], args[:top] = attrs
306
+ when 3; args[:left], args[:top], args[:radius] = attrs
307
+ else args[:left], args[:top], args[:width], args[:height] = attrs
308
+ end
309
+ args = basic_attributes args
310
+ args[:width].zero? ? (args[:width] = args[:radius] * 2) : (args[:radius] = args[:width]/2.0)
311
+ args[:height] = args[:width] if args[:height].zero?
312
+ args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
313
+ args[:nocontrol] = args[:noorder] = true
314
+
315
+ args[:stroke] ||= stroke
316
+ args[:fill] ||= fill
317
+ args[:rotate] ||= rotate
318
+ args[:real], args[:app] = :shape, self
319
+ Oval.new(args).tap do |s|
320
+ pl = Swt::PaintListener.new
321
+ s.pl = pl
322
+ class << pl; self end.
323
+ instance_eval do
324
+ define_method :paintControl do |e|
325
+ unless s.hided
326
+ gc = e.gc
327
+ s.dps << gc
328
+ gc.setAntialias Swt::SWT::ON
329
+ sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
330
+ Shoes.set_rotate gc, *s.rotate do
331
+ if pat2
332
+ Shoes.set_pattern s, gc, pat2
333
+ gc.fillOval s.left+sw, s.top+sw, s.width-sw*2, s.height-sw*2
334
+ end
335
+ if pat1
336
+ Shoes.set_pattern s, gc, pat1, :Foreground
337
+ if sw > 0
338
+ gc.setLineWidth sw
339
+ gc.drawOval s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw
340
+ end
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end
346
+ @cs.addPaintListener pl unless @cs.isDisposed
347
+ clickable s, &blk
348
+ end
349
+ end
350
+
351
+ def rect *attrs, &blk
352
+ args = attrs.last.class == Hash ? attrs.pop : {}
353
+ case attrs.length
354
+ when 0, 1
355
+ when 2; args[:left], args[:top] = attrs
356
+ when 3; args[:left], args[:top], args[:width] = attrs
357
+ else args[:left], args[:top], args[:width], args[:height] = attrs
358
+ end
359
+ args[:height] = args[:width] unless args[:height]
360
+ args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
361
+ args[:curve] ||= 0
362
+ args[:nocontrol] = args[:noorder] = true
363
+ args = basic_attributes args
364
+
365
+ args[:stroke] ||= stroke
366
+ args[:fill] ||= fill
367
+ args[:rotate] ||= rotate
368
+ args[:real], args[:app] = :shape, self
369
+ Rect.new(args).tap do |s|
370
+ pl = Swt::PaintListener.new
371
+ s.pl = pl
372
+ class << pl; self end.
373
+ instance_eval do
374
+ define_method :paintControl do |e|
375
+ unless s.hided
376
+ gc = e.gc
377
+ s.dps << gc
378
+ gc.setAntialias Swt::SWT::ON
379
+ sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
380
+ Shoes.set_rotate gc, *s.rotate do
381
+ if pat2
382
+ Shoes.set_pattern s, gc, pat2
383
+ gc.fillRoundRectangle s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.curve*2, s.curve*2
384
+ end
385
+ if pat1
386
+ Shoes.set_pattern s, gc, pat1, :Foreground
387
+ if sw > 0
388
+ gc.setLineWidth sw
389
+ gc.drawRoundRectangle s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.curve*2, s.curve*2
390
+ end
391
+ end
392
+ end
393
+ end
394
+ end
395
+ end
396
+ @cs.addPaintListener pl unless @cs.isDisposed
397
+ clickable s, &blk
398
+ end
399
+ end
400
+
401
+ def line *attrs, &blk
402
+ args = attrs.last.class == Hash ? attrs.pop : {}
403
+ case attrs.length
404
+ when 0, 1, 2
405
+ when 3; args[:sx], args[:sy], args[:ex] = attrs; args[:ey] = args[:ex]
406
+ else args[:sx], args[:sy], args[:ex], args[:ey] = attrs
407
+ end
408
+ sx, sy, ex, ey = args[:sx], args[:sy], args[:ex], args[:ey]
409
+ sw = args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
410
+ cw = hsw = sw*0.5
411
+ args[:width], args[:height] = (sx - ex).abs, (sy - ey).abs
412
+ args[:width] += cw
413
+ args[:height] += cw
414
+ args[:nocontrol] = args[:noorder] = true
415
+ args = basic_attributes args
416
+
417
+ if ((sx - ex) < 0 and (sy - ey) < 0) or ((sx - ex) > 0 and (sy - ey) > 0)
418
+ args[:left] = (sx - ex) < 0 ? sx - hsw : ex - hsw
419
+ args[:top] = (sy - ey) < 0 ? sy - hsw : ey - hsw
420
+ elsif ((sx - ex) < 0 and (sy - ey) > 0) or ((sx - ex) > 0 and (sy - ey) < 0)
421
+ args[:left] = (sx - ex) < 0 ? sx - hsw : ex - hsw
422
+ args[:top] = (sy - ey) < 0 ? sy - hsw : ey - hsw
423
+ elsif !(sx - ex).zero? and (sy - ey).zero?
424
+ args[:left] = (sx - ex) < 0 ? sx : ex
425
+ args[:top] = (sy - ey) < 0 ? sy - hsw : ey - hsw
426
+ elsif (sx - ex).zero? and !(sy - ey).zero?
427
+ args[:left] = (sx - ex) < 0 ? sx - hsw : ex - hsw
428
+ args[:top] = (sy - ey) < 0 ? sy : ey
429
+ else
430
+ args[:left] = sw
431
+ args[:top] = sy
432
+ end
433
+
434
+ args[:stroke] ||= stroke
435
+ args[:rotate] ||= rotate
436
+ args[:real], args[:app] = :shape, self
437
+ Line.new(args).tap do |s|
438
+ pl = Swt::PaintListener.new
439
+ s.pl = pl
440
+ class << pl; self end.
441
+ instance_eval do
442
+ define_method :paintControl do |e|
443
+ unless s.hided
444
+ gc = e.gc
445
+ s.dps << gc
446
+ gc.setAntialias Swt::SWT::ON
447
+ sw, pat = s.strokewidth, s.stroke
448
+ Shoes.set_rotate gc, *s.rotate do
449
+ if pat
450
+ Shoes.set_pattern s, gc, pat, :Foreground
451
+ if sw > 0
452
+ gc.setLineWidth sw
453
+ gc.drawLine s.sx, s.sy, s.ex, s.ey
454
+ end
455
+ end
456
+ end
457
+ end
458
+ end
459
+ end
460
+ @cs.addPaintListener pl unless @cs.isDisposed
461
+ clickable s, &blk
462
+ end
463
+ end
464
+
465
+ def star *attrs, &blk
466
+ args = attrs.last.class == Hash ? attrs.pop : {}
467
+ case attrs.length
468
+ when 2; args[:left], args[:top] = attrs
469
+ when 5; args[:left], args[:top], args[:points], args[:outer], args[:inner] = attrs
470
+ else
471
+ end
472
+ args[:points] ||= 10; args[:outer] ||= 100.0; args[:inner] ||= 50.0
473
+ args[:width] = args[:height] = args[:outer]*2.0
474
+ args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
475
+ args[:nocontrol] = args[:noorder] = true
476
+ args[:stroke] ||= stroke
477
+ args[:fill] ||= fill
478
+ args[:rotate] ||= rotate
479
+ args[:real], args[:app] = :shape, self
480
+ Star.new(args).tap do |s|
481
+ pl = Swt::PaintListener.new
482
+ s.pl = pl
483
+ class << pl; self end.
484
+ instance_eval do
485
+ define_method :paintControl do |e|
486
+ unless s.hided
487
+ gc = e.gc
488
+ s.dps << gc
489
+ gc.setAntialias Swt::SWT::ON
490
+ sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
491
+ outer, inner, points, left, top = s.outer, s.inner, s.points, s.left, s.top
492
+ polygon = []
493
+ polygon << left << (top + outer)
494
+ (1..points*2).each do |i|
495
+ angle = i * Math::PI / points
496
+ r = (i % 2 == 0) ? outer : inner
497
+ polygon << (left + r * Math.sin(angle)) << (top + r * Math.cos(angle))
498
+ end
499
+ Shoes.set_rotate gc, *s.rotate do
500
+ if pat2
501
+ Shoes.set_pattern s, gc, pat2
502
+ gc.fillPolygon polygon
503
+ end
504
+ if pat1
505
+ Shoes.set_pattern s, gc, pat1, :Foreground
506
+ if sw > 0
507
+ gc.setLineWidth sw
508
+ gc.drawPolygon polygon
509
+ end
510
+ end
511
+ end
512
+ end
513
+ end
514
+ end
515
+ @cs.addPaintListener pl unless @cs.isDisposed
516
+ clickable s, &blk
517
+ end
518
+ end
519
+
520
+ def rgb r, g, b, l=1.0
521
+ (r <= 1 and g <= 1 and b <= 1) ? [r*255, g*255, b*255, l] : [r, g, b, l]
522
+ end
523
+
524
+ %w[fill stroke strokewidth].each do |name|
525
+ eval "def #{name} #{name}=nil; #{name} ? @#{name}=#{name} : @#{name} end"
526
+ end
527
+
528
+ def rotate angle=nil, left=0, top=0
529
+ angle ? @rotate = [angle, left, top] : @rotate ||= [0, 0, 0]
530
+ end
531
+
532
+ def nostroke
533
+ strokewidth 0
534
+ end
535
+
536
+ def nofill
537
+ @fill = false
538
+ end
539
+
540
+ def gradient *attrs
541
+ case attrs.length
542
+ when 1, 2
543
+ pat1, pat2 = attrs
544
+ pat2 = pat1 unless pat2
545
+ return tr_color(pat1)..tr_color(pat2)
546
+ when 5, 6
547
+ pat, l, t, w, h, angle = attrs
548
+ angle = 0 unless angle
549
+ else
550
+ return black..black
551
+ end
552
+
553
+ pat = tr_color pat
554
+ color = case pat
555
+ when Range; [tr_color(pat.first), tr_color(pat.last)]
556
+ when Array; [pat, pat]
557
+ when String
558
+ return Swt::Pattern.new(Shoes.display, Swt::Image.new(Shoes.display, pat))
559
+ else
560
+ [black, black]
561
+ end
562
+ Swt::Pattern.new Shoes.display, *pattern_pos(l, t, w, h, -angle), Swt::Color.new(Shoes.display, *color[0][0, 3]), Swt::Color.new(Shoes.display, *color[1][0, 3])
563
+ end
564
+
565
+ def tr_color pat
566
+ if pat.is_a?(String) and pat[0] == '#'
567
+ color = pat[1..-1]
568
+ color = color.gsub(/(.)/){$1 + '0'} if color.length == 3
569
+ rgb *color.gsub(/(..)/).map{$1.hex}
570
+ else
571
+ pat
572
+ end
573
+ end
574
+
575
+ def background pat, args={}
576
+ args[:pattern] = pat
577
+ args = basic_attributes args
578
+ args[:curve] ||= 0
579
+ args[:real] = args[:create_real] ? :pattern : false
580
+ args[:app] = self
581
+ Background.new(args).tap do |s|
582
+ unless s.real
583
+ pat = s.pattern
584
+ pl = Swt::PaintListener.new
585
+ s.pl = pl
586
+ class << pl; self end.
587
+ instance_eval do
588
+ define_method :paintControl do |e|
589
+ unless s.hided
590
+ gc = e.gc
591
+ s.dps << gc
592
+ gc.setAntialias Swt::SWT::ON
593
+ Shoes.set_pattern s, gc, pat
594
+ gc.fillRoundRectangle s.left, s.top, s.width, s.height, s.curve*2, s.curve*2
595
+ end
596
+ end
597
+ end
598
+ @cs.addPaintListener pl unless @cs.isDisposed
599
+ end
600
+ oval 0, 0, 0, strokewidth: 0 # A monkey patch for sample 10. I don't know why this line is necessary... xx-P
601
+ end
602
+ end
603
+
604
+ def border pat, args={}
605
+ args[:pattern] = pat
606
+ args = basic_attributes args
607
+ args[:curve] ||= 0
608
+ args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
609
+ args[:real] = args[:create_real] ? :pattern : false
610
+ args[:app] = self
611
+ Border.new(args).tap do |s|
612
+ unless s.real
613
+ pat = s.pattern
614
+ sw = s.strokewidth
615
+ pl = Swt::PaintListener.new
616
+ s.pl = pl
617
+ class << pl; self end.
618
+ instance_eval do
619
+ define_method :paintControl do |e|
620
+ unless s.hided
621
+ gc = e.gc
622
+ s.dps << gc
623
+ gc.setAntialias Swt::SWT::ON
624
+ Shoes.set_pattern s, gc, pat, :Foreground
625
+ if sw > 0
626
+ gc.setLineWidth sw
627
+ gc.drawRoundRectangle s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.curve*2, s.curve*2
628
+ end
629
+ end
630
+ end
631
+ end
632
+ @cs.addPaintListener pl unless @cs.isDisposed
633
+ end
634
+ end
635
+ end
636
+
637
+ def progress args={}
638
+ pb = Swt::ProgressBar.new @cs, Swt::SWT::SMOOTH
639
+ if args[:left] or args[:top]
640
+ args[:noorder] = args[:nocontrol] = true
641
+ end
642
+ args[:width] ||= 150
643
+ args[:height] ||= 16
644
+ args = basic_attributes args
645
+ pb.setSize args[:width], args[:height]
646
+ pb.setLocation args[:left], args[:top]
647
+ args[:real], args[:app] = pb, self
648
+ Progress.new args
649
+ end
650
+
651
+ def download name, args={}, &blk
652
+ Download.new name, args, &blk
653
+ end
654
+
655
+ def scroll_top
656
+ cs.getLocation.y
657
+ end
658
+
659
+ def scroll_top=(n)
660
+ cs.setLocation 0, -n
661
+ shell.getVerticalBar.setSelection n
662
+ end
663
+
664
+ def scroll_height
665
+ scroll_max + height
666
+ end
667
+
668
+ def scroll_max
669
+ shell.getVerticalBar.getMaximum - 10
670
+ end
671
+
672
+ def flush
673
+ unless @cs.isDisposed
674
+ Shoes.call_back_procs self
675
+ @cs.redraw
676
+ end
677
+ end
678
+
679
+ def aflush
680
+ @hided = true
681
+ Swt::Display.getDefault.asyncExec do
682
+ Shoes.call_back_procs self
683
+ @hided = false
684
+ @cs.redraw unless @cs.isDisposed
685
+ end
686
+ end
687
+ end
688
+ end