1 #
2 # tk/canvastag.rb - methods for treating canvas tags
3 #
4 require 'tk'
5 require 'tk/tagfont'
6
7 module TkcTagAccess
8 include TkComm
9 include TkTreatTagFont
10 end
11
12 require 'tk/canvas'
13
14 module TkcTagAccess
15 def addtag(tag)
16 @c.addtag(tag, 'withtag', @id)
17 self
18 end
19
20 def bbox
21 @c.bbox(@id)
22 end
23
24 #def bind(seq, cmd=Proc.new, *args)
25 # @c.itembind(@id, seq, cmd, *args)
26 # self
27 #end
28 def bind(seq, *args)
29 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
30 if TkComm._callback_entry?(args[0]) || !block_given?
31 cmd = args.shift
32 else
33 cmd = Proc.new
34 end
35 @c.itembind(@id, seq, cmd, *args)
36 self
37 end
38
39 #def bind_append(seq, cmd=Proc.new, *args)
40 # @c.itembind_append(@id, seq, cmd, *args)
41 # self
42 #end
43 def bind_append(seq, *args)
44 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
45 if TkComm._callback_entry?(args[0]) || !block_given?
46 cmd = args.shift
47 else
48 cmd = Proc.new
49 end
50 @c.itembind_append(@id, seq, cmd, *args)
51 self
52 end
53
54 def bind_remove(seq)
55 @c.itembind_remove(@id, seq)
56 self
57 end
58
59 def bindinfo(seq=nil)
60 @c.itembindinfo(@id, seq)
61 end
62
63 def cget(option)
64 @c.itemcget(@id, option)
65 end
66 def cget_strict(option)
67 @c.itemcget_strict(@id, option)
68 end
69
70 def configure(key, value=None)
71 @c.itemconfigure(@id, key, value)
72 self
73 end
74 # def configure(keys)
75 # @c.itemconfigure @id, keys
76 # end
77
78 def configinfo(key=nil)
79 @c.itemconfiginfo(@id, key)
80 end
81
82 def current_configinfo(key=nil)
83 @c.current_itemconfiginfo(@id, key)
84 end
85
86 def coords(*args)
87 @c.coords(@id, *args)
88 end
89
90 def dchars(first, last=None)
91 @c.dchars(@id, first, last)
92 self
93 end
94
95 def dtag(tag_to_del=None)
96 @c.dtag(@id, tag_to_del)
97 self
98 end
99 alias deltag dtag
100
101 def find
102 @c.find('withtag', @id)
103 end
104 alias list find
105
106 def focus
107 @c.itemfocus(@id)
108 end
109
110 def gettags
111 @c.gettags(@id)
112 end
113
114 def icursor(index)
115 @c.icursor(@id, index)
116 self
117 end
118
119 def index(idx)
120 @c.index(@id, idx)
121 end
122
123 def insert(beforethis, string)
124 @c.insert(@id, beforethis, string)
125 self
126 end
127
128 def lower(belowthis=None)
129 @c.lower(@id, belowthis)
130 self
131 end
132
133 def move(xamount, yamount)
134 @c.move(@id, xamount, yamount)
135 self
136 end
137
138 def raise(abovethis=None)
139 @c.raise(@id, abovethis)
140 self
141 end
142
143 def scale(xorigin, yorigin, xscale, yscale)
144 @c.scale(@id, xorigin, yorigin, xscale, yscale)
145 self
146 end
147
148 def select_adjust(index)
149 @c.select('adjust', @id, index)
150 self
151 end
152 def select_from(index)
153 @c.select('from', @id, index)
154 self
155 end
156 def select_to(index)
157 @c.select('to', @id, index)
158 self
159 end
160
161 def itemtype
162 @c.itemtype(@id)
163 end
164
165 # Following operators support logical expressions of canvas tags
166 # (for Tk8.3+).
167 # If tag1.path is 't1' and tag2.path is 't2', then
168 # ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
169 # ltag = tag1 | tag2; ltag.path => "(t1)||(t2)"
170 # ltag = tag1 ^ tag2; ltag.path => "(t1)^(t2)"
171 # ltag = - tag1; ltag.path => "!(t1)"
172 def & (tag)
173 if tag.kind_of? TkObject
174 TkcTagString.new(@c, '(' + @id + ')&&(' + tag.path + ')')
175 else
176 TkcTagString.new(@c, '(' + @id + ')&&(' + tag.to_s + ')')
177 end
178 end
179
180 def | (tag)
181 if tag.kind_of? TkObject
182 TkcTagString.new(@c, '(' + @id + ')||(' + tag.path + ')')
183 else
184 TkcTagString.new(@c, '(' + @id + ')||(' + tag.to_s + ')')
185 end
186 end
187
188 def ^ (tag)
189 if tag.kind_of? TkObject
190 TkcTagString.new(@c, '(' + @id + ')^(' + tag.path + ')')
191 else
192 TkcTagString.new(@c, '(' + @id + ')^(' + tag.to_s + ')')
193 end
194 end
195
196 def -@
197 TkcTagString.new(@c, '!(' + @id + ')')
198 end
199 end
200
201 class TkcTag<TkObject
202 include TkcTagAccess
203
204 CTagID_TBL = TkCore::INTERP.create_table
205
206 (Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint]).instance_eval{
207 @mutex = Mutex.new
208 def mutex; @mutex; end
209 freeze
210 }
211
212 TkCore::INTERP.init_ip_env{
213 CTagID_TBL.mutex.synchronize{ CTagID_TBL.clear }
214 }
215
216 def TkcTag.id2obj(canvas, id)
217 cpath = canvas.path
218 CTagID_TBL.mutex.synchronize{
219 if CTagID_TBL[cpath]
220 CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
221 else
222 id
223 end
224 }
225 end
226
227 def initialize(parent, mode=nil, *args)
228 #unless parent.kind_of?(TkCanvas)
229 # fail ArgumentError, "expect TkCanvas for 1st argument"
230 #end
231 @c = parent
232 @cpath = parent.path
233 Tk_CanvasTag_ID.mutex.synchronize{
234 # @path = @id = Tk_CanvasTag_ID.join('')
235 @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
236 Tk_CanvasTag_ID[1].succ!
237 }
238 CTagID_TBL.mutex.synchronize{
239 CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
240 CTagID_TBL[@cpath][@id] = self
241 }
242 if mode
243 tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
244 end
245 end
246 def id
247 @id
248 end
249
250 def exist?
251 if @c.find_withtag(@id)
252 true
253 else
254 false
255 end
256 end
257
258 def delete
259 @c.delete @id
260 CTagID_TBL.mutex.synchronize{
261 CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
262 }
263 self
264 end
265 alias remove delete
266 alias destroy delete
267
268 def set_to_above(target)
269 @c.addtag_above(@id, target)
270 self
271 end
272 alias above set_to_above
273
274 def set_to_all
275 @c.addtag_all(@id)
276 self
277 end
278 alias all set_to_all
279
280 def set_to_below(target)
281 @c.addtag_below(@id, target)
282 self
283 end
284 alias below set_to_below
285
286 def set_to_closest(x, y, halo=None, start=None)
287 @c.addtag_closest(@id, x, y, halo, start)
288 self
289 end
290 alias closest set_to_closest
291
292 def set_to_enclosed(x1, y1, x2, y2)
293 @c.addtag_enclosed(@id, x1, y1, x2, y2)
294 self
295 end
296 alias enclosed set_to_enclosed
297
298 def set_to_overlapping(x1, y1, x2, y2)
299 @c.addtag_overlapping(@id, x1, y1, x2, y2)
300 self
301 end
302 alias overlapping set_to_overlapping
303
304 def set_to_withtag(target)
305 @c.addtag_withtag(@id, target)
306 self
307 end
308 alias withtag set_to_withtag
309 end
310
311 class TkcTagString<TkcTag
312 def self.new(parent, name, mode=nil, *args)
313 obj = nil
314 CTagID_TBL.mutex.synchronize{
315 if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
316 obj = CTagID_TBL[parent.path][name]
317 else
318 # super(parent, name, *args)
319 (obj = self.allocate).instance_eval{
320 @c = parent
321 @cpath = parent.path
322 @path = @id = name
323 CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
324 CTagID_TBL[@cpath][@id] = self
325 }
326 end
327 }
328 if obj && mode
329 tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
330 end
331 obj
332 end
333
334 def initialize(parent, name, mode=nil, *args)
335 # dummy:: not called by 'new' method
336
337 #unless parent.kind_of?(TkCanvas)
338 # fail ArgumentError, "expect TkCanvas for 1st argument"
339 #end
340 @c = parent
341 @cpath = parent.path
342 @path = @id = name
343
344 if mode
345 tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
346 end
347 end
348 end
349 TkcNamedTag = TkcTagString
350
351 class TkcTagAll<TkcTagString
352 def self.new(parent)
353 super(parent, 'all')
354 end
355 =begin
356 def initialize(parent)
357 #unless parent.kind_of?(TkCanvas)
358 # fail ArgumentError, "expect TkCanvas for 1st argument"
359 #end
360 @c = parent
361 @cpath = parent.path
362 @path = @id = 'all'
363 CTagID_TBL.mutex.synchronize{
364 CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
365 CTagID_TBL[@cpath][@id] = self
366 }
367 end
368 =end
369 end
370
371 class TkcTagCurrent<TkcTagString
372 def self.new(parent)
373 super(parent, 'current')
374 end
375 =begin
376 def initialize(parent)
377 #unless parent.kind_of?(TkCanvas)
378 # fail ArgumentError, "expect TkCanvas for 1st argument"
379 #end
380 @c = parent
381 @cpath = parent.path
382 @path = @id = 'current'
383 CTagID_TBL.mutex.synchronize{
384 CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
385 CTagID_TBL[@cpath][@id] = self
386 }
387 end
388 =end
389 end
390
391 class TkcGroup<TkcTag
392 (Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint]).instance_eval{
393 @mutex = Mutex.new
394 def mutex; @mutex; end
395 freeze
396 }
397
398 #def create_self(parent, *args)
399 def initialize(parent, *args)
400 #unless parent.kind_of?(TkCanvas)
401 # fail ArgumentError, "expect TkCanvas for 1st argument"
402 #end
403 @c = parent
404 @cpath = parent.path
405 Tk_cGroup_ID.mutex.synchronize{
406 # @path = @id = Tk_cGroup_ID.join('')
407 @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
408 Tk_cGroup_ID[1].succ!
409 }
410 CTagID_TBL.mutex.synchronize{
411 CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
412 CTagID_TBL[@cpath][@id] = self
413 }
414 include(*args) if args != []
415 end
416 #private :create_self
417
418 def include(*tags)
419 for i in tags
420 #i.addtag(@id)
421 @c.addtag_withtag(@id, i)
422 end
423 self
424 end
425 alias add include
426
427 def exclude(*tags)
428 for i in tags
429 #i.dtag(@id)
430 @c.dtag(i, @id)
431 end
432 self
433 end
434 end