1# 2# tkextlib/tktable/tktable.rb 3# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) 4# 5 6require 'tk' 7require 'tk/validation' 8 9# call setup script for general 'tkextlib' libraries 10require 'tkextlib/setup.rb' 11 12# call setup script 13require 'tkextlib/tktable/setup.rb' 14 15# TkPackage.require('Tktable', '2.8') 16TkPackage.require('Tktable') 17 18module Tk 19 class TkTable < TkWindow 20 PACKAGE_NAME = 'Tktable'.freeze 21 def self.package_name 22 PACKAGE_NAME 23 end 24 25 def self.package_version 26 begin 27 TkPackage.require('Tktable') 28 rescue 29 '' 30 end 31 end 32 33 class CellTag < TkObject 34 end 35 36 module ConfigMethod 37 end 38 end 39end 40 41module Tk::TkTable::ConfigMethod 42 include TkItemConfigMethod 43 44 def __item_cget_cmd(id) # id := [ type, tagOrId ] 45 [self.path, id[0], 'cget', id[1]] 46 end 47 private :__item_cget_cmd 48 49 def __item_config_cmd(id) # id := [ type, tagOrId ] 50 [self.path, id[0], 'configure', id[1]] 51 end 52 private :__item_config_cmd 53 54 def __item_pathname(id) 55 if id.kind_of?(Array) 56 id = tagid(id[1]) 57 end 58 [self.path, id].join(';') 59 end 60 private :__item_pathname 61 62 def __item_boolval_optkeys(id) 63 super(id) << 'multiline' << 'showtext' << 'wrap' 64 end 65 private :__item_boolval_optkeys 66 67 def __item_strval_optkeys(id) 68 super(id) << 'ellipsis' 69 end 70 private :__item_strval_optkeys 71 72 def __item_val2ruby_optkeys(id) # { key=>method, ... } 73 super(id).update('window'=>proc{|k,v| window(v)}) 74 end 75 private :__item_val2ruby_optkeys 76 77 def tag_cget_tkstring(tagOrId, option) 78 itemcget_tkstring(['tag', tagid(tagOrId)], option) 79 end 80 def tag_cget(tagOrId, option) 81 itemcget(['tag', tagid(tagOrId)], option) 82 end 83 def tag_cget_strict(tagOrId, option) 84 itemcget_strict(['tag', tagid(tagOrId)], option) 85 end 86 def tag_configure(tagOrId, slot, value=None) 87 itemconfigure(['tag', tagid(tagOrId)], slot, value) 88 end 89 def tag_configinfo(tagOrId, slot=nil) 90 itemconfiginfo(['tag', tagid(tagOrId)], slot) 91 end 92 def current_tag_configinfo(tagOrId, slot=nil) 93 current_itemconfiginfo(['tag', tagid(tagOrId)], slot) 94 end 95 96 def window_cget_tkstring(tagOrId, option) 97 itemcget_tkstring(['window', tagid(tagOrId)], option) 98 end 99 def window_cget(tagOrId, option) 100 itemcget(['window', tagid(tagOrId)], option) 101 end 102 def window_cget_strict(tagOrId, option) 103 itemcget_strict(['window', tagid(tagOrId)], option) 104 end 105 def window_configure(tagOrId, slot, value=None) 106 if slot == :window || slot == 'window' 107 value = _epath(value) 108 elsif slot.kind_of?(Hash) 109 if slot.key?(:window) || slot.key?('window') 110 slot = _symbolkey2str(slot) 111 slot['window'] = _epath(slot['window']) 112 end 113 end 114 itemconfigure(['window', tagid(tagOrId)], slot, value) 115 end 116 def window_configinfo(tagOrId, slot=nil) 117 itemconfiginfo(['window', tagid(tagOrId)], slot) 118 end 119 def current_window_configinfo(tagOrId, slot=nil) 120 current_itemconfiginfo(['window', tagid(tagOrId)], slot) 121 end 122 123 private :itemcget_tkstring, :itemcget, :itemcget_strict 124 private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo 125end 126 127##################################################### 128 129class Tk::TkTable::CellTag 130 include TkTreatTagFont 131 132 CellTagID_TBL = TkCore::INTERP.create_table 133 134 (CellTag_ID = ['tktbl:celltag'.freeze, TkUtil.untrust('00000')]).instance_eval{ 135 @mutex = Mutex.new 136 def mutex; @mutex; end 137 freeze 138 } 139 140 TkCore::INTERP.init_ip_env{ 141 CellTagID_TBL.mutex.synchronize{ CellTagID_TBL.clear } 142 } 143 144 def self.id2obj(table, id) 145 tpath = table.path 146 CellTagID_TBL.mutex.synchronize{ 147 if CellTagID_TBL[tpath] 148 CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id 149 else 150 id 151 end 152 } 153 end 154 155 def initialize(parent, keys=nil) 156 @parent = @t = parent 157 @tpath - parent.path 158 CellTag_ID.mutex.synchronize{ 159 @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_) 160 CellTag_ID[1].succ! 161 } 162 CellTagID_TBL.mutex.synchronize{ 163 CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath] 164 CellTagID_TBL[@tpath][@id] = self 165 } 166 configure(keys) if keys 167 end 168 169 def id 170 @id 171 end 172 173 def destroy 174 tk_call(@tpath, 'tag', 'delete', @id) 175 CellTagID_TBL.mutex.synchronize{ 176 CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath] 177 } 178 self 179 end 180 alias delete destroy 181 182 def exist? 183 @t.tag_exist?(@id) 184 end 185 def include?(idx) 186 @t.tag_include?(@id, idx) 187 end 188 189 def add_cell(*args) 190 @t.tag_cell(@id, *args) 191 end 192 def add_col(*args) 193 @t.tag_col(@id, *args) 194 end 195 def add_row(*args) 196 @t.tag_row(@id, *args) 197 end 198 199 def raise(target=None) 200 @t.tag_raise(@id, target) 201 end 202 def lower(target=None) 203 @t.tag_lower(@id, target) 204 end 205 206 def cget_tkstring(key) 207 @t.tag_cget_tkstring(@id, key) 208 end 209 def cget(key) 210 @t.tag_cget(@id, key) 211 end 212 def cget_strict(key) 213 @t.tag_cget_strict(@id, key) 214 end 215 def configure(key, val=None) 216 @t.tag_configure(@id, key, val) 217 end 218 def configinfo(key=nil) 219 @t.tag_configinfo(@id, key) 220 end 221 def current_configinfo(key=nil) 222 @t.current_tag_configinfo(@id, key) 223 end 224end 225 226class Tk::TkTable::NamedCellTag < Tk::TkTable::CellTag 227 def self.new(parent, name, keys=nil) 228 obj = nil 229 CellTagID_TBL.mutex.synchronize{ 230 if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name] 231 obj = CellTagID_TBL[parent.path][name] 232 else 233 #super(parent, name, keys) 234 (obj = self.allocate).instance_eval{ 235 @parent = @t = parent 236 @tpath = parent.path 237 @path = @id = name 238 CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath] 239 CellTagID_TBL[@tpath][@id] = self 240 } 241 end 242 } 243 obj.configure(keys) if keys && ! keys.empty? 244 obj 245 end 246 247 def initialize(parent, name, keys=nil) 248 # dummy:: not called by 'new' method 249 @parent = @t = parent 250 @tpath = parent.path 251 @path = @id = name 252 CellTagID_TBL.mutex.synchronize{ 253 CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath] 254 CellTagID_TBL[@tpath][@id] = self 255 } 256 configure(keys) if keys && ! keys.empty? 257 end 258end 259 260##################################################### 261 262class Tk::TkTable 263 TkCommandNames = ['table'.freeze].freeze 264 WidgetClassName = 'Table'.freeze 265 WidgetClassNames[WidgetClassName] ||= self 266 267 include Scrollable 268 include Tk::TkTable::ConfigMethod 269 include Tk::ValidateConfigure 270 271 def __destroy_hook__ 272 Tk::TkTable::CelTag::CellTagID_TBL.mutex.synchronize{ 273 Tk::TkTable::CelTag::CellTagID_TBL.delete(@path) 274 } 275 end 276 277 def __boolval_optkeys 278 super() << 'autoclear' << 'flashmode' << 'invertselected' << 279 'multiline' << 'selecttitle' << 'wrap' 280 end 281 private :__boolval_optkeys 282 283 def __strval_optkeys 284 super() << 'colseparator' << 'ellipsis' << 'rowseparator' << 'sparsearray' 285 end 286 private :__strval_optkeys 287 288 289 ################################# 290 291 class BrowseCommand < TkValidateCommand 292 class ValidateArgs < TkUtil::CallbackSubst 293 KEY_TBL = [ 294 [ ?c, ?n, :column ], 295 [ ?C, ?s, :index ], 296 [ ?i, ?x, :cursor ], 297 [ ?r, ?n, :row ], 298 [ ?s, ?s, :last_index ], 299 [ ?S, ?s, :new_index ], 300 [ ?W, ?w, :widget ], 301 nil 302 ] 303 304 PROC_TBL = [ 305 [ ?n, TkComm.method(:number) ], 306 [ ?x, TkComm.method(:num_or_str) ], 307 [ ?s, TkComm.method(:string) ], 308 [ ?w, TkComm.method(:window) ], 309 nil 310 ] 311 312=begin 313 # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) 314 KEY_TBL.map!{|inf| 315 if inf.kind_of?(Array) 316 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 317 inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) 318 end 319 inf 320 } 321 322 PROC_TBL.map!{|inf| 323 if inf.kind_of?(Array) 324 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 325 end 326 inf 327 } 328=end 329 330 _setup_subst_table(KEY_TBL, PROC_TBL); 331 332 def self.ret_val(val) 333 val 334 end 335 end 336 337 def self._config_keys 338 ['browsecommand', 'browsecmd'] 339 end 340 end 341 #-------------------------------- 342 class CellCommand < TkValidateCommand 343 class ValidateArgs < TkUtil::CallbackSubst 344 KEY_TBL = [ 345 [ ?c, ?n, :column ], 346 [ ?C, ?s, :index ], 347 [ ?i, ?m, :rw_mode ], 348 [ ?r, ?n, :row ], 349 [ ?s, ?v, :value ], 350 [ ?W, ?w, :widget ], 351 nil 352 ] 353 354 PROC_TBL = [ 355 [ ?n, TkComm.method(:number) ], 356 [ ?s, TkComm.method(:string) ], 357 [ ?w, TkComm.method(:window) ], 358 [ ?m, proc{|val| (val == '0')? (:r) : (:w)} ], 359 [ ?v, proc{|val| TkComm.tk_tcl2ruby(val, true, false)} ], 360 nil 361 ] 362 363=begin 364 # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) 365 KEY_TBL.map!{|inf| 366 if inf.kind_of?(Array) 367 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 368 inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) 369 end 370 inf 371 } 372 373 PROC_TBL.map!{|inf| 374 if inf.kind_of?(Array) 375 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 376 end 377 inf 378 } 379=end 380 381 _setup_subst_table(KEY_TBL, PROC_TBL); 382 383 def self.ret_val(val) 384 TkComm._get_eval_string(val) 385 end 386 end 387 388 def self._config_keys 389 ['command'] 390 end 391 end 392 #-------------------------------- 393 class SelectionCommand < TkValidateCommand 394 class ValidateArgs < TkUtil::CallbackSubst 395 KEY_TBL = [ 396 [ ?c, ?n, :sel_columns ], 397 [ ?C, ?s, :sel_area ], 398 [ ?i, ?n, :total ], 399 [ ?r, ?n, :sel_rows ], 400 [ ?s, ?s, :value ], 401 [ ?W, ?w, :widget ], 402 nil 403 ] 404 405 PROC_TBL = [ 406 [ ?n, TkComm.method(:number) ], 407 [ ?s, TkComm.method(:string) ], 408 [ ?w, TkComm.method(:window) ], 409 nil 410 ] 411 412=begin 413 # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) 414 KEY_TBL.map!{|inf| 415 if inf.kind_of?(Array) 416 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 417 inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) 418 end 419 inf 420 } 421 422 PROC_TBL.map!{|inf| 423 if inf.kind_of?(Array) 424 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 425 end 426 inf 427 } 428=end 429 430 _setup_subst_table(KEY_TBL, PROC_TBL); 431 432 def self.ret_val(val) 433 val.to_s 434 end 435 end 436 437 def self._config_keys 438 ['selectioncommand', 'selcmd'] 439 end 440 end 441 #-------------------------------- 442 class ValidateCommand < TkValidateCommand 443 class ValidateArgs < TkUtil::CallbackSubst 444 KEY_TBL = [ 445 [ ?c, ?n, :column ], 446 [ ?C, ?s, :index ], 447 [ ?i, ?x, :cursor ], 448 [ ?r, ?n, :row ], 449 [ ?s, ?v, :current_value ], 450 [ ?S, ?v, :new_value ], 451 [ ?W, ?w, :widget ], 452 nil 453 ] 454 455 PROC_TBL = [ 456 [ ?n, TkComm.method(:number) ], 457 [ ?x, TkComm.method(:num_or_str) ], 458 [ ?s, TkComm.method(:string) ], 459 [ ?w, TkComm.method(:window) ], 460 [ ?v, proc{|val| TkComm.tk_tcl2ruby(val, true, false)} ], 461 nil 462 ] 463 464=begin 465 # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) 466 KEY_TBL.map!{|inf| 467 if inf.kind_of?(Array) 468 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 469 inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) 470 end 471 inf 472 } 473 474 PROC_TBL.map!{|inf| 475 if inf.kind_of?(Array) 476 inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) 477 end 478 inf 479 } 480=end 481 482 _setup_subst_table(KEY_TBL, PROC_TBL); 483 end 484 485 def self._config_keys 486 ['vcmd', 'validatecommand'] 487 end 488 end 489 490 ################################# 491 492 def __validation_class_list 493 super() << 494 BrowseCommand << CellCommand << SelectionCommand << ValidateCommand 495 end 496 497 Tk::ValidateConfigure.__def_validcmd(binding, BrowseCommand) 498 Tk::ValidateConfigure.__def_validcmd(binding, CellCommand) 499 Tk::ValidateConfigure.__def_validcmd(binding, SelectionCommand) 500 Tk::ValidateConfigure.__def_validcmd(binding, ValidateCommand) 501 502 ################################# 503 504 def activate(idx) 505 tk_send('activate', tagid(idx)) 506 end 507 508 def bbox(idx) 509 list(tk_send('bbox', tagid(idx))) 510 end 511 512 def border_mark(x, y) 513 simplelist(tk_send('border', 'mark', x, y)) 514 end 515 def border_mark_row(x, y) 516 tk_send('border', 'mark', x, y, 'row') 517 end 518 def border_mark_col(x, y) 519 tk_send('border', 'mark', x, y, 'col') 520 end 521 def border_dragto(x, y) 522 tk_send('border', 'dragto', x, y) 523 end 524 525 def clear_cache(first=None, last=None) 526 tk_send('clear', 'cache', tagid(first), tagid(last)) 527 self 528 end 529 def clear_sizes(first=None, last=None) 530 tk_send('clear', 'sizes', tagid(first), tagid(last)) 531 self 532 end 533 def clear_tags(first=None, last=None) 534 tk_send('clear', 'tags', tagid(first), tagid(last)) 535 self 536 end 537 def clear_all(first=None, last=None) 538 tk_send('clear', 'all', tagid(first), tagid(last)) 539 self 540 end 541 542 def curselection 543 simplelist(tk_send('curselection')) 544 end 545 def curselection=(val) 546 tk_send('curselection', val) 547 val 548 end 549 550 def curvalue 551 tk_tcl2ruby(tk_send('curvalue'), true, false) 552 end 553 def curvalue=(val) 554 tk_send('curvalue', val) 555 val 556 end 557 558 def delete_active(idx1, idx2=None) 559 tk_send('delete', 'active', tagid(idx1), tagid(idx2)) 560 self 561 end 562 def delete_cols(*args) # ?switches_array?, index, ?count? 563 params = [] 564 if args[0].kind_of?(Array) 565 switches = args.shift 566 switches.each{|k| params << "-#{k}"} 567 end 568 params << '--' 569 params << tagid(args.shift) 570 params.concat(args) 571 tk_send('delete', 'cols', *params) 572 self 573 end 574 def delete_rows(*args) # ?switches_array?, index, ?count? 575 params = [] 576 if args[0].kind_of?(Array) 577 switches = args.shift 578 switches.each{|k| params << "-#{k}"} 579 end 580 params << '--' 581 params << tagid(args.shift) 582 params.concat(args) 583 tk_send('delete', 'rows', *params) 584 self 585 end 586 587 def get(idx) 588 tk_tcl2ruby(tk_send('get', tagid(idx)), true, false) 589 end 590 def get_area(idx1, idx2) 591 simplelist(tk_send('get', tagid(idx1), tagid(idx2))).collect{|v| 592 tk_tcl2ruby(v, true, false) 593 } 594 end 595 596 def height_list 597 list(tk_send('height')) 598 end 599 def height(row) 600 number(tk_send('height', row)) 601 end 602 def set_height(*pairs) 603 tk_send('height', *(pairs.flatten)) 604 self 605 end 606 607 def hidden_list 608 simplelist(tk_send('hidden')) 609 end 610 def hidden?(idx, *args) 611 if args.empty? 612 if (ret = tk_send('hidden', tagid(idx))) == '' 613 false 614 else 615 ret 616 end 617 else 618 bool(tk_send('hidden', tagid(idx), *(args.collect{|i| tagid(i)}))) 619 end 620 end 621 622 def icursor 623 number(tk_send('icursor')) 624 end 625 def icursor_set(idx) 626 number(tk_send('icursor', tagid(idx))) 627 end 628 629 def index(idx) 630 tk_send('index', tagid(idx)) 631 end 632 def row_index(idx) 633 number(tk_send('index', tagid(idx), 'row')) 634 end 635 def col_index(idx) 636 number(tk_send('index', tagid(idx), 'col')) 637 end 638 639 def insert_active(idx, val) 640 tk_send('insert', 'active', tagid(idx), val) 641 self 642 end 643 def insert_cols(*args) # ?switches_array?, index, ?count? 644 params = [] 645 if args[0].kind_of?(Array) 646 switches = args.shift 647 switches.each{|k| params << "-#{k}"} 648 end 649 params << '--' 650 params.concat(args) 651 params << tagid(args.shift) 652 tk_send('insert', 'cols', *params) 653 self 654 end 655 def insert_rows(*args) # ?switches_array?, index, ?count? 656 params = [] 657 if args[0].kind_of?(Array) 658 switches = args.shift 659 switches.each{|k| params << "-#{k}"} 660 end 661 params << '--' 662 params << tagid(args.shift) 663 params.concat(args) 664 tk_send('insert', 'rows', *params) 665 self 666 end 667 668 # def postscript(*args) 669 # tk_send('postscript', *args) 670 # end 671 672 def reread 673 tk_send('reread') 674 self 675 end 676 677 def scan_mark(x, y) 678 tk_send('scan', 'mark', x, y) 679 self 680 end 681 def scan_dragto(x, y) 682 tk_send('scan', 'dragto', x, y) 683 self 684 end 685 686 def see(idx) 687 tk_send('see', tagid(idx)) 688 self 689 end 690 691 def selection_anchor(idx) 692 tk_send('selection', 'anchor', tagid(idx)) 693 self 694 end 695 def selection_clear(first, last=None) 696 tk_send('selection', 'clear', tagid(first), tagid(last)) 697 self 698 end 699 def selection_clear_all 700 selection_clear('all') 701 end 702 def selection_include?(idx) 703 bool(tk_send('selection', 'includes', tagid(idx))) 704 end 705 def selection_present 706 bool(tk_send('selection', 'present')) 707 end 708 def selection_set(first, last=None) 709 tk_send('selection', 'set', tagid(first), tagid(last)) 710 self 711 end 712 713 def set(*pairs) # idx, val, idx, val, ... 714 args = [] 715 0.step(pairs.size-1, 2){|i| 716 args << tagid(pairs[i]) 717 args << pairs[i+1] 718 } 719 tk_send('set', *args) 720 self 721 end 722 def set_row(*pairs) # idx, val, idx, val, ... 723 args = [] 724 0.step(pairs.size-1, 2){|i| 725 args << tagid(pairs[i]) 726 args << pairs[i+1] 727 } 728 tk_send('set', 'row', *args) 729 self 730 end 731 def set_col(*pairs) # idx, val, idx, val, ... 732 args = [] 733 0.step(pairs.size-1, 2){|i| 734 args << tagid(pairs[i]) 735 args << pairs[i+1] 736 } 737 tk_send('set', 'col', *args) 738 self 739 end 740=begin 741 def set(*pairs) # idx, val, idx, val, ... OR [idx, val], [idx, val], ... 742 if pairs[0].kind_of?(Array) 743 # [idx, val], [idx, val], ... 744 args = [] 745 pairs.each{|idx, val| args << tagid(idx) << val } 746 tk_send('set', *args) 747 else 748 # idx, val, idx, val, ... 749 args = [] 750 0.step(pairs.size-1, 2){|i| 751 args << tagid(pairs[i]) 752 args << pairs[i+1] 753 } 754 tk_send('set', *args) 755 end 756 self 757 end 758 def set_row(*pairs) 759 if pairs[0].kind_of?(Array) 760 # [idx, val], [idx, val], ... 761 args = [] 762 pairs.each{|idx, val| args << tagid(idx) << val } 763 tk_send('set', 'row', *args) 764 else 765 # idx, val, idx, val, ... 766 args = [] 767 0.step(pairs.size-1, 2){|i| 768 args << tagid(pairs[i]) 769 args << pairs[i+1] 770 } 771 tk_send('set', 'row', *args) 772 end 773 self 774 end 775 def set_col(*pairs) 776 if pairs[0].kind_of?(Array) 777 # [idx, val], [idx, val], ... 778 args = [] 779 pairs.each{|idx, val| args << idx << val } 780 tk_send('set', 'col', *args) 781 else 782 # idx, val, idx, val, ... 783 args = [] 784 0.step(pairs.size-1, 2){|i| 785 args << tagid(pairs[i]) 786 args << pairs[i+1] 787 } 788 tk_send('set', 'col', *args) 789 end 790 self 791 end 792=end 793 794 def spans 795 simplelist(tk_send('spans')).collect{|inf| 796 lst = simplelist(inf) 797 idx = lst[0] 798 rows, cols = lst[1].split(',').map!{|n| Integer(n)} 799 [idx [rows, cols]] 800 } 801 end 802 alias span_list spans 803 def span(idx) 804 lst = simplelist(tk_send('spans', tagid(idx))) 805 idx = lst[0] 806 rows, cols = lst[1].split(',').map!{|n| Integer(n)} 807 [idx [rows, cols]] 808 end 809 def set_spans(*pairs) 810 # idx, val, idx, val, ... 811 args = [] 812 0.step(pairs.size-1, 2){|i| 813 args << tagid(pairs[i]) 814 val = pairs[i+1] 815 if val.kind_of?(Array) 816 args << val.join(',') 817 else 818 args << val 819 end 820 } 821 tk_send('spans', *args) 822 self 823 end 824=begin 825 def set_spans(*pairs) 826 if pairs[0].kind_of?(Array) 827 # [idx, val], [idx, val], ... 828 args = [] 829 pairs.each{|idx, val| 830 args << tagid(idx) 831 if val.kind_of?(Array) 832 args << val.join(',') 833 else 834 args << val 835 end 836 } 837 tk_send('spans', *args) 838 else 839 # idx, val, idx, val, ... 840 args = [] 841 0.step(pairs.size-1, 2){|i| 842 args << tagid(pairs[i]) 843 val = pairs[i+1] 844 if val.kind_of?(Array) 845 args << val.join(',') 846 else 847 args << val 848 end 849 } 850 tk_send('spans', *args) 851 end 852 self 853 end 854=end 855 856 def tagid(tag) 857 if tag.kind_of?(Tk::TkTable::CellTag) 858 tag.id 859 elsif tag.kind_of?(Array) 860 if tag[0].kind_of?(Integer) && tag[1].kind_of?(Integer) 861 # [row, col] 862 tag.join(',') 863 else 864 tag 865 end 866 else 867 tag 868 end 869 end 870 871 def tagid2obj(tagid) 872 Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{ 873 if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path) 874 if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid) 875 Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid] 876 else 877 tagid 878 end 879 else 880 tagid 881 end 882 } 883 end 884 885 def tag_cell(tag, *cells) 886 tk_send('tag', 'cell', tagid(tag), *(cells.collect{|idx| tagid(idx)})) 887 self 888 end 889 def tag_reset(*cells) 890 tk_send('tag', 'cell', '', *(cells.collect{|idx| tagid(idx)})) 891 self 892 end 893 def tag_col(tag, *cols) 894 tk_send('tag', 'col', tagid(tag), *cols) 895 self 896 end 897 def tag_col_reset(*cols) 898 tk_send('tag', 'col', '', *cols) 899 self 900 end 901 def tag_delete(tag) 902 tk_send('tag', 'delete', tagid(tag)) 903 Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{ 904 if Tk::TkTable::CellTag::CellTagID_TBL[@path] 905 if tag.kind_of? Tk::TkTable::CellTag 906 Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id) 907 else 908 Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag) 909 end 910 end 911 } 912 self 913 end 914 def tag_exist?(tag) 915 bool(tk_send('tag', 'exists', tagid(tag))) 916 end 917 def tag_include?(tag, idx) 918 bool(tk_send('tag', 'includes', tagid(tag), tagid(idx))) 919 end 920 def tag_lower(tag, target=None) 921 tk_send('tag', 'lower', tagid(tag), tagid(target)) 922 self 923 end 924 def tag_names(pat=None) 925 simplelist(tk_send('tag', 'names', pat)).collect{|tag| tagid2obj(tag)} 926 end 927 def tag_raise(tag, target=None) 928 tk_send('tag', 'raise', tagid(tag), tagid(target)) 929 self 930 end 931 def tag_row(tag, *rows) 932 tk_send('tag', 'row', tagid(tag), *rows) 933 self 934 end 935 def tag_row_reset(*rows) 936 tk_send('tag', 'row', '', *rows) 937 self 938 end 939 940 def validate(idx) 941 bool(tk_send('validate', tagid(idx))) 942 end 943 944 def width_list 945 list(tk_send('width')) 946 end 947 def width(row) 948 number(tk_send('width', row)) 949 end 950 def set_width(*pairs) 951 tk_send('width', *(pairs.flatten)) 952 self 953 end 954 955 def window_delete(*args) 956 tk_send('window', 'delete', *(args.collect{|idx| tagid(idx)})) 957 self 958 end 959 def window_move(from_idx, to_idx) 960 tk_send('window', 'move', tagid(from_idx), tagid(to_idx)) 961 self 962 end 963 def window_names(pat=None) 964 simplelist(tk_send('window', 'names', pat)) 965 end 966end 967