purple_shoes 0.0.101

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.
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