green_shoes 0.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +104 -0
  3. data/README.rdoc +23 -0
  4. data/README_old.md +132 -0
  5. data/lib/ext/bloops.rb +1 -0
  6. data/lib/ext/bloops/bloops.so +0 -0
  7. data/lib/ext/bloops/libportaudio-2.dll +0 -0
  8. data/lib/ext/bloops/songs/1901_by_Aanand_Prasad.rb +478 -0
  9. data/lib/ext/bloops/songs/bloopsaphone_theme_song_by_why.rb +31 -0
  10. data/lib/ext/bloops/songs/feepogram.rb +67 -0
  11. data/lib/ext/bloops/songs/simpsons_theme_song_by_why.rb +14 -0
  12. data/lib/ext/chipmunk.rb +34 -0
  13. data/lib/ext/chipmunk/chipmunk.so +0 -0
  14. data/lib/ext/projector.rb +1 -0
  15. data/lib/ext/projector/matrix3d.rb +73 -0
  16. data/lib/ext/projector/projector.rb +306 -0
  17. data/lib/green_shoes.rb +45 -0
  18. data/lib/shoes/anim.rb +19 -0
  19. data/lib/shoes/app.rb +591 -0
  20. data/lib/shoes/basic.rb +242 -0
  21. data/lib/shoes/colors.rb +150 -0
  22. data/lib/shoes/download.rb +26 -0
  23. data/lib/shoes/help.rb +171 -0
  24. data/lib/shoes/helper_methods.rb +308 -0
  25. data/lib/shoes/main.rb +99 -0
  26. data/lib/shoes/manual.rb +6 -0
  27. data/lib/shoes/mask.rb +29 -0
  28. data/lib/shoes/projector.rb +42 -0
  29. data/lib/shoes/ruby.rb +73 -0
  30. data/lib/shoes/slot.rb +68 -0
  31. data/lib/shoes/text.rb +44 -0
  32. data/lib/shoes/url.rb +14 -0
  33. data/lib/shoes/widget.rb +18 -0
  34. data/static/Coolvetica.ttf +0 -0
  35. data/static/Lacuna.ttf +0 -0
  36. data/static/downloading.png +0 -0
  37. data/static/gshoes-heading-icon.png +0 -0
  38. data/static/gshoes-icon.png +0 -0
  39. data/static/man-app.png +0 -0
  40. data/static/man-builds.png +0 -0
  41. data/static/man-builds1.png +0 -0
  42. data/static/man-editor-notepad.png +0 -0
  43. data/static/man-editor-osx.png +0 -0
  44. data/static/man-ele-background.png +0 -0
  45. data/static/man-ele-border.png +0 -0
  46. data/static/man-ele-button.png +0 -0
  47. data/static/man-ele-check.png +0 -0
  48. data/static/man-ele-editbox.png +0 -0
  49. data/static/man-ele-editline.png +0 -0
  50. data/static/man-ele-image.png +0 -0
  51. data/static/man-ele-listbox.png +0 -0
  52. data/static/man-ele-progress.png +0 -0
  53. data/static/man-ele-radio.png +0 -0
  54. data/static/man-ele-shape.png +0 -0
  55. data/static/man-ele-textblock.png +0 -0
  56. data/static/man-ele-video.png +0 -0
  57. data/static/man-intro-dmg.png +0 -0
  58. data/static/man-intro-exe.png +0 -0
  59. data/static/man-look-tiger.png +0 -0
  60. data/static/man-look-ubuntu.png +0 -0
  61. data/static/man-look-vista.png +0 -0
  62. data/static/man-run-osx.png +0 -0
  63. data/static/man-run-vista.png +0 -0
  64. data/static/man-run-xp.png +0 -0
  65. data/static/man-shot1.png +0 -0
  66. data/static/manual-en.txt +3523 -0
  67. data/static/manual-ja.txt +2825 -0
  68. data/static/shoes-manual-apps.png +0 -0
  69. metadata +146 -0
