1# 2# tk/composite.rb : 3# 4require 'tk' 5 6module TkComposite 7 include Tk 8 extend Tk 9 10=begin 11 def initialize(parent=nil, *args) 12 @delegates = {} 13 @option_methods = {} 14 @option_setting = {} 15 16 if parent.kind_of? Hash 17 keys = _symbolkey2str(parent) 18 parent = keys.delete('parent') 19 @frame = TkFrame.new(parent) 20 @path = @epath = @frame.path 21 initialize_composite(keys) 22 else 23 @frame = TkFrame.new(parent) 24 @path = @epath = @frame.path 25 initialize_composite(*args) 26 end 27 end 28=end 29 30 def _choice_classname_of_baseframe 31 base_class_name = nil 32 33 klass = WidgetClassNames[self.class::WidgetClassName] 34 35 if klass 36 # WidgetClassName is a known class 37 #if klass <= TkFrame || klass < TkComposite 38 if klass <= TkFrame || klass < Tk::Frame || klass < TkComposite 39 # klass is valid for the base frame 40 if self.class <= klass 41 # use my classname 42 base_class_name = self.class.name 43 if base_class_name == '' 44 # anonymous class -> use ancestor's name 45 base_class_name = klass.name 46 end 47 else 48 # not subclass -> use WidgetClassName 49 base_class_name = klass.name 50 end 51 52 else 53 # klass is invalid for the base frame 54 #if self.class < TkFrame || self.class.superclass < TkComposite 55 if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite 56 # my class name is valid for the base frame -> use my classname 57 base_class_name = self.class.name 58 if base_class_name == '' 59 # anonymous class -> use TkFrame 60 base_class_name = nil 61 end 62 else 63 # no idea for the base frame -> use TkFrame 64 base_class_name = nil 65 end 66 end 67 68 elsif self.class::WidgetClassName && ! self.class::WidgetClassName.empty? 69 # unknown WidgetClassName is defined -> use it for the base frame 70 base_class_name = self.class::WidgetClassName 71 72 else 73 # no valid WidgetClassName 74 #if self.class < TkFrame || self.class.superclass < TkComposite 75 if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite 76 # my class name is valid for the base frame -> use my classname 77 base_class_name = self.class.name 78 if base_class_name == '' 79 # anonymous class -> use TkFrame 80 base_class_name = nil 81 end 82 else 83 # no idea for the base frame -> use TkFrame 84 base_class_name = nil 85 end 86 end 87 88 base_class_name 89 end 90 private :_choice_classname_of_baseframe 91 92 # def initialize(parent=nil, *args) 93 def initialize(*args) 94 @delegates = {} 95 @option_methods = {} 96 @option_setting = {} 97 98 if args[-1].kind_of?(Hash) 99 keys = _symbolkey2str(args.pop) 100 else 101 keys = {} 102 end 103 parent = args.shift 104 parent = keys.delete('parent') if keys.has_key?('parent') 105 106 if keys.key?('classname') 107 keys['class'] = keys.delete('classname') 108 end 109 if (base_class_name = (keys.delete('class')).to_s).empty? 110 base_class_name = _choice_classname_of_baseframe 111 end 112 113 if base_class_name 114 # @frame = Tk::Frame.new(parent, :class=>base_class_name) 115 # --> use current TkFrame class 116 @frame = TkFrame.new(parent, :class=>base_class_name) 117 else 118 # @frame = Tk::Frame.new(parent) 119 # --> use current TkFrame class 120 @frame = TkFrame.new(parent) 121 end 122 @path = @epath = @frame.path 123 124 args.push(keys) unless keys.empty? 125 initialize_composite(*args) 126 end 127 128 def database_classname 129 @frame.database_classname 130 end 131 132 def database_class 133 @frame.database_class 134 end 135 136 def epath 137 @epath 138 end 139 140 def initialize_composite(*args) end 141 private :initialize_composite 142 143 def inspect 144 str = super 145 str.chop << ' @epath=' << @epath.inspect << '>' 146 end 147 148 def _get_opt_method_list(arg) 149 m_set, m_cget, m_info = arg 150 m_set = m_set.to_s 151 m_cget = m_set if !m_cget && self.method(m_set).arity == -1 152 m_cget = m_cget.to_s if m_cget 153 m_info = m_info.to_s if m_info 154 [m_set, m_cget, m_info] 155 end 156 private :_get_opt_method_list 157 158 def option_methods(*opts) 159 if opts.size == 1 && opts[0].kind_of?(Hash) 160 # {name => [m_set, m_cget, m_info], name => method} style 161 opts[0].each{|name, arg| 162 m_set, m_cget, m_info = _get_opt_method_list(arg) 163 @option_methods[name.to_s] = { 164 :set => m_set, :cget => m_cget, :info => m_info 165 } 166 } 167 else 168 # [m_set, m_cget, m_info] or method style 169 opts.each{|arg| 170 m_set, m_cget, m_info = _get_opt_method_list(arg) 171 @option_methods[m_set] = { 172 :set => m_set, :cget => m_cget, :info => m_info 173 } 174 } 175 end 176 end 177 178 def delegate_alias(alias_opt, option, *wins) 179 if wins.length == 0 180 fail ArgumentError, "target widgets are not given" 181 end 182 if alias_opt != option && (alias_opt == 'DEFAULT' || option == 'DEFAULT') 183 fail ArgumentError, "cannot alias 'DEFAULT' option" 184 end 185 alias_opt = alias_opt.to_s 186 option = option.to_s 187 if @delegates[alias_opt].kind_of?(Array) 188 if (elem = @delegates[alias_opt].assoc(option)) 189 wins.each{|w| elem[1].push(w)} 190 else 191 @delegates[alias_opt] << [option, wins] 192 end 193 else 194 @delegates[alias_opt] = [ [option, wins] ] 195 end 196 end 197 198 def delegate(option, *wins) 199 delegate_alias(option, option, *wins) 200 end 201 202 def __cget_delegates(slot) 203 slot = slot.to_s 204 205 if @option_methods.include?(slot) 206 if @option_methods[slot][:cget] 207 return self.__send__(@option_methods[slot][:cget]) 208 else 209 if @option_setting[slot] 210 return @option_setting[slot] 211 else 212 return '' 213 end 214 end 215 end 216 217 tbl = @delegates[slot] 218 tbl = @delegates['DEFAULT'] unless tbl 219 220 begin 221 if tbl 222 opt, wins = tbl[-1] 223 opt = slot if opt == 'DEFAULT' 224 if wins && wins[-1] 225 # return wins[-1].cget(opt) 226 return wins[-1].cget_strict(opt) 227 end 228 end 229 rescue 230 end 231 232 return None 233 end 234 private :__cget_delegates 235 236 def cget_tkstring(slot) 237 if (ret = __cget_delegates(slot)) == None 238 super(slot) 239 else 240 _get_eval_string(ret) 241 end 242 end 243 244 def cget(slot) 245 if (ret = __cget_delegates(slot)) == None 246 super(slot) 247 else 248 ret 249 end 250 end 251 252 def cget_strict(slot) 253 if (ret = __cget_delegates(slot)) == None 254 super(slot) 255 else 256 ret 257 end 258 end 259 260=begin 261 def cget(slot) 262 slot = slot.to_s 263 264 if @option_methods.include?(slot) 265 if @option_methods[slot][:cget] 266 return self.__send__(@option_methods[slot][:cget]) 267 else 268 if @option_setting[slot] 269 return @option_setting[slot] 270 else 271 return '' 272 end 273 end 274 end 275 276 tbl = @delegates[slot] 277 tbl = @delegates['DEFAULT'] unless tbl 278 279 begin 280 if tbl 281 opt, wins = tbl[-1] 282 opt = slot if opt == 'DEFAULT' 283 if wins && wins[-1] 284 return wins[-1].cget(opt) 285 end 286 end 287 rescue 288 end 289 290 super(slot) 291 end 292=end 293 294 def configure(slot, value=None) 295 if slot.kind_of? Hash 296 slot.each{|slot,value| configure slot, value} 297 return self 298 end 299 300 slot = slot.to_s 301 302 if @option_methods.include?(slot) 303 unless @option_methods[slot][:cget] 304 if value.kind_of?(Symbol) 305 @option_setting[slot] = value.to_s 306 else 307 @option_setting[slot] = value 308 end 309 end 310 return self.__send__(@option_methods[slot][:set], value) 311 end 312 313 tbl = @delegates[slot] 314 tbl = @delegates['DEFAULT'] unless tbl 315 316 begin 317 if tbl 318 last = nil 319 tbl.each{|opt, wins| 320 opt = slot if opt == 'DEFAULT' 321 wins.each{|w| last = w.configure(opt, value)} 322 } 323 return last 324 end 325 rescue 326 end 327 328 super(slot, value) 329 end 330 331 def configinfo(slot = nil) 332 if TkComm::GET_CONFIGINFO_AS_ARRAY 333 if slot 334 slot = slot.to_s 335 if @option_methods.include?(slot) 336 if @option_methods[slot][:info] 337 return self.__send__(@option_methods[slot][:info]) 338 else 339 return [slot, '', '', '', self.cget(slot)] 340 end 341 end 342 343 tbl = @delegates[slot] 344 tbl = @delegates['DEFAULT'] unless tbl 345 346 begin 347 if tbl 348 if tbl.length == 1 349 opt, wins = tbl[0] 350 if slot == opt || opt == 'DEFAULT' 351 return wins[-1].configinfo(slot) 352 else 353 info = wins[-1].configinfo(opt) 354 info[0] = slot 355 return info 356 end 357 else 358 opt, wins = tbl[-1] 359 return [slot, '', '', '', wins[-1].cget(opt)] 360 end 361 end 362 rescue 363 end 364 365 super(slot) 366 367 else # slot == nil 368 info_list = super(slot) 369 370 tbl = @delegates['DEFAULT'] 371 if tbl 372 wins = tbl[0][1] 373 if wins && wins[-1] 374 wins[-1].configinfo.each{|info| 375 slot = info[0] 376 info_list.delete_if{|i| i[0] == slot} << info 377 } 378 end 379 end 380 381 @delegates.each{|slot, tbl| 382 next if slot == 'DEFAULT' 383 if tbl.length == 1 384 opt, wins = tbl[0] 385 next unless wins && wins[-1] 386 if slot == opt 387 info_list.delete_if{|i| i[0] == slot} << 388 wins[-1].configinfo(slot) 389 else 390 info = wins[-1].configinfo(opt) 391 info[0] = slot 392 info_list.delete_if{|i| i[0] == slot} << info 393 end 394 else 395 opt, wins = tbl[-1] 396 info_list.delete_if{|i| i[0] == slot} << 397 [slot, '', '', '', wins[-1].cget(opt)] 398 end 399 } 400 401 @option_methods.each{|slot, m| 402 if m[:info] 403 info = self.__send__(m[:info]) 404 else 405 info = [slot, '', '', '', self.cget(slot)] 406 end 407 info_list.delete_if{|i| i[0] == slot} << info 408 } 409 410 info_list 411 end 412 413 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY 414 if slot 415 slot = slot.to_s 416 if @option_methods.include?(slot) 417 if @option_methods[slot][:info] 418 return self.__send__(@option_methods[slot][:info]) 419 else 420 return {slot => ['', '', '', self.cget(slot)]} 421 end 422 end 423 424 tbl = @delegates[slot] 425 tbl = @delegates['DEFAULT'] unless tbl 426 427 begin 428 if tbl 429 if tbl.length == 1 430 opt, wins = tbl[0] 431 if slot == opt || opt == 'DEFAULT' 432 return wins[-1].configinfo(slot) 433 else 434 return {slot => wins[-1].configinfo(opt)[opt]} 435 end 436 else 437 opt, wins = tbl[-1] 438 return {slot => ['', '', '', wins[-1].cget(opt)]} 439 end 440 end 441 rescue 442 end 443 444 super(slot) 445 446 else # slot == nil 447 info_list = super(slot) 448 449 tbl = @delegates['DEFAULT'] 450 if tbl 451 wins = tbl[0][1] 452 info_list.update(wins[-1].configinfo) if wins && wins[-1] 453 end 454 455 @delegates.each{|slot, tbl| 456 next if slot == 'DEFAULT' 457 if tbl.length == 1 458 opt, wins = tbl[0] 459 next unless wins && wins[-1] 460 if slot == opt 461 info_list.update(wins[-1].configinfo(slot)) 462 else 463 info_list.update({slot => wins[-1].configinfo(opt)[opt]}) 464 end 465 else 466 opt, wins = tbl[-1] 467 info_list.update({slot => ['', '', '', wins[-1].cget(opt)]}) 468 end 469 } 470 471 @option_methods.each{|slot, m| 472 if m[:info] 473 info = self.__send__(m[:info]) 474 else 475 info = {slot => ['', '', '', self.cget(slot)]} 476 end 477 info_list.update(info) 478 } 479 480 info_list 481 end 482 end 483 end 484end 485