1# 2# tkextlib/itk/incr_tk.rb 3# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) 4# 5 6require 'tk' 7require 'tk/menuspec' 8require 'tkextlib/itcl.rb' 9 10# call setup script 11require 'tkextlib/itk.rb' 12 13#TkPackage.require('Itk', '3.2') 14TkPackage.require('Itk') 15 16module Tk 17 module Itk 18 include Tk 19 extend Tk 20 21 LIBRARY = TkVarAccess.new('::itk::library') 22 23 PACKAGE_NAME = 'Itk'.freeze 24 def self.package_name 25 PACKAGE_NAME 26 end 27 28 def self.package_version 29 begin 30 TkPackage.require('Itk') 31 rescue 32 '' 33 end 34 end 35 36 def self.usual(arg, *args) 37 tk_call('::itk::usual', arg, *args) 38 end 39 40 def self.usual_names 41 list(tk_call('::itk::usual')) 42 end 43 44 ############################ 45 46 class Archetype < TkWindow 47 TkCommandNames = [].freeze 48 # WidgetClassName = 'Archetype'.freeze 49 # WidgetClassNames[WidgetClassName] = self 50 51 def self.to_eval 52 '::itk::' << self::WidgetClassName 53 end 54 55 def __destroy_hook__ 56 Tk::Itk::Component::ComponentID_TBL.delete(self.path) 57 end 58 59 #### [incr Tk] public methods 60 def component 61 simplelist(tk_send('component')) 62 end 63 64 def component_path(name) 65 window(tk_send('component', name)) 66 end 67 alias component_widget component_path 68 69 def component_invoke(name, cmd, *args) 70 window(tk_send('component', name, cmd, *args)) 71 end 72 73 def component_obj(*names) 74 names = component if names.empty? 75 names.collect{|name| Tk::Itk::Component.new(self.path, name) } 76 end 77 78 #### [incr Tk] protected methods 79=begin 80 def itk_component_add(visibility, name, create_cmds, option_cmds=None) 81 args = [] 82 visibility.each{|v| v = v.to_s; args << ( (v[0] == ?-)? v: "-#{v}" )} 83 args << '--' << name << create_cmd << option_cmds 84 tk_call('itk_component', 'add', *args) 85 end 86 87 def itk_component_delete(*names) 88 tk_call('itk_component', 'delete', *names) 89 end 90 91 def itk_initialize(keys={}) 92 tk_call('itk_initialize', keys) 93 end 94 95 def itk_option_add(*args) 96 tk_call('itk_option', 'add', *args) 97 end 98 99 def itk_option_define(name, resource, klass, init, config=None) 100 tk_call('itk_option', 'define', name, resource, klass, init, config) 101 end 102 103 def itk_option_remove(*args) 104 tk_call('itk_option', 'remove', *args) 105 end 106=end 107 end 108 109 ############################ 110 111 class Toplevel < Archetype 112 TkCommandNames = ['::itk::Toplevel'].freeze 113 WidgetClassName = 'Toplevel'.freeze 114 WidgetClassNames[WidgetClassName] ||= self 115 116 include Wm 117 include TkMenuSpec 118 119 def __strval_optkeys 120 super() << 'title' 121 end 122 private :__strval_optkeys 123 end 124 125 ############################ 126 127 class Widget < Archetype 128 TkCommandNames = ['::itk::Widget'].freeze 129 WidgetClassName = 'Widget'.freeze 130 WidgetClassNames[WidgetClassName] ||= self 131 end 132 133 134 ############################ 135 136 class Component < TkObject 137 def __cget_cmd 138 [self.master, 'component', self.name, 'cget'] 139 end 140 private :__cget_cmd 141 142 def __config_cmd 143 [self.master, 'component', self.name, 'configure'] 144 end 145 private :__config_cmd 146 147 ComponentID_TBL = TkCore::INTERP.create_table 148 149 (Itk_Component_ID = ['itk:component'.freeze, TkUtil.untrust('00000')]).instance_eval{ 150 @mutex = Mutex.new 151 def mutex; @mutex; end 152 freeze 153 } 154 155 TkCore::INTERP.init_ip_env{ 156 ComponentID_TBL.mutex.synchronize{ ComponentID_TBL.clear } 157 } 158 159 def self.id2obj(master, id) 160 if master.kind_of?(TkObject) 161 master = master.path 162 else 163 master = master.to_s 164 end 165 ComponentID_TBL.mutex.synchronize{ 166 if ComponentID_TBL.key?(master) 167 (ComponentID_TBL[master].key?(id))? ComponentID_TBL[master][id]: id 168 else 169 id 170 end 171 } 172 end 173 174 def self.new(master, component=nil) 175 if master.kind_of?(TkObject) 176 master = master.path 177 else 178 master = master.to_s 179 end 180 181 if component.kind_of?(Tk::Itk::Component) 182 component = component.name 183 elsif component 184 component = component.to_s 185 else 186 Itk_Component_ID.mutex.synchronize{ 187 component = Itk_Component_ID.join(TkCore::INTERP._ip_id_) 188 Itk_Component_ID[1].succ! 189 } 190 end 191 192 ComponentID_TBL.mutex.synchronize{ 193 if ComponentID_TBL.key?(master) 194 if ComponentID_TBL[master].key?(component) 195 return ComponentID_TBL[master][component] 196 end 197 else 198 ComponentID_TBL[master] = {} 199 end 200 } 201 202 super(master, component) 203 end 204 205 def initialize(master, component) 206 @master = master 207 @component = component 208 209 ComponentID_TBL.mutex.synchronize{ 210 ComponentID_TBL[@master][@component] = self 211 } 212 213 begin 214 @widget = window(tk_call(@master, 'component', @component)) 215 @path = @widget.path 216 rescue 217 @widget = nil 218 @path = nil 219 end 220 end 221 222 def path 223 unless @path 224 begin 225 @widget = window(tk_call(@master, 'component', @component)) 226 @path = @widget.path 227 rescue 228 fail RuntimeError, 'component is not assigned to a widget' 229 end 230 end 231 @path 232 end 233 234 def epath 235 path() 236 end 237 238 def to_eval 239 path() 240 end 241 242 def master 243 @master 244 end 245 246 def name 247 @component 248 end 249 250 def widget 251 unless @widget 252 begin 253 @widget = window(tk_call(@master, 'component', @component)) 254 @path = @widget.path 255 rescue 256 fail RuntimeError, 'component is not assigned to a widget' 257 end 258 end 259 @widget 260 end 261 262 def widget_class 263 unless @widget 264 begin 265 @widget = window(tk_call(@master, 'component', @component)) 266 @path = @widget.path 267 @widget.classname 268 rescue 269 nil 270 end 271 end 272 end 273 274 def method_missing(id, *args) 275 name = id.id2name 276 277 # try 1 : component command 278 begin 279 return tk_call(@master, 'component', @component, name, *args) 280 rescue 281 end 282 283 # try 2 : component configure 284 len = args.length 285 begin 286 case len 287 when 1 288 if name[-1] == ?= 289 return configure(name[0..-2], args[0]) 290 else 291 return configure(name, args[0]) 292 end 293 when 0 294 return cget(name) 295 end 296 rescue 297 end 298 299 # try 3 : widget method or widget configure 300 begin 301 unless @widget 302 @widget = window(tk_call(@master, 'component', @component)) 303 @path = @widget.path 304 end 305 @widget.__send__(id, *args) 306 rescue 307 end 308 309 # unknown method 310 super(id, *args) 311 # fail RuntimeError, "unknown method '#{name}' for #{self.inspect}" 312 end 313 314 def tk_send(cmd, *rest) 315 begin 316 tk_call(@master, 'component', @component, cmd, *rest) 317 rescue 318 unless @path 319 begin 320 @widget = window(tk_call(@master, 'component', @component)) 321 @path = @widget.path 322 rescue 323 fail RuntimeError, 'component is not assigned to a widget' 324 end 325 end 326 tk_call(@path, cmd, *rest) 327 end 328 end 329 330 def tk_send_without_enc(cmd, *rest) 331 begin 332 tk_call_without_enc(@master, 'component', @component, cmd, *rest) 333 rescue 334 unless @path 335 begin 336 @widget = window(tk_call(@master, 'component', @component)) 337 @path = @widget.path 338 rescue 339 fail RuntimeError, 'component is not assigned to a widget' 340 end 341 end 342 tk_call_without_enc(@path, cmd, *rest) 343 end 344 end 345 346 def tk_send_with_enc(cmd, *rest) 347 begin 348 tk_call_with_enc(@master, 'component', @component, cmd, *rest) 349 rescue 350 unless @path 351 begin 352 @widget = window(tk_call(@master, 'component', @component)) 353 @path = @widget.path 354 rescue 355 fail RuntimeError, 'component is not assigned to a widget' 356 end 357 end 358 tk_call_with_enc(@path, cmd, *rest) 359 end 360 end 361 362 #def bind(*args) 363 # unless @widget 364 # begin 365 # @widget = window(tk_call(@master, 'component', @component)) 366 # @path = @widget.path 367 # rescue 368 # fail RuntimeError, 'component is not assigned to a widget' 369 # end 370 # end 371 # @widget.bind(*args) 372 #end 373 def bind(context, *args) 374 unless @widget 375 begin 376 @widget = window(tk_call(@master, 'component', @component)) 377 @path = @widget.path 378 rescue 379 fail RuntimeError, 'component is not assigned to a widget' 380 end 381 end 382 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) 383 if TkComm._callback_entry?(args[0]) || !block_given? 384 cmd = args.shift 385 else 386 cmd = Proc.new 387 end 388 @widget.bind(context, cmd, *args) 389 end 390 391 #def bind_append(*args) 392 # unless @widget 393 # begin 394 # @widget = window(tk_call(@master, 'component', @component)) 395 # @path = @widget.path 396 # rescue 397 # fail RuntimeError, 'component is not assigned to a widget' 398 # end 399 # end 400 # @widget.bind_append(*args) 401 #end 402 def bind_append(context, *args) 403 unless @widget 404 begin 405 @widget = window(tk_call(@master, 'component', @component)) 406 @path = @widget.path 407 rescue 408 fail RuntimeError, 'component is not assigned to a widget' 409 end 410 end 411 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) 412 if TkComm._callback_entry?(args[0]) || !block_given? 413 cmd = args.shift 414 else 415 cmd = Proc.new 416 end 417 @widget.bind_append(context, cmd, *args) 418 end 419 420 def bind_remove(*args) 421 unless @widget 422 begin 423 @widget = window(tk_call(@master, 'component', @component)) 424 @path = @widget.path 425 rescue 426 fail RuntimeError, 'component is not assigned to a widget' 427 end 428 end 429 @widget.bind_remove(*args) 430 end 431 432 def bindinfo(*args) 433 unless @widget 434 begin 435 @widget = window(tk_call(@master, 'component', @component)) 436 @path = @widget.path 437 rescue 438 fail RuntimeError, 'component is not assigned to a widget' 439 end 440 end 441 @widget.bindinfo(*args) 442 end 443 444 end 445 end 446end 447