@@ -0,0 +1,242 @@
1
+ class Shoes
2
+ class Basic
3
+ include Mod
4
+ def initialize args
5
+ args.each do |k, v|
6
+ instance_variable_set "@#{k}", v
7
+ end
8
+
9
+ (@app.order << self) unless @noorder or self.is_a?(EditBox) or self.is_a?(EditLine)
10
+ (@app.cslot.contents << self) unless @nocontrol or @app.cmask
11
+ (@app.cmask.contents << self) if @app.cmask
12
+ @parent = @app.cslot
13
+
14
+ Basic.class_eval do
15
+ attr_accessor *args.keys
16
+ end
17
+
18
+ (@width, @height = @real.size_request) if @real and !self.is_a?(TextBlock)
19
+
20
+ set_margin
21
+ @width += (@margin_left + @margin_right)
22
+ @height += (@margin_top + @margin_bottom)
23
+
24
+ @proc = nil
25
+ [:app, :real].each{|k| args.delete k}
26
+ @args = args
27
+ @hided, @shows, @hovered = false, true, false
28
+ end
29
+
30
+ attr_reader :parent, :click_proc, :release_proc, :hover_proc, :leave_proc, :args, :shows
31
+ attr_accessor :hided, :hovered
32
+
33
+ def move x, y
34
+ @app.cslot.contents -= [self]
35
+ @app.canvas.move @real, x, y
36
+ move3 x, y
37
+ self
38
+ end
39
+
40
+ def move2 x, y
41
+ unless @hided
42
+ remove
43
+ @app.canvas.put @real, x, y
44
+ end
45
+ move3 x, y
46
+ end
47
+
48
+ def move3 x, y
49
+ @left, @top = x, y
50
+ end
51
+
52
+ def remove
53
+ @app.canvas.remove @real unless @hided
54
+ end
55
+
56
+ def hide
57
+ @app.shcs.delete self
58
+ @app.shcs << self
59
+ @shows = false
60
+ self
61
+ end
62
+
63
+ def show
64
+ @app.shcs.delete self
65
+ @app.shcs << self
66
+ @shows = true
67
+ self
68
+ end
69
+
70
+ def toggle
71
+ @app.shcs.delete self
72
+ @app.shcs << self
73
+ @shows = !@shows
74
+ self
75
+ end
76
+
77
+ def clear
78
+ @app.mccs.delete(self); @app.mrcs.delete(self); @app.mmcs.delete(self)
79
+ case self
80
+ when Button, EditLine, EditBox, ListBox
81
+ @app.cslot.contents.delete self
82
+ remove
83
+ else @real.clear
84
+ end
85
+ end
86
+
87
+ def positioning x, y, max
88
+ if parent.is_a?(Flow) and x + @width <= parent.left + parent.width
89
+ move3 x + parent.margin_left, max.top + parent.margin_top
90
+ max = self if max.height < @height
91
+ else
92
+ move3 parent.left + parent.margin_left, max.top + max.height + parent.margin_top
93
+ max = self
94
+ end
95
+ max
96
+ end
97
+
98
+ def click &blk
99
+ @click_proc = blk
100
+ @app.mccs << self
101
+ end
102
+
103
+ def release &blk
104
+ @release_proc = blk
105
+ @app.mrcs << self
106
+ end
107
+
108
+ def hover &blk
109
+ @hover_proc = blk
110
+ (@app.mhcs << self) unless @app.mhcs.include? self
111
+ end
112
+
113
+ def leave &blk
114
+ @leave_proc = blk
115
+ (@app.mhcs << self) unless @app.mhcs.include? self
116
+ end
117
+
118
+ def style args
119
+ clear
120
+ @args[:nocontrol] = @args[:noorder] = true
121
+ m = self.class.to_s.downcase[7..-1]
122
+ args = @args.merge args
123
+ blk = args[:block]
124
+ @real = @app.send(m, args, &blk).real
125
+ end
126
+ end
127
+
128
+ class Image < Basic; end
129
+ class Button < Basic; end
130
+
131
+ class Pattern < Basic
132
+ def move2 x, y
133
+ return if @hided
134
+ clear if @real
135
+ @left, @top, @width, @height = parent.left, parent.top, parent.width, parent.height
136
+ @width = @args[:width] unless @args[:width].zero?
137
+ @height = @args[:height] unless @args[:height].zero?
138
+ m = self.class.to_s.downcase[7..-1]
139
+ args = eval "{#{@args.keys.map{|k| "#{k}: @#{k}"}.join(', ')}}"
140
+ args = [@pattern, args.merge({create_real: true, nocontrol: true})]
141
+ pt = @app.send(m, *args)
142
+ @real = pt.real
143
+ @width, @height = 0, 0
144
+ end
145
+ end
146
+ class Background < Pattern; end
147
+ class Border < Pattern; end
148
+
149
+ class ShapeBase < Basic; end
150
+ class Shape < ShapeBase; end
151
+ class Rect < ShapeBase; end
152
+ class Oval < ShapeBase; end
153
+ class Line < ShapeBase; end
154
+ class Star < ShapeBase; end
155
+
156
+ class TextBlock < Basic
157
+ def initialize args
158
+ super
159
+ @app.mlcs << self unless @real
160
+ end
161
+
162
+ def text
163
+ @args[:markup].gsub(/\<.*?>/, '')
164
+ end
165
+
166
+ def text= s
167
+ clear if @real
168
+ @width = (@left + parent.width <= @app.width) ? parent.width : @app.width - @left
169
+ @height = 20 if @height.zero?
170
+ m = self.class.to_s.downcase[7..-1]
171
+ args = [s, @args.merge({left: @left, top: @top, width: @width, height: @height, create_real: true, nocontrol: true})]
172
+ tb = @app.send(m, *args)
173
+ @real, @height, @args[:markup] = tb.real, tb.height, tb.markup
174
+ end
175
+
176
+ alias :replace :text=
177
+
178
+ def positioning x, y, max
179
+ self.text = @args[:markup]
180
+ super
181
+ end
182
+
183
+ def move2 x, y
184
+ self.text = @args[:markup]
185
+ super
186
+ end
187
+ end
188
+
189
+ class Banner < TextBlock; end
190
+ class Title < TextBlock; end
191
+ class Subtitle < TextBlock; end
192
+ class Tagline < TextBlock; end
193
+ class Caption < TextBlock; end
194
+ class Para < TextBlock; end
195
+ class Inscription < TextBlock; end
196
+
197
+ class EditLine < Basic
198
+ def text
199
+ @real.text
200
+ end
201
+
202
+ def text=(s)
203
+ @real.text = s
204
+ end
205
+
206
+ def move2 x, y
207
+ @app.canvas.move @real, x, y
208
+ move3 x, y
209
+ end
210
+ end
211
+
212
+ class EditBox < Basic
213
+ def text
214
+ @textview.buffer.text
215
+ end
216
+
217
+ def text=(s)
218
+ @textview.buffer.text = s
219
+ end
220
+
221
+ def move2 x, y
222
+ @app.canvas.move @real, x, y
223
+ move3 x, y
224
+ end
225
+ end
226
+
227
+ class ListBox < Basic
228
+ def text
229
+ @items[@real.active]
230
+ end
231
+ end
232
+
233
+ class Progress < Basic
234
+ def fraction
235
+ real.fraction
236
+ end
237
+
238
+ def fraction= n
239
+ real.fraction = n
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,150 @@
1
+ class Shoes
2
+ colors = [
3
+ [:aliceblue, 240, 248, 255],
4
+ [:antiquewhite, 250, 235, 215],
5
+ [:aqua, 0, 255, 255],
6
+ [:aquamarine, 127, 255, 212],
7
+ [:azure, 240, 255, 255],
8
+ [:beige, 245, 245, 220],
9
+ [:bisque, 255, 228, 196],
10
+ [:black, 0, 0, 0],
11
+ [:blanchedalmond, 255, 235, 205],
12
+ [:blue, 0, 0, 255],
13
+ [:blueviolet, 138, 43, 226],
14
+ [:brown, 165, 42, 42],
15
+ [:burlywood, 222, 184, 135],
16
+ [:cadetblue, 95, 158, 160],
17
+ [:chartreuse, 127, 255, 0],
18
+ [:chocolate, 210, 105, 30],
19
+ [:coral, 255, 127, 80],
20
+ [:cornflowerblue, 100, 149, 237],
21
+ [:cornsilk, 255, 248, 220],
22
+ [:crimson, 220, 20, 60],
23
+ [:cyan, 0, 255, 255],
24
+ [:darkblue, 0, 0, 139],
25
+ [:darkcyan, 0, 139, 139],
26
+ [:darkgoldenrod, 184, 134, 11],
27
+ [:darkgray, 169, 169, 169],
28
+ [:darkgreen, 0, 100, 0],
29
+ [:darkkhaki, 189, 183, 107],
30
+ [:darkmagenta, 139, 0, 139],
31
+ [:darkolivegreen, 85, 107, 47],
32
+ [:darkorange, 255, 140, 0],
33
+ [:darkorchid, 153, 50, 204],
34
+ [:darkred, 139, 0, 0],
35
+ [:darksalmon, 233, 150, 122],
36
+ [:darkseagreen, 143, 188, 143],
37
+ [:darkslateblue, 72, 61, 139],
38
+ [:darkslategray, 47, 79, 79],
39
+ [:darkturquoise, 0, 206, 209],
40
+ [:darkviolet, 148, 0, 211],
41
+ [:deeppink, 255, 20, 147],
42
+ [:deepskyblue, 0, 191, 255],
43
+ [:dimgray, 105, 105, 105],
44
+ [:dodgerblue, 30, 144, 255],
45
+ [:firebrick, 178, 34, 34],
46
+ [:floralwhite, 255, 250, 240],
47
+ [:forestgreen, 34, 139, 34],
48
+ [:fuchsia, 255, 0, 255],
49
+ [:gainsboro, 220, 220, 220],
50
+ [:ghostwhite, 248, 248, 255],
51
+ [:gold, 255, 215, 0],
52
+ [:goldenrod, 218, 165, 32],
53
+ [:gray, 128, 128, 128],
54
+ [:green, 0, 128, 0],
55
+ [:greenyellow, 173, 255, 47],
56
+ [:honeydew, 240, 255, 240],
57
+ [:hotpink, 255, 105, 180],
58
+ [:indianred, 205, 92, 92],
59
+ [:indigo, 75, 0, 130],
60
+ [:ivory, 255, 255, 240],
61
+ [:khaki, 240, 230, 140],
62
+ [:lavender, 230, 230, 250],
63
+ [:lavenderblush, 255, 240, 245],
64
+ [:lawngreen, 124, 252, 0],
65
+ [:lemonchiffon, 255, 250, 205],
66
+ [:lightblue, 173, 216, 230],
67
+ [:lightcoral, 240, 128, 128],
68
+ [:lightcyan, 224, 255, 255],
69
+ [:lightgoldenrodyellow, 250, 250, 210],
70
+ [:lightgreen, 144, 238, 144],
71
+ [:lightgrey, 211, 211, 211],
72
+ [:lightpink, 255, 182, 193],
73
+ [:lightsalmon, 255, 160, 122],
74
+ [:lightseagreen, 32, 178, 170],
75
+ [:lightskyblue, 135, 206, 250],
76
+ [:lightslategray, 119, 136, 153],
77
+ [:lightsteelblue, 176, 196, 222],
78
+ [:lightyellow, 255, 255, 224],
79
+ [:lime, 0, 255, 0],
80
+ [:limegreen, 50, 205, 50],
81
+ [:linen, 250, 240, 230],
82
+ [:magenta, 255, 0, 255],
83
+ [:maroon, 128, 0, 0],
84
+ [:mediumaquamarine, 102, 205, 170],
85
+ [:mediumblue, 0, 0, 205],
86
+ [:mediumorchid, 186, 85, 211],
87
+ [:mediumpurple, 147, 112, 219],
88
+ [:mediumseagreen, 60, 179, 113],
89
+ [:mediumslateblue, 123, 104, 238],
90
+ [:mediumspringgreen, 0, 250, 154],
91
+ [:mediumturquoise, 72, 209, 204],
92
+ [:mediumvioletred, 199, 21, 133],
93
+ [:midnightblue, 25, 25, 112],
94
+ [:mintcream, 245, 255, 250],
95
+ [:mistyrose, 255, 228, 225],
96
+ [:moccasin, 255, 228, 181],
97
+ [:navajowhite, 255, 222, 173],
98
+ [:navy, 0, 0, 128],
99
+ [:oldlace, 253, 245, 230],
100
+ [:olive, 128, 128, 0],
101
+ [:olivedrab, 107, 142, 35],
102
+ [:orange, 255, 165, 0],
103
+ [:orangered, 255, 69, 0],
104
+ [:orchid, 218, 112, 214],
105
+ [:palegoldenrod, 238, 232, 170],
106
+ [:palegreen, 152, 251, 152],
107
+ [:paleturquoise, 175, 238, 238],
108
+ [:palevioletred, 219, 112, 147],
109
+ [:papayawhip, 255, 239, 213],
110
+ [:peachpuff, 255, 218, 185],
111
+ [:peru, 205, 133, 63],
112
+ [:pink, 255, 192, 203],
113
+ [:plum, 221, 160, 221],
114
+ [:powderblue, 176, 224, 230],
115
+ [:purple, 128, 0, 128],
116
+ [:red, 255, 0, 0],
117
+ [:rosybrown, 188, 143, 143],
118
+ [:royalblue, 65, 105, 225],
119
+ [:saddlebrown, 139, 69, 19],
120
+ [:salmon, 250, 128, 114],
121
+ [:sandybrown, 244, 164, 96],
122
+ [:seagreen, 46, 139, 87],
123
+ [:seashell, 255, 245, 238],
124
+ [:sienna, 160, 82, 45],
125
+ [:silver, 192, 192, 192],
126
+ [:skyblue, 135, 206, 235],
127
+ [:slateblue, 106, 90, 205],
128
+ [:slategray, 112, 128, 144],
129
+ [:snow, 255, 250, 250],
130
+ [:springgreen, 0, 255, 127],
131
+ [:steelblue, 70, 130, 180],
132
+ [:tan, 210, 180, 140],
133
+ [:teal, 0, 128, 128],
134
+ [:thistle, 216, 191, 216],
135
+ [:tomato, 255, 99, 71],
136
+ [:turquoise, 64, 224, 208],
137
+ [:violet, 238, 130, 238],
138
+ [:wheat, 245, 222, 179],
139
+ [:white, 255, 255, 255],
140
+ [:whitesmoke, 245, 245, 245],
141
+ [:yellow, 255, 255, 0],
142
+ [:yellowgreen, 154, 205, 50],
143
+ ]
144
+
145
+ App.class_eval do
146
+ colors.each{|color| define_method(color[0]){[color[1]/255.0, color[2]/255.0, color[3]/255.0]}}
147
+ end
148
+ App::COLORS = {}
149
+ colors.each{|c, r, g, b| App::COLORS[c] = [r, g, b]}
150
+ end
@@ -0,0 +1,26 @@
1
+ class Shoes
2
+ class Download
3
+ def initialize name, args, &blk
4
+ require 'open-uri'
5
+ Thread.new do
6
+ open name,
7
+ content_length_proc: lambda{|len| @content_length, @started = len, true},
8
+ progress_proc: lambda{|size| @progress = size} do |sio|
9
+ open(args[:save], 'wb'){|fw| fw.print sio.read} if args[:save]
10
+ blk[sio] if blk
11
+ @finished = true
12
+ end
13
+ end
14
+ end
15
+
16
+ attr_reader :progress, :content_length
17
+
18
+ def started?
19
+ @started
20
+ end
21
+
22
+ def finished?
23
+ @finished
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,171 @@
1
+ class Manual < Shoes
2
+ url '/', :index
3
+ url '/manual/(\d+)', :index
4
+
5
+ def index pnum = 0
6
+ font LANG == 'ja' ? 'MS UI Gothic' : 'Arial'
7
+ style Link, underline: false, weight: 'bold'
8
+ style LinkHover, stroke: '#06E'
9
+ manual *get_title_and_desc(pnum.to_i)
10
+ end
11
+
12
+ def get_title_and_desc pnum
13
+ chapter, section = PNUMS[pnum]
14
+ if section
15
+ [pnum, DOCS[chapter][1][:sections][section][1][:title],
16
+ DOCS[chapter][1][:sections][section][1][:description],
17
+ DOCS[chapter][1][:sections][section][1][:methods]]
18
+ else
19
+ [pnum, DOCS[chapter][0], DOCS[chapter][1][:description], []]
20
+ end
21
+ end
22
+
23
+ def table_of_contents
24
+ PNUMS.map.with_index do |e, pnum|
25
+ chapter, section = e
26
+ title = section ? DOCS[chapter][1][:sections][section][1][:title] : DOCS[chapter][0]
27
+ title = title.sub('The', '').split(' ').first
28
+ section ? [' ', link(title){visit "/manual/#{pnum}"}, "\n"] : [link(fg(title, darkgreen)){visit "/manual/#{pnum}"}, "\n"]
29
+ end.flatten
30
+ end
31
+
32
+ def manual pnum, docs_title, docs_description, docs_methods
33
+ flow do
34
+ background tr_color("#ddd")..white, angle: 90
35
+ background black..green, height: 90
36
+ para fg("The Green Shoes Manual", gray), left: 120, top: 10
37
+ title fg(docs_title, white), left: 120, top: 30, font: 'Coolvetica'
38
+ image File.join(DIR, '../static/gshoes-icon.png'), left: 5, top: -12, width: 110, height: 110, nocontrol: true
39
+
40
+ paras = mk_paras docs_description
41
+
42
+ stack{para NL * 4}
43
+ flow width: 0.2, margin_left: 10 do
44
+ para *table_of_contents
45
+ end
46
+
47
+ flow width: 0.8, margin: [10, 0, 20, 0] do
48
+ show_page paras, true
49
+ docs_methods.each do |m, d|
50
+ flow do
51
+ background rgb(60, 60, 60), curve: 5
52
+ n = m.index("\u00BB")
53
+ if n
54
+ para ' ', fg(strong(m[0...n]), white), fg(strong(m[n..-1]), rgb(160, 160, 160))
55
+ else
56
+ para ' ', fg(strong(m), white)
57
+ end
58
+ end
59
+ para
60
+ show_page mk_paras(d.gsub('&', '\u0026'))
61
+ end
62
+ para link('top'){visit "/manual/0"}, " ",
63
+ link('prev'){visit "/manual/#{(pnum-1)%PEND}"}, " ",
64
+ link('next'){visit "/manual/#{(pnum+1)%PEND}"}, " ",
65
+ link('end'){visit "/manual/#{PEND-1}"}
66
+ end
67
+ end
68
+ end
69
+
70
+ def show_page paras, intro = false
71
+ paras.each_with_index do |text, i|
72
+ if text.index CODE_RE
73
+ text.gsub CODE_RE do |lines|
74
+ lines = lines.split NL
75
+ n = lines[1] =~ /\#\!ruby/ ? 2 : 1
76
+ code = lines[n...-1].join(NL+' ')
77
+ flow do
78
+ background lightsteelblue, curve: 5
79
+ inscription link(fg('Run this', green)){instance_eval code}, margin_left: 480
80
+ para ' ', fg(code, maroon), NL
81
+ end
82
+ para
83
+ end
84
+ next
85
+ end
86
+
87
+ if text =~ /\A \* (.+)/m
88
+ $1.split(/^ \* /).each do |txt|
89
+ image File.join(DIR, '../static/gshoes-icon.png'), width: 20, height: 20
90
+ flow(width: 510){show_paragraph txt, intro, i}
91
+ end
92
+ else
93
+ show_paragraph text, intro, i
94
+ end
95
+ end
96
+ end
97
+
98
+ def show_paragraph txt, intro, i, dot = nil
99
+ txt = txt.gsub("\n", ' ').gsub(/`(.+?)`/m){fg code($1), rgb(255, 30, 0)}.
100
+ gsub(/\^(.+?)\^/m, '\1').gsub(/'''(.+?)'''/m){strong($1)}.gsub(/''(.+?)''/m){em($1)}.
101
+ gsub(/\[\[BR\]\]/i, "\n").gsub(/\[\[(\S+?)\]\]/m){link ins($1.split('.').last)}.
102
+ gsub(/\[\[(\S+?) (.+?)\]\]/m){link ins($2)}
103
+ case txt
104
+ when /\A==== (.+) ====/; caption $1, size: 24
105
+ when /\A=== (.+) ===/; tagline $1, size: 12, weight: 'bold'
106
+ when /\A== (.+) ==/; subtitle $1
107
+ when /\A= (.+) =/; title $1
108
+ when /\A\{COLORS\}/; flow{color_page}
109
+ else
110
+ para txt.gsub(IMAGE_RE, ''), NL, (intro and i.zero?) ? {size: 16} : ''
111
+ txt.gsub IMAGE_RE do
112
+ image File.join(DIR, "../static/#{$3}"), eval("{#{$2 or "margin_left: 50"}}")
113
+ para
114
+ end
115
+ end
116
+ end
117
+
118
+ def mk_paras str
119
+ str.split("\n\n") - ['']
120
+ end
121
+
122
+ def color_page
123
+ Shoes::App::COLORS.each do |color, v|
124
+ r, g, b = v
125
+ c = v.dark? ? white : black
126
+ flow width: 0.33 do
127
+ background send(color)
128
+ para fg(strong(color), c), align: 'center'
129
+ para fg("rgb(#{r}, #{g}, #{b})", c), align: 'center'
130
+ end
131
+ end
132
+ para
133
+ end
134
+
135
+ def self.load_docs path
136
+ str = IO.read(path).force_encoding("UTF-8")
137
+ (str.split(/^= (.+?) =/)[1..-1]/2).map do |k, v|
138
+ sparts = v.split(/^== (.+?) ==/)
139
+ sections = (sparts[1..-1]/2).map do |k2, v2|
140
+ meth = v2.split(/^=== (.+?) ===/)
141
+ k2t = k2[/^(?:The )?([\-\w]+)/, 1]
142
+ meth_plain = meth[0].gsub(IMAGE_RE, '')
143
+ h = {title: k2, section: k, description: meth[0], methods: (meth[1..-1]/2)}
144
+ [k2t, h]
145
+ end
146
+ h = {description: sparts[0], sections: sections, class: "toc" + k.downcase.gsub(/\W+/, '')}
147
+ [k, h]
148
+ end
149
+ end
150
+
151
+ def self.mk_page_numbers docs
152
+ pnum = []
153
+ docs.length.times do |i|
154
+ pnum << [i, nil]
155
+ docs[i][1][:sections].length.times do |j|
156
+ pnum << [i, j]
157
+ end
158
+ end
159
+ pnum
160
+ end
161
+
162
+ IMAGE_RE = /\!(\{([^}\n]+)\})?([^!\n]+\.\w+)\!/
163
+ CODE_RE = /\{{3}(?:\s*\#![^\n]+)?(.+?)\}{3}/m
164
+ NL = "\n"
165
+ LANG = $lang.downcase[0, 2]
166
+ DOCS = load_docs File.join(DIR, "../static/manual-#{LANG}.txt")
167
+ PNUMS = mk_page_numbers DOCS
168
+ PEND = PNUMS.length
169
+ end
170
+
171
+ Shoes.app title: 'The Green Shoes Manual', width: 720, height: 640