1# 2# tkextlib/blt/treeview.rb 3# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) 4# 5 6require 'tk' 7require 'tkextlib/blt.rb' 8require 'tk/validation.rb' 9 10module Tk::BLT 11 class Treeview < TkWindow 12 module ConfigMethod 13 end 14 15 module TagOrID_Methods 16 end 17 18 class Node < TkObject 19 end 20 21 class Tag < TkObject 22 end 23 end 24 25 class Hiertable < Treeview 26 end 27end 28 29###################################### 30 31module Tk::BLT::Treeview::ConfigMethod 32 include TkItemConfigMethod 33 34 def __item_boolval_optkeys(id) 35 case id 36 when Array 37 # id := [ 'column', name ] 38 ['edit', 'hide'] 39 when 'sort' 40 ['decreasing'] 41 else 42 [] 43 end 44 end 45 private :__item_boolval_optkeys 46 47 def __item_strval_optkeys(id) 48 case id 49 when Array 50 # id := [ 'column', name ] 51 super() << 'titleforeground' << 'titleshadow' 52 when 'sort' 53 ['decreasing'] 54 else 55 [] 56 end 57 end 58 private :__item_strval_optkeys 59 60 def __item_listval_optkeys(id) 61 case id 62 when 'entry' 63 ['bindtags'] 64 else 65 [] 66 end 67 end 68 private :__item_listval_optkeys 69 70 def __item_cget_cmd(id) 71 if id.kind_of?(Array) 72 # id := [ type, name ] 73 [self.path, id[0], 'cget', id[1]] 74 else 75 [self.path, id, 'cget'] 76 end 77 end 78 private :__item_cget_cmd 79 80 def __item_config_cmd(id) 81 if id.kind_of?(Array) 82 # id := [ type, name ] 83 [self.path, id[0], 'configure', id[1]] 84 else 85 [self.path, id, 'configure'] 86 end 87 end 88 private :__item_config_cmd 89 90 def __item_pathname(id) 91 if id.kind_of?(Array) 92 id = tagid(id[1]) 93 end 94 [self.path, id].join(';') 95 end 96 private :__item_pathname 97 98 def column_cget_tkstring(name, option) 99 itemcget_tkstring(['column', name], option) 100 end 101 def column_cget(name, option) 102 itemcget(['column', name], option) 103 end 104 def column_cget_strict(name, option) 105 itemcget_strict(['column', name], option) 106 end 107 def column_configure(name, slot, value=None) 108 itemconfigure(['column', name], slot, value) 109 end 110 def column_configinfo(name, slot=nil) 111 itemconfiginfo(['column', name], slot) 112 end 113 def current_column_configinfo(name, slot=nil) 114 current_itemconfiginfo(['column', name], slot) 115 end 116 117 def button_cget_tkstring(option) 118 itemcget_tkstring('button', option) 119 end 120 def button_cget(option) 121 itemcget('button', option) 122 end 123 def button_cget_strict(option) 124 itemcget_strict('button', option) 125 end 126 def button_configure(slot, value=None) 127 itemconfigure('button', slot, value) 128 end 129 def button_configinfo(slot=nil) 130 itemconfiginfo('button', slot) 131 end 132 def current_button_configinfo(slot=nil) 133 current_itemconfiginfo('button', slot) 134 end 135 136 def entry_cget_tkstring(option) 137 itemcget_tkstring('entry', option) 138 end 139 def entry_cget(option) 140 ret = itemcget('entry', option) 141 if option == 'bindtags' || option == :bindtags 142 ret.collect{|tag| TkBindTag.id2obj(tag)} 143 else 144 ret 145 end 146 end 147 def entry_cget_strict(option) 148 ret = itemcget_strict('entry', option) 149 if option == 'bindtags' || option == :bindtags 150 ret.collect{|tag| TkBindTag.id2obj(tag)} 151 else 152 ret 153 end 154 end 155 def entry_configure(slot, value=None) 156 itemconfigure('entry', slot, value) 157 end 158 def entry_configinfo(slot=nil) 159 ret = itemconfiginfo('entry', slot) 160 161 if TkComm::GET_CONFIGINFO_AS_ARRAY 162 if slot 163 if slot == 'bindtags' || slot == :bindtags 164 ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)} 165 ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)} 166 end 167 else 168 inf = ret.assoc('bindtags') 169 inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)} 170 inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)} 171 end 172 173 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY 174 if (inf = ret['bindtags']) 175 inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)} 176 inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)} 177 ret['bindtags'] = inf 178 end 179 end 180 181 ret 182 end 183 def current_entry_configinfo(slot=nil) 184 ret = current_itemconfiginfo('entry', slot) 185 186 if (val = ret['bindtags']) 187 ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)} 188 end 189 190 ret 191 end 192 193 def sort_cget_tkstring(option) 194 itemcget_tkstring('sort', option) 195 end 196 def sort_cget(option) 197 itemcget('sort', option) 198 end 199 def sort_cget_strict(option) 200 itemcget_strict('sort', option) 201 end 202 def sort_configure(slot, value=None) 203 itemconfigure('sort', slot, value) 204 end 205 def sort_configinfo(slot=nil) 206 itemconfiginfo('sort', slot) 207 end 208 def current_sort_configinfo(slot=nil) 209 current_itemconfiginfo('sort', slot) 210 end 211 212 def text_cget_tkstring(option) 213 itemcget_tkstring('text', option) 214 end 215 def text_cget(option) 216 itemcget('text', option) 217 end 218 def text_cget_strict(option) 219 itemcget_strict('text', option) 220 end 221 def text_configure(slot, value=None) 222 itemconfigure('text', slot, value) 223 end 224 def text_configinfo(slot=nil) 225 itemconfiginfo('text', slot) 226 end 227 def current_text_configinfo(slot=nil) 228 current_itemconfiginfo('text', slot) 229 end 230 231 private :itemcget_tkstring, :itemcget, :itemcget_strict 232 private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo 233end 234 235class Tk::BLT::Treeview 236 TkCommandNames = ['::blt::treeview'.freeze].freeze 237 WidgetClassName = 'TreeView'.freeze 238 WidgetClassNames[WidgetClassName] ||= self 239 240 include Scrollable 241 include ValidateConfigure 242 include ItemValidateConfigure 243 include Tk::BLT::Treeview::ConfigMethod 244 245 ######################## 246 247 def __boolval_optkeys 248 ['autocreate', 'allowduplicates', 'exportselection', 'flat', 'hideroot', 249 'newtags', 'showtitles', 'sortselection'] 250 end 251 private :__boolval_optkeys 252 253 def __strval_optkeys 254 super() + ['focusforeground', 'linecolor', 'separator', 'trim'] 255 end 256 private :__strval_optkeys 257 258 ######################## 259 260 class OpenCloseCommand < TkValidateCommand 261 class ValidateArgs < TkUtil::CallbackSubst 262 KEY_TBL = [ 263 [ ?W, ?w, :widget ], 264 [ ?p, ?s, :name ], 265 [ ?P, ?s, :fullpath ], 266 [ ?#, ?x, :node_id ], 267 nil 268 ] 269 270 PROC_TBL = [ 271 [ ?x, TkComm.method(:num_or_str) ], 272 [ ?s, TkComm.method(:string) ], 273 [ ?w, TkComm.method(:window) ], 274 nil 275 ] 276 277=begin 278 # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) 279 KEY_TBL.map!{|inf| 280 if inf.kind_of?(Array) 281 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 282 inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) 283 end 284 inf 285 } 286 287 PROC_TBL.map!{|inf| 288 if inf.kind_of?(Array) 289 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 290 end 291 inf 292 } 293=end 294 295 _setup_subst_table(KEY_TBL, PROC_TBL); 296 297 def self.ret_val(val) 298 val 299 end 300 end 301 302 def self._config_keys 303 ['opencommand', 'closecomand'] 304 end 305 end 306 307 def __validation_class_list 308 super() << OpenCloseCommand 309 end 310 311 Tk::ValidateConfigure.__def_validcmd(binding, OpenCloseCommand) 312 313 ######################## 314 315 def __item_validation_class_list(id) 316 case id 317 when 'entry' 318 super(id) << OpenCloseCommand 319 else 320 super(id) 321 end 322 end 323 324 Tk::ItemValidateConfigure.__def_validcmd(binding, OpenCloseCommand) 325 326 ######################## 327 328 def __destroy_hook__ 329 Tk::BLT::Treeview::Node::TreeNodeID_TBL.mutex.synchronize{ 330 Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path) 331 } 332 Tk::BLT::Treeview::Tag::TreeTagID_TBL.mutex.synchronize{ 333 Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path) 334 } 335 end 336 337 def tagid(tag) 338 if tag.kind_of?(Tk::BLT::Treeview::Node) \ 339 || tag.kind_of?(Tk::BLT::Treeview::Tag) 340 tag.id 341 else 342 tag # maybe an Array of configure paramters 343 end 344 end 345 private :tagid 346 347 def tagid2obj(tagid) 348 if tagid.kind_of?(Integer) 349 Tk::BLT::Treeview::Node.id2obj(self, tagid.to_s) 350 elsif tagid.kind_of?(String) 351 if tagid =~ /^\d+$/ 352 Tk::BLT::Treeview::Node.id2obj(self, tagid) 353 else 354 Tk::BLT::Treeview::Tag.id2obj(self, tagid) 355 end 356 else 357 tagid 358 end 359 end 360 361 def bbox(*tags) 362 list(tk_send('bbox', *(tags.collect{|tag| tagid(tag)}))) 363 end 364 365 def screen_bbox(*tags) 366 list(tk_send('bbox', '-screen', *(tags.collect{|tag| tagid(tag)}))) 367 end 368 369 def tag_bind(tag, seq, *args) 370 if TkComm._callback_entry?(args[0]) || !block_given? 371 cmd = args.shift 372 else 373 cmd = Proc.new 374 end 375 _bind([@path, 'bind', tagid(tag)], seq, cmd, *args) 376 self 377 end 378 def tag_bind_append(tag, seq, *args) 379 if TkComm._callback_entry?(args[0]) || !block_given? 380 cmd = args.shift 381 else 382 cmd = Proc.new 383 end 384 _bind_append([@path, 'bind', tagid(tag)], seq, cmd, *args) 385 self 386 end 387 def tag_bind_remove(tag, seq) 388 _bind_remove([@path, 'bind', tagid(tag)], seq) 389 self 390 end 391 def tag_bindinfo(tag, seq=nil) 392 _bindinfo([@path, 'bind', tagid(tag)], seq) 393 end 394 395 def button_activate(tag) 396 tk_send('button', 'activate', tagid(tag)) 397 self 398 end 399 400 def button_bind(tag, seq, *args) 401 if TkComm._callback_entry?(args[0]) || !block_given? 402 cmd = args.shift 403 else 404 cmd = Proc.new 405 end 406 _bind([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args) 407 self 408 end 409 def button_bind_append(tag, seq, *args) 410 if TkComm._callback_entry?(args[0]) || !block_given? 411 cmd = args.shift 412 else 413 cmd = Proc.new 414 end 415 _bind_append([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args) 416 self 417 end 418 def button_bind_remove(tag, seq) 419 _bind_remove([@path, 'button', 'bind', tagid(tag)], seq) 420 self 421 end 422 def button_bindinfo(tag, seq=nil) 423 _bindinfo([@path, 'button', 'bind', tagid(tag)], seq) 424 end 425 426 def close(*tags) 427 tk_send('close', *(tags.collect{|tag| tagid(tag)})) 428 self 429 end 430 def close_recurse(*tags) 431 tk_send('close', '-recurse', *(tags.collect{|tag| tagid(tag)})) 432 self 433 end 434 435 def column_activate(column=None) 436 if column == None 437 tk_send('column', 'activate') 438 else 439 tk_send('column', 'activate', column) 440 self 441 end 442 end 443 444 def column_delete(*fields) 445 tk_send('column', 'delete', *fields) 446 self 447 end 448 def column_insert(pos, field, *opts) 449 tk_send('column', 'insert', pos, field, *opts) 450 self 451 end 452 def column_invoke(field) 453 tk_send('column', 'invoke', field) 454 self 455 end 456 def column_move(name, dest) 457 tk_send('column', 'move', name, dest) 458 self 459 end 460 def column_names() 461 simplelist(tk_send('column', 'names')) 462 end 463 def column_nearest(x, y=None) 464 tk_send('column', 'nearest', x, y) 465 end 466 467 def curselection 468 simplelist(tk_send('curselection')).collect{|id| tagid2obj(id)} 469 end 470 471 def delete(*tags) 472 tk_send('delete', *(tags.collect{|tag| tagid(tag)})) 473 self 474 end 475 476 def entry_activate(tag) 477 tk_send('entry', 'activate', tagid(tag)) 478 self 479 end 480 def entry_children(tag, first=None, last=None) 481 simplelist(tk_send('entry', 'children', tagid(tag), 482 first, last)).collect{|id| tagid2obj(id)} 483 end 484 def entry_delete(tag, first=None, last=None) 485 tk_send('entry', 'delete', tagid(tag), first, last) 486 end 487 def entry_before?(tag1, tag2) 488 bool(tk_send('entry', 'isbefore', tagid(tag1), tagid(tag2))) 489 end 490 def entry_hidden?(tag) 491 bool(tk_send('entry', 'ishidden', tagid(tag))) 492 end 493 def entry_open?(tag) 494 bool(tk_send('entry', 'isopen', tagid(tag))) 495 end 496 497 def entry_size(tag) 498 number(tk_send('entry', 'size', tagid(tag))) 499 end 500 def entry_size_recurse(tag) 501 number(tk_send('entry', 'size', '-recurse', tagid(tag))) 502 end 503 504 def _search_flags(keys) 505 keys = _symbolkey2str(keys) 506 keys['exact'] = None if keys.delete('exact') 507 keys['glob'] = None if keys.delete('glob') 508 keys['regexp'] = None if keys.delete('regexp') 509 keys['nonmatching'] = None if keys.delete('nonmatching') 510 end 511 private :_search_flags 512 513 ################################ 514 515 class FindExecFlagValue < TkValidateCommand 516 class ValidateArgs < TkUtil::CallbackSubst 517 KEY_TBL = [ 518 [ ?W, ?w, :widget ], 519 [ ?p, ?s, :name ], 520 [ ?P, ?s, :fullpath ], 521 [ ?#, ?x, :node_id ], 522 nil 523 ] 524 525 PROC_TBL = [ 526 [ ?x, TkComm.method(:num_or_str) ], 527 [ ?s, TkComm.method(:string) ], 528 [ ?w, TkComm.method(:window) ], 529 nil 530 ] 531 532=begin 533 # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) 534 KEY_TBL.map!{|inf| 535 if inf.kind_of?(Array) 536 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 537 inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) 538 end 539 inf 540 } 541 542 PROC_TBL.map!{|inf| 543 if inf.kind_of?(Array) 544 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 545 end 546 inf 547 } 548=end 549 550 _setup_subst_table(KEY_TBL, PROC_TBL); 551 552 def self.ret_val(val) 553 val 554 end 555 end 556 557 def self._config_keys 558 [] 559 end 560 end 561 562 def _find_exec_flag_value(val) 563 if val.kind_of?(Array) 564 cmd, *args = val 565 #FindExecFlagValue.new(cmd, args.join(' ')) 566 FindExecFlagValue.new(cmd, *args) 567 elsif TkComm._callback_entry?(val) 568 FindExecFlagValue.new(val) 569 else 570 val 571 end 572 end 573 574 ################################ 575 576 def find(first, last, keys={}) 577 keys = _search_flags(keys) 578 keys['exec'] = _find_exec_flag_value(keys['exec']) if keys.key?('exec') 579 args = hash_kv(keys) << '--' << tagid(first) << tagid(last) 580 simplelist(tk_send('find', *args)).collect{|id| tagid2obj(id)} 581 end 582 583 def tag_focus(tag) 584 tk_send('focus', tagid(tag)) 585 self 586 end 587 def get(*tags) 588 simplelist(tk_send('get', *(tags.collect{|tag| tagid(tag)}))) 589 end 590 def get_full(*tags) 591 simplelist(tk_send('get', '-full', *(tags.collect{|tag| tagid(tag)}))) 592 end 593 594 def hide(*tags) 595 if tags[-1].kind_of?(Hash) 596 keys = tags.pop 597 else 598 keys = {} 599 end 600 keys = _search_flags(keys) 601 args = hash_kv(keys) << '--' 602 args.concat(tags.collect{|t| tagid(t)}) 603 tk_send('hide', *args) 604 self 605 end 606 607 def index(str) 608 tagid2obj(tk_send('index', str)) 609 end 610 def index_at(tag, str) 611 tagid2obj(tk_send('index', '-at', tagid(tag), str)) 612 end 613 def index_at_path(tag, str) 614 tagid2obj(tk_send('index', '-at', tagid(tag), '-path', str)) 615 end 616 617 def insert(pos, parent=nil, keys={}) 618 Tk::BLT::Treeview::Node.new(pos, parent, keys) 619 end 620 def insert_at(tag, pos, parent=nil, keys={}) 621 if parent.kind_of?(Hash) 622 keys = parent 623 parent = nil 624 end 625 626 keys = _symbolkey2str(keys) 627 keys['at'] = tagid(tag) 628 629 Tk::BLT::Treeview::Node.new(pos, parent, keys) 630 end 631 632 def move_before(tag, dest) 633 tk_send('move', tagid(tag), 'before', tagid(dest)) 634 self 635 end 636 def move_after(tag, dest) 637 tk_send('move', tagid(tag), 'after', tagid(dest)) 638 self 639 end 640 def move_into(tag, dest) 641 tk_send('move', tagid(tag), 'into', tagid(dest)) 642 self 643 end 644 645 def nearest(x, y, var=None) 646 tagid2obj(tk_send('nearest', x, y, var)) 647 end 648 649 def open(*tags) 650 tk_send('open', *(tags.collect{|tag| tagid(tag)})) 651 self 652 end 653 def open_recurse(*tags) 654 tk_send('open', '-recurse', *(tags.collect{|tag| tagid(tag)})) 655 self 656 end 657 658 def range(first, last) 659 simplelist(tk_send('range', tagid(first), tagid(last))).collect{|id| 660 tagid2obj(id) 661 } 662 end 663 def range_open(first, last) 664 simplelist(tk_send('range', '-open', 665 tagid(first), tagid(last))).collect{|id| 666 tagid2obj(id) 667 } 668 end 669 670 def scan_mark(x, y) 671 tk_send_without_enc('scan', 'mark', x, y) 672 self 673 end 674 def scan_dragto(x, y) 675 tk_send_without_enc('scan', 'dragto', x, y) 676 self 677 end 678 679 def see(tag) 680 tk_send_without_enc('see', tagid(tag)) 681 self 682 end 683 def see_anchor(anchor, tag) 684 tk_send_without_enc('see', '-anchor', anchor, tagid(tag)) 685 self 686 end 687 688 def selection_anchor(tag) 689 tk_send_without_enc('selection', 'anchor', tagid(tag)) 690 self 691 end 692 def selection_cancel() 693 tk_send_without_enc('selection', 'cancel') 694 self 695 end 696 def selection_clear(first, last=None) 697 tk_send_without_enc('selection', 'clear', tagid(first), tagid(last)) 698 self 699 end 700 def selection_clear_all() 701 tk_send_without_enc('selection', 'clearall') 702 self 703 end 704 def selection_mark(tag) 705 tk_send_without_enc('selection', 'mark', tagid(tag)) 706 self 707 end 708 def selection_include?(tag) 709 bool(tk_send('selection', 'include', tagid(tag))) 710 end 711 def selection_present?() 712 bool(tk_send('selection', 'present')) 713 end 714 def selection_set(first, last=None) 715 tk_send_without_enc('selection', 'set', tagid(first), tagid(last)) 716 self 717 end 718 def selection_toggle(first, last=None) 719 tk_send_without_enc('selection', 'toggle', tagid(first), tagid(last)) 720 self 721 end 722 723 def show(*tags) 724 if tags[-1].kind_of?(Hash) 725 keys = tags.pop 726 else 727 keys = {} 728 end 729 keys = _search_flags(keys) 730 args = hash_kv(keys) << '--' 731 args.concat(tags.collect{|t| tagid(t)}) 732 tk_send('show', *args) 733 self 734 end 735 736 def sort_auto(mode) 737 tk_send('sort', 'auto', mode) 738 self 739 end 740 def sort_auto=(mode) 741 tk_send('sort', 'auto', mode) 742 mode 743 end 744 def sort_auto? 745 bool(tk_send('sort', 'auto')) 746 end 747 def sort_once(*tags) 748 tk_send('sort', 'once', *(tags.collect{|tag| tagid(tag)})) 749 self 750 end 751 def sort_once_recurse(*tags) 752 tk_send('sort', 'once', '-recurse', *(tags.collect{|tag| tagid(tag)})) 753 self 754 end 755 756 def tag_add(tag, *ids) 757 tk_send('tag', 'add', tagid(tag), *ids) 758 self 759 end 760 def tag_delete(tag, *ids) 761 tk_send('tag', 'delete', tagid(tag), *ids) 762 self 763 end 764 def tag_forget(tag) 765 tk_send('tag', 'forget', tagid(tag)) 766 self 767 end 768 def tag_names(id=nil) 769 id = (id)? tagid(id): None 770 771 simplelist(tk_send('tag', 'nodes', id)).collect{|tag| 772 Tk::BLT::Treeview::Tag.id2obj(self, tag) 773 } 774 end 775 def tag_nodes(tag) 776 simplelist(tk_send('tag', 'nodes', tagid(tag))).collect{|id| 777 Tk::BLT::Treeview::Node.id2obj(self, id) 778 } 779 end 780 781 def text_apply 782 tk_send('text', 'apply') 783 self 784 end 785 def text_cancel 786 tk_send('text', 'cancel') 787 self 788 end 789 790 def text_delete(first, last) 791 tk_send('text', 'delete', first, last) 792 self 793 end 794 def text_get(x, y) 795 tk_send('text', 'get', x, y) 796 end 797 def text_get_root(x, y) 798 tk_send('text', 'get', '-root', x, y) 799 end 800 def text_icursor(idx) 801 tk_send('text', 'icursor', idx) 802 self 803 end 804 def text_index(idx) 805 num_or_str(tk_send('text', 'index', idx)) 806 end 807 def text_insert(idx, str) 808 tk_send('text', 'insert', idx, str) 809 self 810 end 811 812 def text_selection_adjust(idx) 813 tk_send('text', 'selection', 'adjust', idx) 814 self 815 end 816 def text_selection_clear 817 tk_send('text', 'selection', 'clear') 818 self 819 end 820 def text_selection_from(idx) 821 tk_send('text', 'selection', 'from', idx) 822 self 823 end 824 def text_selection_present 825 num_or_str(tk_send('text', 'selection', 'present')) 826 end 827 def text_selection_range(start, last) 828 tk_send('text', 'selection', 'range', start, last) 829 self 830 end 831 def text_selection_to(idx) 832 tk_send('text', 'selection', 'to', idx) 833 self 834 end 835 836 def toggle(tag) 837 tk_send('toggle', tagid(tag)) 838 self 839 end 840end 841 842###################################### 843 844module Tk::BLT::Treeview::TagOrID_Methods 845 def bbox 846 @tree.bbox(self) 847 end 848 def screen_bbox 849 @tree.screen_bbox(self) 850 end 851 852 def bind(seq, *args) 853 @tree.tag_bind(self, seq, *args) 854 self 855 end 856 def bind_append(seq, *args) 857 @tree.tag_bind_append(self, seq, *args) 858 self 859 end 860 def bind_remove(seq) 861 @tree.tag_bind_remove(self, seq) 862 self 863 end 864 def bindinfo(seq=nil) 865 @tree.tag_bindinfo(self, seq) 866 end 867 868 def button_activate 869 @tree.button_activate(self) 870 self 871 end 872 873 def button_bind(seq, *args) 874 @tree.button_bind(self, seq, *args) 875 self 876 end 877 def button_bind_append(seq, *args) 878 @tree.button_bind_append(self, seq, *args) 879 self 880 end 881 def button_bind_remove(seq) 882 @tree.button_bind_remove(self, seq) 883 self 884 end 885 def button_bindinfo(seq=nil) 886 @tree.button_bindinfo(self, seq) 887 end 888 889 def close 890 @tree.close(self) 891 self 892 end 893 def close_recurse 894 @tree.close_recurse(self) 895 self 896 end 897 898 def delete 899 @tree.delete(self) 900 self 901 end 902 903 def entry_activate 904 @tree.entry_activate(self) 905 self 906 end 907 def entry_children(first=None, last=None) 908 @tree.entry_children(self, first, last) 909 end 910 def entry_delete(first=None, last=None) 911 @tree.entry_delete(self, first, last) 912 end 913 def entry_before?(tag) 914 @tree.entry_before?(self, tag) 915 end 916 def entry_hidden? 917 @tree.entry_before?(self) 918 end 919 def entry_open? 920 @tree.entry_open?(self) 921 end 922 923 def entry_size 924 @tree.entry_size(self) 925 end 926 def entry_size_recurse 927 @tree.entry_size_recurse(self) 928 end 929 930 def focus 931 @tree.tag_focus(self) 932 self 933 end 934 935 def get 936 @tree.get(self) 937 end 938 def get_full 939 @tree.get_full(self) 940 end 941 942 def hide 943 @tree.hide(self) 944 self 945 end 946 947 def index(str) 948 @tree.index_at(self, str) 949 end 950 def index_path(str) 951 @tree.index_at_path(self, str) 952 end 953 954 def insert(pos, parent=nil, keys={}) 955 @tree.insert_at(self, pos, parent, keys) 956 end 957 958 def move_before(dest) 959 @tree.move_before(self, dest) 960 self 961 end 962 def move_after(dest) 963 @tree.move_after(self, dest) 964 self 965 end 966 def move_into(dest) 967 @tree.move_into(self, dest) 968 self 969 end 970 971 def open 972 @tree.open(self) 973 self 974 end 975 def open_recurse 976 @tree.open_recurse(self) 977 self 978 end 979 980 def range_to(tag) 981 @tree.range(self, tag) 982 end 983 def range_open_to(tag) 984 @tree.range(self, tag) 985 end 986 987 def see 988 @tree.see(self) 989 self 990 end 991 def see_anchor(anchor) 992 @tree.see_anchor(anchor, self) 993 self 994 end 995 996 def selection_anchor 997 @tree.selection_anchor(self) 998 self 999 end 1000 def selection_clear 1001 @tree.selection_clear(self) 1002 self 1003 end 1004 def selection_mark 1005 @tree.selection_mark(self) 1006 self 1007 end 1008 def selection_include? 1009 @tree.selection_include?(self) 1010 end 1011 def selection_set 1012 @tree.selection_set(self) 1013 self 1014 end 1015 def selection_toggle 1016 @tree.selection_toggle(self) 1017 self 1018 end 1019 1020 def show 1021 @tree.show(self) 1022 self 1023 end 1024 1025 def sort_once 1026 @tree.sort_once(self) 1027 self 1028 end 1029 def sort_once_recurse 1030 @tree.sort_once_recurse(self) 1031 self 1032 end 1033 1034 def toggle 1035 @tree.toggle(self) 1036 self 1037 end 1038end 1039 1040###################################### 1041 1042class Tk::BLT::Treeview::Node < TkObject 1043 include Tk::BLT::Treeview::TagOrID_Methods 1044 1045 TreeNodeID_TBL = TkCore::INTERP.create_table 1046 1047 (TreeNode_ID = ['blt_treeview_node'.freeze, TkUtil.untrust('00000')]).instance_eval{ 1048 @mutex = Mutex.new 1049 def mutex; @mutex; end 1050 freeze 1051 } 1052 1053 TkCore::INTERP.init_ip_env{ 1054 TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear } 1055 } 1056 1057 def self.id2obj(tree, id) 1058 tpath = tree.path 1059 TreeNodeID_TBL.mutex.synchronize{ 1060 if TreeNodeID_TBL[tpath] 1061 if TreeNodeID_TBL[tpath][id] 1062 TreeNodeID_TBL[tpath][id] 1063 else 1064 begin 1065 # self.new(tree, nil, nil, 'node'=>Integer(id)) 1066 unless (tk_call(@tpath, 'get', id)).empty? 1067 id = Integer(id) 1068 (obj = self.allocate).instance_eval{ 1069 @parent = @tree = tree 1070 @tpath = @parent.path 1071 @path = @id = id 1072 TreeNodeID_TBL[@tpath] ||= {} 1073 TreeNodeID_TBL[@tpath][@id] = self 1074 } 1075 obj 1076 else 1077 id 1078 end 1079 rescue 1080 id 1081 end 1082 end 1083 else 1084 id 1085 end 1086 } 1087 end 1088 1089 def self.new(tree, pos, parent=nil, keys={}) 1090 if parent.kind_of?(Hash) 1091 keys = parent 1092 parent = nil 1093 end 1094 1095 keys = _symbolkey2str(keys) 1096 tpath = tree.path 1097 1098 TreeNodeID_TBL.mutex.synchronize{ 1099 TreeNodeID_TBL[tpath] ||= {} 1100 if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id]) 1101 keys.delete('node') 1102 tk_call(tree.path, 'move', id, pos, parent) if parent 1103 return obj 1104 end 1105 1106 #super(tree, pos, parent, keys) 1107 (obj = self.allocate).instance_eval{ 1108 initialize(tree, pos, parent, keys) 1109 TreeNodeID_TBL[tpath][@id] = self 1110 } 1111 obj 1112 } 1113 end 1114 1115 def initialize(tree, pos, parent, keys) 1116 @parent = @tree = tree 1117 @tpath = @parent.path 1118 1119 if (id = keys['node']) 1120 # if tk_call(@tpath, 'get', id).empty? 1121 # fail RuntimeError, "not exist the node '#{id}'" 1122 # end 1123 @path = @id = id 1124 tk_call(@tpath, 'move', @id, pos, tagid(parent)) if parent 1125 configure(keys) if keys && ! keys.empty? 1126 else 1127 name = nil 1128 TreeNode_ID.mutex.synchronize{ 1129 name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze 1130 TreeNode_ID[1].succ! 1131 } 1132 1133 at = keys.delete['at'] 1134 1135 if parent 1136 if parent.kind_of?(Tk::BLT::Treeview::Node) || 1137 parent.kind_of?(Tk::BLT::Treeview::Tag) 1138 path = [get_full(parent.id)[0], name] 1139 at = nil # ignore 'at' option 1140 else 1141 path = [parent.to_s, name] 1142 end 1143 else 1144 path = name 1145 end 1146 1147 if at 1148 @id = tk_call(@tpath, 'insert', '-at', tagid(at), pos, path, keys) 1149 else 1150 @id = tk_call(@tpath, 'insert', pos, path, keys) 1151 end 1152 @path = @id 1153 end 1154 end 1155 1156 def id 1157 @id 1158 end 1159end 1160 1161###################################### 1162 1163class Tk::BLT::Treeview::Tag < TkObject 1164 include Tk::BLT::Treeview::TagOrID_Methods 1165 1166 TreeTagID_TBL = TkCore::INTERP.create_table 1167 1168 (TreeTag_ID = ['blt_treeview_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ 1169 @mutex = Mutex.new 1170 def mutex; @mutex; end 1171 freeze 1172 } 1173 1174 TkCore::INTERP.init_ip_env{ 1175 TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear } 1176 } 1177 1178 def self.id2obj(tree, name) 1179 tpath = tree.path 1180 TreeTagID_TBL.mutex.synchronize{ 1181 if TreeTagID_TBL[tpath] 1182 if TreeTagID_TBL[tpath][name] 1183 TreeTagID_TBL[tpath][name] 1184 else 1185 #self.new(tree, name) 1186 (obj = self.allocate).instance_eval{ 1187 @parent = @tree = tree 1188 @tpath = @parent.path 1189 @path = @id = name 1190 TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] 1191 TreeTagID_TBL[@tpath][@id] = self 1192 } 1193 obj 1194 end 1195 else 1196 id 1197 end 1198 } 1199 end 1200 1201 def self.new_by_name(tree, name, *ids) 1202 TreeTagID_TBL.mutex.synchronize{ 1203 unless (obj = TreeTagID_TBL[tree.path][name]) 1204 (obj = self.allocate).instance_eval{ 1205 initialize(tree, name, ids) 1206 TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] 1207 TreeTagID_TBL[@tpath][@id] = self 1208 } 1209 end 1210 obj 1211 } 1212 end 1213 1214 def self.new(tree, *ids) 1215 TreeTagID_TBL.mutex.synchronize{ 1216 (obj = self.allocate).instance_eval{ 1217 if tree.kind_of?(Array) 1218 initialize(tree[0], tree[1], ids) 1219 else 1220 initialize(tree, nil, ids) 1221 end 1222 TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] 1223 TreeTagID_TBL[@tpath][@id] = self 1224 } 1225 obj 1226 } 1227 end 1228 1229 def initialize(tree, name, ids) 1230 @parent = @tree = tree 1231 @tpath = @parent.path 1232 1233 if name 1234 @path = @id = name 1235 else 1236 TreeTag_ID.mutex.synchronize{ 1237 @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze 1238 TreeTag_ID[1].succ! 1239 } 1240 end 1241 1242 unless ids.empty? 1243 tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)})) 1244 end 1245 end 1246 1247 def tagid(tag) 1248 if tag.kind_of?(Tk::BLT::Treeview::Node) \ 1249 || tag.kind_of?(Tk::BLT::Treeview::Tag) 1250 tag.id 1251 else 1252 tag 1253 end 1254 end 1255 private :tagid 1256 1257 def id 1258 @id 1259 end 1260 1261 def add(*ids) 1262 tk_call(@tpath, 'tag', 'add', @id, *(ids{|id| tagid(id)})) 1263 self 1264 end 1265 1266 def remove(*ids) 1267 tk_call(@tpath, 'tag', 'delete', @id, *(ids{|id| tagid(id)})) 1268 self 1269 end 1270 1271 def forget 1272 tk_call(@tpath, 'tag', 'forget', @id) 1273 self 1274 end 1275 1276 def nodes 1277 simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|id| 1278 Tk::BLT::Treeview::Node.id2obj(@tree, id) 1279 } 1280 end 1281end 1282 1283class Tk::BLT::Hiertable 1284 TkCommandNames = ['::blt::hiertable'.freeze].freeze 1285 WidgetClassName = 'Hiertable'.freeze 1286 WidgetClassNames[WidgetClassName] ||= self 1287end 1288