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