green_shoes 0.129.0

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