purple_shoes 0.0.126 → 0.5.149
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/ext/highlighter/common.rb +197 -0
- data/lib/ext/highlighter/lang/ruby.rb +316 -0
- data/lib/ext/highlighter/markup.rb +222 -0
- data/lib/ext/highlighter.rb +2 -0
- data/lib/purple_shoes.rb +6 -0
- data/lib/shoes/app.rb +88 -7
- data/lib/shoes/basic.rb +41 -10
- data/lib/shoes/download.rb +5 -3
- data/lib/shoes/help.rb +5 -6
- data/lib/shoes/helper_methods.rb +44 -3
- data/lib/shoes/main.rb +2 -0
- data/lib/shoes/slot.rb +27 -2
- data/lib/shoes/style.rb +6 -3
- data/samples/sample43.rb +5 -4
- data/samples/sample52.rb +33 -0
- data/snapshots/sample52.png +0 -0
- data/static/downloading.png +0 -0
- data/static/manual-en.txt +24 -33
- metadata +11 -4
@@ -0,0 +1,222 @@
|
|
1
|
+
# syntax highlighting
|
2
|
+
|
3
|
+
require_relative 'common'
|
4
|
+
|
5
|
+
module HH::Markup
|
6
|
+
|
7
|
+
TOKENIZER = HH::Syntax.load "ruby"
|
8
|
+
COLORS = {
|
9
|
+
:comment => {:stroke => "#887"},
|
10
|
+
:keyword => {:stroke => "#111"},
|
11
|
+
:method => {:stroke => "#C09", :weight => "bold"},
|
12
|
+
# :class => {:stroke => "#0c4", :weight => "bold"},
|
13
|
+
# :module => {:stroke => "#050"},
|
14
|
+
# :punct => {:stroke => "#668", :weight => "bold"},
|
15
|
+
:symbol => {:stroke => "#C30"},
|
16
|
+
:string => {:stroke => "#C90"},
|
17
|
+
:number => {:stroke => "#396" },
|
18
|
+
:regex => {:stroke => "#000", :fill => "#FFC" },
|
19
|
+
# :char => {:stroke => "#f07"},
|
20
|
+
:attribute => {:stroke => "#369" },
|
21
|
+
# :global => {:stroke => "#7FB" },
|
22
|
+
:expr => {:stroke => "#722" },
|
23
|
+
# :escape => {:stroke => "#277" }
|
24
|
+
:ident => {:stroke => "#994c99"},
|
25
|
+
:constant => {:stroke => "#630", :weight => "bold"},
|
26
|
+
:class => {:stroke => "#630", :weight => "bold"},
|
27
|
+
:matching => {:stroke => "#ff0", :weight => "bold"},
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
def highlight str, pos=nil, colors=COLORS
|
32
|
+
tokens = []
|
33
|
+
TOKENIZER.tokenize(str) do |t|
|
34
|
+
if t.group == :punct
|
35
|
+
# split punctuation into single characters tokens
|
36
|
+
# TODO: to it in the parser
|
37
|
+
tokens += t.split('').map{|s| HH::Syntax::Token.new(s, :punct)}
|
38
|
+
else
|
39
|
+
# add token as is
|
40
|
+
tokens << t
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
res = []
|
45
|
+
tokens.each do |token|
|
46
|
+
res <<
|
47
|
+
if colors[token.group]
|
48
|
+
#span(token, colors[token.group])
|
49
|
+
tmp = fg(token, tr_color(colors[token.group][:stroke]))
|
50
|
+
colors[token.group][:fill] ? bg(tmp, tr_color(colors[token.group][:fill])) : tmp
|
51
|
+
elsif colors[:any]
|
52
|
+
#span(token, colors[:any])
|
53
|
+
tmp = fg(token, tr_color(colors[:any][:stroke]))
|
54
|
+
colors[:any][:fill] ? bg(tmp, tr_color(colors[:any][:fill])) : tmp
|
55
|
+
else
|
56
|
+
token
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
if pos.nil? or pos < 0
|
61
|
+
return res
|
62
|
+
end
|
63
|
+
|
64
|
+
token_index, matching_index = matching_token(tokens, pos)
|
65
|
+
|
66
|
+
if token_index
|
67
|
+
#res[token_index] = span(tokens[token_index], colors[:matching])
|
68
|
+
tmp = fg(tokens[token_index], tr_color(colors[:matching][:stroke]))
|
69
|
+
res[token_index] = colors[:matching][:fill] ? bg(tmp, tr_color(colors[:matching][:fill])) : tmp
|
70
|
+
if matching_index
|
71
|
+
#res[matching_index] = span(tokens[matching_index], colors[:matching])
|
72
|
+
tmp = fg(tokens[matching_index], tr_color(colors[:matching][:stroke]))
|
73
|
+
res[matching_index] = colors[:matching][:fill] ? bg(tmp, tr_color(colors[:matching][:fill])) : tmp
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
res
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def matching_token(tokens, pos)
|
82
|
+
curr_pos = 0
|
83
|
+
token_index = nil
|
84
|
+
tokens.each_with_index do |t, i|
|
85
|
+
curr_pos += t.size
|
86
|
+
if token_index.nil? and curr_pos >= pos
|
87
|
+
token_index = i
|
88
|
+
break
|
89
|
+
end
|
90
|
+
end
|
91
|
+
if token_index.nil? then return nil end
|
92
|
+
|
93
|
+
match = matching_token_at_index(tokens, token_index);
|
94
|
+
if match.nil? and curr_pos == pos and token_index < tokens.size-1
|
95
|
+
# try the token before the cursor, instead of the one after
|
96
|
+
token_index += 1
|
97
|
+
match = matching_token_at_index(tokens, token_index)
|
98
|
+
end
|
99
|
+
|
100
|
+
if match
|
101
|
+
[token_index, match]
|
102
|
+
else
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def matching_token_at_index(tokens, index)
|
109
|
+
starts, ends, direction = matching_tokens(tokens, index)
|
110
|
+
if starts.nil?
|
111
|
+
return nil
|
112
|
+
end
|
113
|
+
|
114
|
+
stack_level = 1
|
115
|
+
index += direction
|
116
|
+
while index >= 0 and index < tokens.size
|
117
|
+
# TODO separate space in the tokenizer
|
118
|
+
t = tokens[index].gsub(/\s/, '')
|
119
|
+
if ends.include?(t) and not as_modifier?(tokens, index)
|
120
|
+
stack_level -= 1
|
121
|
+
return index if stack_level == 0
|
122
|
+
elsif starts.include?(t) and not as_modifier?(tokens, index)
|
123
|
+
stack_level += 1
|
124
|
+
end
|
125
|
+
index += direction
|
126
|
+
end
|
127
|
+
# no matching token found
|
128
|
+
return nil
|
129
|
+
end
|
130
|
+
|
131
|
+
# returns an array of tokens matching and the direction
|
132
|
+
def matching_tokens(tokens, index)
|
133
|
+
# TODO separate space in the tokenizer
|
134
|
+
token = tokens[index].gsub(/\s/, '')
|
135
|
+
starts = [token]
|
136
|
+
if OPEN_BRACKETS[token]
|
137
|
+
direction = 1
|
138
|
+
ends = [OPEN_BRACKETS[token]]
|
139
|
+
elsif CLOSE_BRACKETS[token]
|
140
|
+
direction = -1
|
141
|
+
ends = [CLOSE_BRACKETS[token]]
|
142
|
+
elsif OPEN_BLOCK.include?(token)
|
143
|
+
if as_modifier?(tokens, index)
|
144
|
+
return nil
|
145
|
+
end
|
146
|
+
direction = 1
|
147
|
+
ends = ['end']
|
148
|
+
starts = OPEN_BLOCK
|
149
|
+
elsif token == 'end'
|
150
|
+
direction = -1
|
151
|
+
ends = OPEN_BLOCK
|
152
|
+
else
|
153
|
+
return nil
|
154
|
+
end
|
155
|
+
|
156
|
+
[starts, ends, direction]
|
157
|
+
end
|
158
|
+
|
159
|
+
def as_modifier?(tokens, index)
|
160
|
+
|
161
|
+
if not MODIFIERS.include? tokens[index].gsub(/\s/, '')
|
162
|
+
return false
|
163
|
+
end
|
164
|
+
|
165
|
+
index -= 1
|
166
|
+
# find last index before the token that is no space
|
167
|
+
index -= 1 while index >= 0 and tokens[index] =~ /\A[ \t]*\z/
|
168
|
+
|
169
|
+
if index < 0
|
170
|
+
# first character of the string
|
171
|
+
false
|
172
|
+
elsif tokens[index] =~ /\n[ \t]*\Z/
|
173
|
+
# first token of the line
|
174
|
+
false
|
175
|
+
elsif tokens[index].group == :punct
|
176
|
+
# preceded by a punctuation token on the same line
|
177
|
+
i = tokens[index].rindex(/\S/)
|
178
|
+
punc = tokens[index][i, 1]
|
179
|
+
# true if the preceeding statement was terminating
|
180
|
+
not NON_TERMINATING.include?(punc)
|
181
|
+
else
|
182
|
+
# preceded by a non punctuation token on the same line
|
183
|
+
true
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
OPEN_BRACKETS = {
|
189
|
+
'{' => '}',
|
190
|
+
'(' => ')',
|
191
|
+
'[' => ']',
|
192
|
+
}
|
193
|
+
|
194
|
+
#close_bracket = {}
|
195
|
+
#OPEN_BRACKETS.each{|open, close| opens_bracket[close] = open}
|
196
|
+
#CLOSE_BRACKETS = opens_bracket
|
197
|
+
# the following is more readable :)
|
198
|
+
CLOSE_BRACKETS = {
|
199
|
+
'}' => '{',
|
200
|
+
')' => '(',
|
201
|
+
']' => '[',
|
202
|
+
}
|
203
|
+
|
204
|
+
BRACKETS = CLOSE_BRACKETS.keys + OPEN_BRACKETS.keys
|
205
|
+
|
206
|
+
OPEN_BLOCK = [
|
207
|
+
'def',
|
208
|
+
'class',
|
209
|
+
'module',
|
210
|
+
'do',
|
211
|
+
'if',
|
212
|
+
'unless',
|
213
|
+
'while',
|
214
|
+
'until',
|
215
|
+
'begin',
|
216
|
+
'for'
|
217
|
+
]
|
218
|
+
|
219
|
+
MODIFIERS = %w[if unless while until]
|
220
|
+
|
221
|
+
NON_TERMINATING = %w{+ - * / , . = ~ < > ( [}
|
222
|
+
end
|
data/lib/purple_shoes.rb
CHANGED
@@ -22,6 +22,7 @@ module Shoes
|
|
22
22
|
PAGE_UP PAGE_DOWN HOME END INSERT
|
23
23
|
F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15].each{|k| KEY_NAMES[eval("Swt::SWT::#{k}")] = k}
|
24
24
|
KEY_NAMES[Swt::SWT::CR] = "\n"
|
25
|
+
LINECAP = {curve: Swt::SWT::CAP_ROUND, rect: Swt::SWT::CAP_FLAT, project: Swt::SWT::CAP_SQUARE}
|
25
26
|
COLORS = {}
|
26
27
|
end
|
27
28
|
|
@@ -31,6 +32,9 @@ module Swt
|
|
31
32
|
include_package 'org.eclipse.swt.widgets'
|
32
33
|
include_package 'org.eclipse.swt.graphics'
|
33
34
|
include_package 'org.eclipse.swt.events'
|
35
|
+
include_package 'org.eclipse.swt.dnd'
|
36
|
+
import java.awt.datatransfer.StringSelection
|
37
|
+
import java.awt.Toolkit
|
34
38
|
end
|
35
39
|
|
36
40
|
class Object
|
@@ -53,3 +57,5 @@ require_relative 'shoes/download'
|
|
53
57
|
require_relative 'shoes/manual'
|
54
58
|
|
55
59
|
require_relative 'plugins/video'
|
60
|
+
|
61
|
+
autoload :HH, File.join(Shoes::DIR, 'ext/highlighter')
|
data/lib/shoes/app.rb
CHANGED
@@ -6,6 +6,15 @@ class Shoes
|
|
6
6
|
args.each do |k, v|
|
7
7
|
instance_variable_set "@#{k}", v
|
8
8
|
end
|
9
|
+
|
10
|
+
win_title = @owner.instance_variable_get('@title')
|
11
|
+
class << @owner; self end.
|
12
|
+
class_eval do
|
13
|
+
define_method :inspect do
|
14
|
+
win_title or 'purple shoes'
|
15
|
+
end
|
16
|
+
end if @owner
|
17
|
+
|
9
18
|
App.class_eval do
|
10
19
|
attr_accessor *(args.keys - [:width, :height, :title])
|
11
20
|
end
|
@@ -14,9 +23,9 @@ class Shoes
|
|
14
23
|
Shoes.APPS << self
|
15
24
|
end
|
16
25
|
|
17
|
-
attr_accessor :cslot, :top_slot, :contents, :mmcs, :mscs, :order, :mouse_pos, :hided
|
26
|
+
attr_accessor :cslot, :top_slot, :contents, :mmcs, :mhcs, :mscs, :order, :mouse_pos, :hided
|
18
27
|
attr_writer :mouse_button
|
19
|
-
attr_reader :location
|
28
|
+
attr_reader :owner, :location
|
20
29
|
|
21
30
|
def visit url
|
22
31
|
if url =~ /^(http|https):\/\//
|
@@ -124,11 +133,25 @@ class Shoes
|
|
124
133
|
def image name, args={}, &blk
|
125
134
|
args = basic_attributes args
|
126
135
|
args[:rotate] ||= rotate
|
136
|
+
if name =~ /^(http|https):\/\//
|
137
|
+
tmpname = File.join(Dir.tmpdir, "__purple_shoes_#{Time.now.to_f}.png")
|
138
|
+
url, name = name, File.join(DIR, '../static/downloading.png')
|
139
|
+
end
|
127
140
|
img = Swt::Image.new Shoes.display, name
|
128
141
|
args[:full_width], args[:full_height] = img.getImageData.width, img.getImageData.height
|
129
142
|
args[:real], args[:app] = img, self
|
130
143
|
|
131
144
|
Image.new(args).tap do |s|
|
145
|
+
download url, save: tmpname do
|
146
|
+
tmp = Swt::Image.new Shoes.display, tmpname
|
147
|
+
s.real = tmp
|
148
|
+
s.full_width, s.full_height = tmp.getImageData.width, tmp.getImageData.height
|
149
|
+
if s.initials[:width].zero? and s.initials[:height].zero?
|
150
|
+
s.width, s.height = s.full_width, s.full_height
|
151
|
+
end
|
152
|
+
File.delete tmpname
|
153
|
+
end if url
|
154
|
+
|
132
155
|
pl = Swt::PaintListener.new
|
133
156
|
s.pl = pl
|
134
157
|
class << pl; self end.
|
@@ -139,11 +162,11 @@ class Shoes
|
|
139
162
|
unless s.hided
|
140
163
|
Shoes.set_rotate e.gc, *s.rotate do
|
141
164
|
if s.initials[:width].zero? and s.initials[:height].zero?
|
142
|
-
gc.drawImage
|
165
|
+
gc.drawImage s.real, s.left, s.top
|
143
166
|
else
|
144
167
|
s.width = s.full_width if s.width.zero?
|
145
168
|
s.height = s.full_height if s.height.zero?
|
146
|
-
gc.drawImage
|
169
|
+
gc.drawImage s.real, 0, 0, s.full_width, s.full_height, s.left, s.top, s.width, s.height
|
147
170
|
end
|
148
171
|
end
|
149
172
|
end
|
@@ -161,6 +184,8 @@ class Shoes
|
|
161
184
|
elsif klass == Radio then Swt::SWT::RADIO
|
162
185
|
elsif klass == Check then Swt::SWT::CHECK end
|
163
186
|
b = Swt::Button.new @cs, opt
|
187
|
+
b.setVisible false if args[:hidden]
|
188
|
+
args.delete :hidden
|
164
189
|
b.setText name if klass == Button
|
165
190
|
b.setLocation args[:left], args[:top]
|
166
191
|
if args[:width] > 0 and args[:height] > 0
|
@@ -197,6 +222,8 @@ class Shoes
|
|
197
222
|
args[:height] = h if args[:height].zero?
|
198
223
|
|
199
224
|
el = Swt::Text.new @cs, Swt::SWT::BORDER | style
|
225
|
+
el.setVisible false if args[:hidden]
|
226
|
+
args.delete :hidden
|
200
227
|
el.setText txt || args[:text].to_s
|
201
228
|
el.setSize args[:width], args[:height]
|
202
229
|
args[:real], args[:app] = el, self
|
@@ -219,6 +246,8 @@ class Shoes
|
|
219
246
|
args[:height] = 20 if args[:height].zero?
|
220
247
|
args[:items] ||= []
|
221
248
|
cb = Swt::Combo.new @cs, Swt::SWT::DROP_DOWN
|
249
|
+
cb.setVisible false if args[:hidden]
|
250
|
+
args.delete :hidden
|
222
251
|
cb.setSize args[:width], args[:height]
|
223
252
|
cb.setItems args[:items].map(&:to_s)
|
224
253
|
cb.setText args[:choose].to_s
|
@@ -273,6 +302,7 @@ class Shoes
|
|
273
302
|
args[:stroke] ||= stroke
|
274
303
|
args[:fill] ||= fill
|
275
304
|
args[:rotate] ||= rotate
|
305
|
+
args[:cap] = (LINECAP[args[:cap]] or cap)
|
276
306
|
args[:real], args[:app], args[:block] = :shape, self, blk
|
277
307
|
Shape.new(args).tap do |s|
|
278
308
|
pl = Swt::PaintListener.new
|
@@ -286,6 +316,7 @@ class Shoes
|
|
286
316
|
gc = e.gc
|
287
317
|
Shoes.dps_reset s.dps, gc
|
288
318
|
gc.setAntialias Swt::SWT::ON
|
319
|
+
gc.setLineCap s.cap
|
289
320
|
sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
|
290
321
|
Shoes.set_rotate gc, *s.rotate do
|
291
322
|
if pat2
|
@@ -320,13 +351,19 @@ class Shoes
|
|
320
351
|
args = basic_attributes args
|
321
352
|
args[:width].zero? ? (args[:width] = args[:radius] * 2) : (args[:radius] = args[:width]/2.0)
|
322
353
|
args[:height] = args[:width] if args[:height].zero?
|
354
|
+
if args[:center]
|
355
|
+
args[:left] -= args[:width] / 2
|
356
|
+
args[:top] -= args[:height] / 2
|
357
|
+
end
|
323
358
|
args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
|
324
359
|
args[:nocontrol] = args[:noorder] = true
|
325
360
|
|
326
361
|
args[:stroke] ||= stroke
|
327
362
|
args[:fill] ||= fill
|
328
363
|
args[:rotate] ||= rotate
|
364
|
+
args[:cap] = (LINECAP[args[:cap]] or cap)
|
329
365
|
args[:real], args[:app] = :shape, self
|
366
|
+
args[:angle1] = false unless args[:angle1]
|
330
367
|
Oval.new(args).tap do |s|
|
331
368
|
pl = Swt::PaintListener.new
|
332
369
|
s.pl = pl
|
@@ -337,17 +374,20 @@ class Shoes
|
|
337
374
|
gc = e.gc
|
338
375
|
Shoes.dps_reset s.dps, gc
|
339
376
|
gc.setAntialias Swt::SWT::ON
|
377
|
+
gc.setLineCap s.cap
|
340
378
|
sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
|
341
379
|
Shoes.set_rotate gc, *s.rotate do
|
342
380
|
if pat2
|
343
381
|
Shoes.set_pattern s, gc, pat2
|
344
|
-
gc.
|
382
|
+
s.angle1 ? gc.fillArc(s.left+sw, s.top+sw, s.width-sw*2, s.height-sw*2, s.angle1, s.angle2) :
|
383
|
+
gc.fillOval(s.left+sw, s.top+sw, s.width-sw*2, s.height-sw*2)
|
345
384
|
end
|
346
385
|
if pat1
|
347
386
|
Shoes.set_pattern s, gc, pat1, :Foreground
|
348
387
|
if sw > 0
|
349
388
|
gc.setLineWidth sw
|
350
|
-
gc.
|
389
|
+
s.angle1 ? gc.drawArc(s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw, s.angle1, s.angle2) :
|
390
|
+
gc.drawOval(s.left+sw/2, s.top+sw/2, s.width-sw, s.height-sw)
|
351
391
|
end
|
352
392
|
end
|
353
393
|
end
|
@@ -358,6 +398,13 @@ class Shoes
|
|
358
398
|
clickable s, &blk
|
359
399
|
end
|
360
400
|
end
|
401
|
+
|
402
|
+
def arc l, t, w, h, a1, a2, args={}
|
403
|
+
a1 = a1 * 180 / Math::PI
|
404
|
+
a2 = -a2 * 180 / Math::PI
|
405
|
+
args.merge!({angle1: a1, angle2: a2})
|
406
|
+
oval l, t, w, h, args
|
407
|
+
end
|
361
408
|
|
362
409
|
def rect *attrs, &blk
|
363
410
|
args = attrs.last.class == Hash ? attrs.pop : {}
|
@@ -368,6 +415,10 @@ class Shoes
|
|
368
415
|
else args[:left], args[:top], args[:width], args[:height] = attrs
|
369
416
|
end
|
370
417
|
args[:height] = args[:width] unless args[:height]
|
418
|
+
if args[:center]
|
419
|
+
args[:left] -= args[:width] / 2
|
420
|
+
args[:top] -= args[:height] / 2
|
421
|
+
end
|
371
422
|
args[:strokewidth] = ( args[:strokewidth] or strokewidth or 1 )
|
372
423
|
args[:curve] ||= 0
|
373
424
|
args[:nocontrol] = args[:noorder] = true
|
@@ -376,6 +427,7 @@ class Shoes
|
|
376
427
|
args[:stroke] ||= stroke
|
377
428
|
args[:fill] ||= fill
|
378
429
|
args[:rotate] ||= rotate
|
430
|
+
args[:cap] = (LINECAP[args[:cap]] or cap)
|
379
431
|
args[:real], args[:app] = :shape, self
|
380
432
|
Rect.new(args).tap do |s|
|
381
433
|
pl = Swt::PaintListener.new
|
@@ -387,6 +439,7 @@ class Shoes
|
|
387
439
|
gc = e.gc
|
388
440
|
Shoes.dps_reset s.dps, gc
|
389
441
|
gc.setAntialias Swt::SWT::ON
|
442
|
+
gc.setLineCap s.cap
|
390
443
|
sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
|
391
444
|
Shoes.set_rotate gc, *s.rotate do
|
392
445
|
if pat2
|
@@ -444,6 +497,7 @@ class Shoes
|
|
444
497
|
|
445
498
|
args[:stroke] ||= stroke
|
446
499
|
args[:rotate] ||= rotate
|
500
|
+
args[:cap] = (LINECAP[args[:cap]] or cap)
|
447
501
|
args[:real], args[:app] = :shape, self
|
448
502
|
Line.new(args).tap do |s|
|
449
503
|
pl = Swt::PaintListener.new
|
@@ -455,6 +509,7 @@ class Shoes
|
|
455
509
|
gc = e.gc
|
456
510
|
Shoes.dps_reset s.dps, gc
|
457
511
|
gc.setAntialias Swt::SWT::ON
|
512
|
+
gc.setLineCap s.cap
|
458
513
|
sw, pat = s.strokewidth, s.stroke
|
459
514
|
Shoes.set_rotate gc, *s.rotate do
|
460
515
|
if pat
|
@@ -487,6 +542,7 @@ class Shoes
|
|
487
542
|
args[:stroke] ||= stroke
|
488
543
|
args[:fill] ||= fill
|
489
544
|
args[:rotate] ||= rotate
|
545
|
+
args[:cap] = (LINECAP[args[:cap]] or cap)
|
490
546
|
args[:real], args[:app] = :shape, self
|
491
547
|
Star.new(args).tap do |s|
|
492
548
|
pl = Swt::PaintListener.new
|
@@ -498,6 +554,7 @@ class Shoes
|
|
498
554
|
gc = e.gc
|
499
555
|
Shoes.dps_reset s.dps, gc
|
500
556
|
gc.setAntialias Swt::SWT::ON
|
557
|
+
gc.setLineCap s.cap
|
501
558
|
sw, pat1, pat2 = s.strokewidth, s.stroke, s.fill
|
502
559
|
outer, inner, points, left, top = s.outer, s.inner, s.points, s.left, s.top
|
503
560
|
polygon = []
|
@@ -653,6 +710,8 @@ class Shoes
|
|
653
710
|
args[:width] ||= 150
|
654
711
|
args[:height] ||= 16
|
655
712
|
args = basic_attributes args
|
713
|
+
pb.setVisible false if args[:hidden]
|
714
|
+
args.delete :hidden
|
656
715
|
pb.setSize args[:width], args[:height]
|
657
716
|
pb.setLocation args[:left], args[:top]
|
658
717
|
args[:real], args[:app] = pb, self
|
@@ -660,7 +719,7 @@ class Shoes
|
|
660
719
|
end
|
661
720
|
|
662
721
|
def download name, args={}, &blk
|
663
|
-
Download.new name, args, &blk
|
722
|
+
Download.new self, name, args, &blk
|
664
723
|
end
|
665
724
|
|
666
725
|
def scroll_top
|
@@ -680,11 +739,24 @@ class Shoes
|
|
680
739
|
shell.getVerticalBar.getMaximum - 10
|
681
740
|
end
|
682
741
|
|
742
|
+
def clipboard
|
743
|
+
Swt::Clipboard.new(Shoes.display).getContents Swt::TextTransfer.getInstance
|
744
|
+
end
|
745
|
+
|
746
|
+
def clipboard=(str)
|
747
|
+
Swt::Toolkit.getDefaultToolkit.getSystemClipboard.setContents Swt::StringSelection.new(str), Shoes
|
748
|
+
end
|
749
|
+
|
683
750
|
def close
|
684
751
|
@shell.close
|
685
752
|
Shoes.APPS.delete self
|
686
753
|
end
|
687
754
|
|
755
|
+
def window args={}, &blk
|
756
|
+
args.merge! owner: self
|
757
|
+
Shoes.app args, &blk
|
758
|
+
end
|
759
|
+
|
688
760
|
def flush
|
689
761
|
unless @cs.isDisposed
|
690
762
|
Shoes.call_back_procs self
|
@@ -711,5 +783,14 @@ class Shoes
|
|
711
783
|
g, a = attrs
|
712
784
|
g ? rgb(g*255, g*255, g*255, a) : rgb(128, 128, 128)[0..2]
|
713
785
|
end
|
786
|
+
|
787
|
+
def cap *line_cap
|
788
|
+
@line_cap = case line_cap.first
|
789
|
+
when :curve, :rect, :project
|
790
|
+
LINECAP[line_cap.first]
|
791
|
+
else
|
792
|
+
@line_cap ||= LINECAP[:rect]
|
793
|
+
end
|
794
|
+
end
|
714
795
|
end
|
715
796
|
end
|
data/lib/shoes/basic.rb
CHANGED
@@ -3,6 +3,8 @@ class Shoes
|
|
3
3
|
include Mod
|
4
4
|
def initialize args
|
5
5
|
@initials = args
|
6
|
+
@hided = true if args[:hidden]
|
7
|
+
args.delete :hidden
|
6
8
|
args.each do |k, v|
|
7
9
|
instance_variable_set "@#{k}", v
|
8
10
|
end
|
@@ -39,10 +41,6 @@ class Shoes
|
|
39
41
|
attr_reader :args, :initials
|
40
42
|
attr_accessor :parent, :pl, :ln, :dps
|
41
43
|
|
42
|
-
def hided
|
43
|
-
@app.hided or @hided
|
44
|
-
end
|
45
|
-
|
46
44
|
def move x, y
|
47
45
|
@app.cslot.contents -= [self]
|
48
46
|
move3 x, y
|
@@ -61,6 +59,10 @@ class Shoes
|
|
61
59
|
@left, @top = x, y
|
62
60
|
end
|
63
61
|
|
62
|
+
def center_at x, y
|
63
|
+
[x - (@width / 2), y - (@height / 2)]
|
64
|
+
end
|
65
|
+
|
64
66
|
def positioning x, y, max
|
65
67
|
if parent.is_a?(Flow) and x + @width <= parent.left + parent.width
|
66
68
|
move3 x + parent.margin_left, max.top + parent.margin_top
|
@@ -82,6 +84,7 @@ class Shoes
|
|
82
84
|
@dps.clear
|
83
85
|
@parent.contents -= [self]
|
84
86
|
@app.mscs -= [self]
|
87
|
+
@app.mhcs -= [self]
|
85
88
|
hide
|
86
89
|
end
|
87
90
|
end
|
@@ -154,8 +157,18 @@ class Shoes
|
|
154
157
|
class Border < Pattern; end
|
155
158
|
|
156
159
|
class ShapeBase < Basic; end
|
157
|
-
class Rect < ShapeBase
|
158
|
-
|
160
|
+
class Rect < ShapeBase
|
161
|
+
def move3 x, y
|
162
|
+
x, y = center_at(x, y) if @center
|
163
|
+
super
|
164
|
+
end
|
165
|
+
end
|
166
|
+
class Oval < ShapeBase
|
167
|
+
def move3 x, y
|
168
|
+
x, y = center_at(x, y) if @center
|
169
|
+
super
|
170
|
+
end
|
171
|
+
end
|
159
172
|
class Line < ShapeBase; end
|
160
173
|
class Star < ShapeBase
|
161
174
|
def move3 x, y
|
@@ -247,7 +260,13 @@ class Shoes
|
|
247
260
|
end
|
248
261
|
end
|
249
262
|
|
250
|
-
class Button < Native
|
263
|
+
class Button < Native
|
264
|
+
def click &blk
|
265
|
+
@real.addSelectionListener do |e|
|
266
|
+
self.class == Button ? blk[self] : (blk[self] if @real.getSelection)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
251
270
|
class ToggleButton < Button
|
252
271
|
def checked?
|
253
272
|
real.getSelection
|
@@ -260,9 +279,21 @@ class Shoes
|
|
260
279
|
class Radio < ToggleButton; end
|
261
280
|
class Check < ToggleButton; end
|
262
281
|
|
263
|
-
class EditLine < Native
|
264
|
-
|
265
|
-
|
282
|
+
class EditLine < Native
|
283
|
+
def change &blk
|
284
|
+
@real.addModifyListener{|e| blk[self]}
|
285
|
+
end
|
286
|
+
end
|
287
|
+
class EditBox < Native
|
288
|
+
def change &blk
|
289
|
+
@real.addModifyListener{|e| blk[self]}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
class ListBox < Native
|
293
|
+
def change &blk
|
294
|
+
@real.addSelectionListener{|e| blk[self]}
|
295
|
+
end
|
296
|
+
end
|
266
297
|
class Progress < Native
|
267
298
|
def fraction
|
268
299
|
@real.isDisposed ? 0 : real.getSelection / 100.0
|
data/lib/shoes/download.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
class Shoes
|
2
2
|
class Download
|
3
|
-
def initialize name, args, &blk
|
3
|
+
def initialize app, name, args, &blk
|
4
4
|
require 'open-uri'
|
5
5
|
Thread.new do
|
6
6
|
open name,
|
7
7
|
content_length_proc: lambda{|len| @content_length, @started = len, true},
|
8
8
|
progress_proc: lambda{|size| @progress = size} do |sio|
|
9
9
|
open(args[:save], 'wb'){|fw| fw.print sio.read} if args[:save]
|
10
|
-
|
11
|
-
@finished = true
|
10
|
+
@finished, @sio = true, sio
|
12
11
|
end
|
13
12
|
end
|
13
|
+
a = app.animate do
|
14
|
+
(a.stop; blk[@sio]) if @finished
|
15
|
+
end if blk
|
14
16
|
end
|
15
17
|
|
16
18
|
attr_reader :progress, :content_length
|
data/lib/shoes/help.rb
CHANGED
@@ -4,10 +4,9 @@ require 'nkf'
|
|
4
4
|
class Manual < Shoes
|
5
5
|
url '/', :index
|
6
6
|
url '/manual/(\d+)', :index
|
7
|
-
#url '/mk_search_page', :mk_search_page
|
8
7
|
|
9
8
|
include Hpricot
|
10
|
-
|
9
|
+
include HH::Markup
|
11
10
|
|
12
11
|
def index pnum = 0
|
13
12
|
font LANG == 'ja' ? 'MS UI Gothic' : 'Arial'
|
@@ -90,7 +89,7 @@ class Manual < Shoes
|
|
90
89
|
end
|
91
90
|
end
|
92
91
|
para NL
|
93
|
-
show_page mk_paras(d
|
92
|
+
show_page mk_paras(d), false, term
|
94
93
|
end
|
95
94
|
end
|
96
95
|
|
@@ -107,8 +106,7 @@ class Manual < Shoes
|
|
107
106
|
if _code.include? 'te-su-to'
|
108
107
|
para fg(code(' ' + _code), maroon), NL, margin: [-10, 10, 0, 20]
|
109
108
|
else
|
110
|
-
|
111
|
-
para fg(code(' ' + _code), blueviolet), NL, margin: [-10, 10, 0, 20]
|
109
|
+
para *highlight(' ' + _code, nil).map{|e| code e}, NL, margin: [-10, 10, 0, 20]
|
112
110
|
end
|
113
111
|
end
|
114
112
|
para NL
|
@@ -171,7 +169,7 @@ class Manual < Shoes
|
|
171
169
|
COLORS.each do |color, v|
|
172
170
|
r, g, b = v
|
173
171
|
c = v.dark? ? white : black
|
174
|
-
flow width: 0.33 do
|
172
|
+
flow width: 0.33, height: 55, margin_top: 5 do
|
175
173
|
background send(color)
|
176
174
|
para fg(strong(color), c), align: 'center'
|
177
175
|
para fg("rgb(#{r}, #{g}, #{b})", c), align: 'center'
|
@@ -203,6 +201,7 @@ class Manual < Shoes
|
|
203
201
|
end
|
204
202
|
|
205
203
|
def find_pnum page
|
204
|
+
return 999 if page == 'Search'
|
206
205
|
TOC_LIST.each_with_index do |e, i|
|
207
206
|
title, section = e
|
208
207
|
return i if title == page
|