1# RCS: @(#) $Id: filelist-bindings.tcl,v 1.28 2010/03/21 20:47:06 treectrl Exp $ 2 3bind TreeCtrlFileList <Double-ButtonPress-1> { 4 TreeCtrl::FileListEditCancel %W 5 TreeCtrl::DoubleButton1 %W %x %y 6 break 7} 8bind TreeCtrlFileList <Control-ButtonPress-1> { 9 set TreeCtrl::Priv(selectMode) toggle 10 TreeCtrl::FileListButton1 %W %x %y 11 break 12} 13bind TreeCtrlFileList <Shift-ButtonPress-1> { 14 set TreeCtrl::Priv(selectMode) add 15 TreeCtrl::FileListButton1 %W %x %y 16 break 17} 18bind TreeCtrlFileList <ButtonPress-1> { 19 set TreeCtrl::Priv(selectMode) set 20 TreeCtrl::FileListButton1 %W %x %y 21 break 22} 23bind TreeCtrlFileList <Button1-Motion> { 24 TreeCtrl::FileListMotion1 %W %x %y 25 break 26} 27bind TreeCtrlFileList <Button1-Leave> { 28 TreeCtrl::FileListLeave1 %W %x %y 29 break 30} 31bind TreeCtrlFileList <ButtonRelease-1> { 32 TreeCtrl::FileListRelease1 %W %x %y 33 break 34} 35 36## Bindings for the Entry widget used for editing 37 38# Accept edit when we lose the focus 39bind TreeCtrlEntry <FocusOut> { 40 if {[winfo ismapped %W]} { 41 TreeCtrl::EditClose [winfo parent %W] entry 1 0 42 } 43} 44 45# Accept edit on <Return> 46bind TreeCtrlEntry <KeyPress-Return> { 47 TreeCtrl::EditClose [winfo parent %W] entry 1 1 48 break 49} 50 51# Cancel edit on <Escape>, use break as we are doing a "closing" action 52# and don't want that propagated upwards 53bind TreeCtrlEntry <KeyPress-Escape> { 54 TreeCtrl::EditClose [winfo parent %W] entry 0 1 55 break 56} 57 58## Bindings for the Text widget used for editing 59 60# Accept edit when we lose the focus 61bind TreeCtrlText <FocusOut> { 62 if {[winfo ismapped %W]} { 63 TreeCtrl::EditClose [winfo parent %W] text 1 0 64 } 65} 66 67# Accept edit on <Return> 68bind TreeCtrlText <KeyPress-Return> { 69 TreeCtrl::EditClose [winfo parent %W] text 1 1 70 break 71} 72 73# Cancel edit on <Escape>, use break as we are doing a "closing" action 74# and don't want that propagated upwards 75bind TreeCtrlText <KeyPress-Escape> { 76 TreeCtrl::EditClose [winfo parent %W] text 0 1 77 break 78} 79 80namespace eval TreeCtrl { 81 variable Priv 82 83 # Number of milliseconds after clicking a selected item before the Edit 84 # widget appears. 85 set Priv(edit,delay) 500 86 87 # Try to deal with people importing ttk::entry into the global namespace; 88 # we want tk::entry 89 if {[llength [info commands ::tk::entry]]} { 90 set Priv(entryCmd) ::tk::entry 91 } else { 92 set Priv(entryCmd) ::entry 93 } 94} 95 96# ::TreeCtrl::IsSensitive 97# 98# Returns 1 if the given window coordinates are over an element that should 99# respond to mouse clicks. The list of elements that respond to mouse clicks 100# is set by calling ::TreeCtrl::SetSensitive. 101# 102# Arguments: 103# T The treectrl widget. 104# x Window coord of pointer. 105# y Window coord of pointer. 106 107proc ::TreeCtrl::IsSensitive {T x y} { 108 variable Priv 109 set id [$T identify $x $y] 110 if {[lindex $id 0] ne "item" || [llength $id] != 6} { 111 return 0 112 } 113 lassign $id where item arg1 arg2 arg3 arg4 114 if {![$T item enabled $item]} { 115 return 0 116 } 117 foreach list $Priv(sensitive,$T) { 118 set eList [lassign $list C S] 119 if {[$T column compare $arg2 != $C]} continue 120 if {[$T item style set $item $C] ne $S} continue 121 if {[lsearch -exact $eList $arg4] == -1} continue 122 return 1 123 } 124 return 0 125} 126 127# ::TreeCtrl::FileListButton1 128# 129# Handle <ButtonPress-1>. 130# 131# Arguments: 132# T The treectrl widget. 133# x Window coord of pointer. 134# y Window coord of pointer. 135 136proc ::TreeCtrl::FileListButton1 {T x y} { 137 variable Priv 138 focus $T 139 set id [$T identify $x $y] 140 set marquee 0 141 set Priv(buttonMode) "" 142 foreach e {text entry} { 143 if {[winfo exists $T.$e] && [winfo ismapped $T.$e]} { 144 EditClose $T $e 1 0 145 } 146 } 147 FileListEditCancel $T 148 # Click outside any item 149 if {$id eq ""} { 150 set marquee 1 151 152 # Click in header 153 } elseif {[lindex $id 0] eq "header"} { 154 ButtonPress1 $T $x $y 155 156 # Click in item 157 } else { 158 lassign $id where item arg1 arg2 arg3 arg4 159 switch $arg1 { 160 button - 161 line { 162 ButtonPress1 $T $x $y 163 } 164 column { 165 if {[IsSensitive $T $x $y]} { 166 set Priv(drag,motion) 0 167 set Priv(drag,click,x) $x 168 set Priv(drag,click,y) $y 169 set Priv(drag,x) [$T canvasx $x] 170 set Priv(drag,y) [$T canvasy $y] 171 set Priv(drop) "" 172 set Priv(drag,wasSel) [$T selection includes $item] 173 set Priv(drag,C) $arg2 174 set Priv(drag,E) $arg4 175 $T activate $item 176 if {$Priv(selectMode) eq "add"} { 177 BeginExtend $T $item 178 } elseif {$Priv(selectMode) eq "toggle"} { 179 BeginToggle $T $item 180 } elseif {![$T selection includes $item]} { 181 BeginSelect $T $item 182 } 183 184 # Changing the selection might change the list 185 if {[$T item id $item] eq ""} return 186 187 # Click selected item to drag 188 if {[$T selection includes $item]} { 189 set Priv(buttonMode) drag 190 } 191 } else { 192 set marquee 1 193 } 194 } 195 } 196 } 197 if {$marquee} { 198 set Priv(buttonMode) marquee 199 if {$Priv(selectMode) ne "set"} { 200 set Priv(selection) [$T selection get] 201 } else { 202 $T selection clear 203 set Priv(selection) {} 204 } 205 MarqueeBegin $T $x $y 206 } 207 return 208} 209 210# ::TreeCtrl::FileListMotion1 211# 212# Override default <Button1-Motion> to handle "drag" and "marquee". 213# 214# Arguments: 215# T The treectrl widget. 216# x Window coord of pointer. 217# y Window coord of pointer. 218 219proc ::TreeCtrl::FileListMotion1 {T x y} { 220 variable Priv 221 if {![info exists Priv(buttonMode)]} return 222 switch $Priv(buttonMode) { 223 "drag" - 224 "marquee" { 225 set Priv(autoscan,command,$T) {FileListMotion %T %x %y} 226 AutoScanCheck $T $x $y 227 FileListMotion $T $x $y 228 } 229 default { 230 Motion1 $T $x $y 231 } 232 } 233 return 234} 235 236# ::TreeCtrl::FileListMotion 237# 238# Handle <Button1-Motion>. 239# 240# Arguments: 241# T The treectrl widget. 242# x Window coord of pointer. 243# y Window coord of pointer. 244 245proc ::TreeCtrl::FileListMotion {T x y} { 246 variable Priv 247 if {![info exists Priv(buttonMode)]} return 248 switch $Priv(buttonMode) { 249 "marquee" { 250 MarqueeUpdate $T $x $y 251 set select $Priv(selection) 252 set deselect {} 253 254 # Check items covered by the marquee 255 foreach list [$T marque identify] { 256 set item [lindex $list 0] 257 if {![$T item enabled $item]} continue 258 259 # Check covered columns in this item 260 foreach sublist [lrange $list 1 end] { 261 set column [lindex $sublist 0] 262 set ok 0 263 264 # Check covered elements in this column 265 foreach E [lrange $sublist 1 end] { 266 foreach sList $Priv(sensitive,$T) { 267 set sEList [lassign $sList sC sS] 268 if {[$T column compare $column != $sC]} continue 269 if {[$T item style set $item $sC] ne $sS} continue 270 if {[lsearch -exact $sEList $E] == -1} continue 271 set ok 1 272 break 273 } 274 } 275 # Some sensitive elements in this column are covered 276 if {$ok} { 277 278 # Toggle selected status 279 if {$Priv(selectMode) eq "toggle"} { 280 set i [lsearch -exact $Priv(selection) $item] 281 if {$i == -1} { 282 lappend select $item 283 } else { 284 set i [lsearch -exact $select $item] 285 set select [lreplace $select $i $i] 286 } 287 } else { 288 lappend select $item 289 } 290 } 291 } 292 } 293 $T selection modify $select all 294 } 295 "drag" { 296 if {!$Priv(drag,motion)} { 297 # Detect initial mouse movement 298 if {(abs($x - $Priv(drag,click,x)) <= 4) && 299 (abs($y - $Priv(drag,click,y)) <= 4)} return 300 301 set Priv(selection) [$T selection get] 302 set Priv(drop) "" 303 $T dragimage clear 304 # For each selected item, add some elements to the dragimage 305 foreach I $Priv(selection) { 306 foreach list $Priv(dragimage,$T) { 307 set EList [lassign $list C S] 308 if {[$T item style set $I $C] eq $S} { 309 eval $T dragimage add $I $C $EList 310 } 311 } 312 } 313 set Priv(drag,motion) 1 314 TryEvent $T Drag begin {} 315 } 316 317 # Find the element under the cursor 318 set drop "" 319 set id [$T identify $x $y] 320 if {[IsSensitive $T $x $y]} { 321 set item [lindex $id 1] 322 # If the item is not in the pre-drag selection 323 # (i.e. not being dragged) and it is a directory, 324 # see if we can drop on it 325 if {[lsearch -exact $Priv(selection) $item] == -1} { 326 if {[$T item order $item -visible] < $Priv(DirCnt,$T)} { 327 set drop $item 328 # We can drop if dragged item isn't an ancestor 329 foreach item2 $Priv(selection) { 330 if {[$T item isancestor $item2 $item]} { 331 set drop "" 332 break 333 } 334 } 335 } 336 } 337 } 338 339 # Select the directory under the cursor (if any) and deselect 340 # the previous drop-directory (if any) 341 $T selection modify $drop $Priv(drop) 342 set Priv(drop) $drop 343 344 # Show the dragimage in its new position 345if {0 && [$T dragimage cget -style] ne ""} { 346 set x [$T canvasx $x] 347 set y [$T canvasy $y] 348} else { 349 set x [expr {[$T canvasx $x] - $Priv(drag,x)}] 350 set y [expr {[$T canvasy $y] - $Priv(drag,y)}] 351} 352 $T dragimage offset $x $y 353 $T dragimage configure -visible yes 354 } 355 default { 356 Motion1 $T $x $y 357 } 358 } 359 return 360} 361 362# ::TreeCtrl::FileListLeave1 363# 364# Handle <Button1-Leave>. 365# 366# Arguments: 367# T The treectrl widget. 368# x Window coord of pointer. 369# y Window coord of pointer. 370 371proc ::TreeCtrl::FileListLeave1 {T x y} { 372 variable Priv 373 # This gets called when I click the mouse on Unix, and buttonMode is unset 374 if {![info exists Priv(buttonMode)]} return 375 switch $Priv(buttonMode) { 376 default { 377 Leave1 $T $x $y 378 } 379 } 380 return 381} 382 383# ::TreeCtrl::FileListRelease1 384# 385# Handle <Button1-Release>. 386# 387# Arguments: 388# T The treectrl widget. 389# x Window coord of pointer. 390# y Window coord of pointer. 391 392proc ::TreeCtrl::FileListRelease1 {T x y} { 393 variable Priv 394 if {![info exists Priv(buttonMode)]} return 395 switch $Priv(buttonMode) { 396 "marquee" { 397 AutoScanCancel $T 398 MarqueeEnd $T $x $y 399 } 400 "drag" { 401 AutoScanCancel $T 402 403 # Some dragging occurred 404 if {$Priv(drag,motion)} { 405 $T dragimage configure -visible no 406 if {$Priv(drop) ne ""} { 407 $T selection modify {} $Priv(drop) 408 TryEvent $T Drag receive \ 409 [list I $Priv(drop) l $Priv(selection)] 410 } 411 TryEvent $T Drag end {} 412 } elseif {$Priv(selectMode) eq "toggle"} { 413 # don't rename 414 415 # Clicked/released a selected item, but didn't drag 416 } elseif {$Priv(drag,wasSel)} { 417 set I [$T item id active] 418 set C $Priv(drag,C) 419 set E $Priv(drag,E) 420 set S [$T item style set $I $C] 421 set ok 0 422 foreach list $Priv(edit,$T) { 423 set eEList [lassign $list eC eS] 424 if {[$T column compare $C != $eC]} continue 425 if {$S ne $eS} continue 426 if {[lsearch -exact $eEList $E] == -1} continue 427 set ok 1 428 break 429 } 430 if {$ok} { 431 FileListEditCancel $T 432 set Priv(editId,$T) \ 433 [after $Priv(edit,delay) [list ::TreeCtrl::FileListEdit $T $I $C $E]] 434 } 435 } 436 } 437 default { 438 Release1 $T $x $y 439 } 440 } 441 set Priv(buttonMode) "" 442 return 443} 444 445# ::TreeCtrl::FileListEdit 446# 447# Displays an Entry or Text widget to allow the user to edit the specified 448# text element. 449# 450# Arguments: 451# T The treectrl widget. 452# I Item. 453# C Column. 454# E Element. 455 456proc ::TreeCtrl::FileListEdit {T I C E} { 457 variable Priv 458 array unset Priv editId,$T 459 460 set lines [$T item element cget $I $C $E -lines] 461 if {$lines eq ""} { 462 set lines [$T element cget $E -lines] 463 } 464 465 # Scroll item into view 466 $T see $I ; update 467 468 # Multi-line edit 469 if {$lines ne "1"} { 470 scan [$T item bbox $I $C] "%d %d %d %d" x1 y1 x2 y2 471 set S [$T item style set $I $C] 472 set padx [$T style layout $S $E -padx] 473 if {[llength $padx] == 2} { 474 lassign $padx padw pade 475 } else { 476 set pade [set padw $padx] 477 } 478 foreach E2 [$T style elements $S] { 479 if {[lsearch -exact [$T style layout $S $E2 -union] $E] == -1} continue 480 foreach option {-padx -ipadx} { 481 set pad [$T style layout $S $E2 $option] 482 if {[llength $pad] == 2} { 483 incr padw [lindex $pad 0] 484 incr pade [lindex $pad 1] 485 } else { 486 incr padw $pad 487 incr pade $pad 488 } 489 } 490 } 491 TextExpanderOpen $T $I $C $E [expr {$x2 - $x1 - $padw - $pade}] 492 493 # Single-line edit 494 } else { 495 EntryExpanderOpen $T $I $C $E 496 } 497 498 TryEvent $T Edit begin [list I $I C $C E $E] 499 500 return 501} 502 503# ::TreeCtrl::FileListEditCancel 504# 505# Aborts any scheduled display of the text-edit widget. 506# 507# Arguments: 508# T The treectrl widget. 509 510proc ::TreeCtrl::FileListEditCancel {T} { 511 variable Priv 512 if {[info exists Priv(editId,$T)]} { 513 after cancel $Priv(editId,$T) 514 array unset Priv editId,$T 515 } 516 return 517} 518 519# ::TreeCtrl::SetDragImage 520# 521# Specifies the list of elements that should be added to the dragimage. 522# 523# Arguments: 524# T The treectrl widget. 525# listOfLists {{column style element ...} {column style element ...}} 526 527proc ::TreeCtrl::SetDragImage {T listOfLists} { 528 variable Priv 529 foreach list $listOfLists { 530 set elements [lassign $list column style] 531 if {[$T column id $column] eq ""} { 532 error "column \"$column\" doesn't exist" 533 } 534 if {[lsearch -exact [$T style names] $style] == -1} { 535 error "style \"$style\" doesn't exist" 536 } 537 foreach element $elements { 538 if {[lsearch -exact [$T element names] $element] == -1} { 539 error "element \"$element\" doesn't exist" 540 } 541 } 542 } 543 set Priv(dragimage,$T) $listOfLists 544 return 545} 546 547# ::TreeCtrl::SetEditable 548# 549# Specifies the list of text elements that can be edited. 550# 551# Arguments: 552# T The treectrl widget. 553# listOfLists {{column style element ...} {column style element ...}} 554 555proc ::TreeCtrl::SetEditable {T listOfLists} { 556 variable Priv 557 foreach list $listOfLists { 558 set elements [lassign $list column style] 559 if {[$T column id $column] eq ""} { 560 error "column \"$column\" doesn't exist" 561 } 562 if {[lsearch -exact [$T style names] $style] == -1} { 563 error "style \"$style\" doesn't exist" 564 } 565 foreach element $elements { 566 if {[lsearch -exact [$T element names] $element] == -1} { 567 error "element \"$element\" doesn't exist" 568 } 569 if {[$T element type $element] ne "text"} { 570 error "element \"$element\" is not of type \"text\"" 571 } 572 } 573 } 574 set Priv(edit,$T) $listOfLists 575 return 576} 577 578# ::TreeCtrl::SetSensitive 579# 580# Specifies the list of elements that respond to mouse clicks. 581# 582# Arguments: 583# T The treectrl widget. 584# listOfLists {{column style element ...} {column style element ...}} 585 586proc ::TreeCtrl::SetSensitive {T listOfLists} { 587 variable Priv 588 foreach list $listOfLists { 589 set elements [lassign $list column style] 590 if {[$T column id $column] eq ""} { 591 error "column \"$column\" doesn't exist" 592 } 593 if {[lsearch -exact [$T style names] $style] == -1} { 594 error "style \"$style\" doesn't exist" 595 } 596 foreach element $elements { 597 if {[lsearch -exact [$T element names] $element] == -1} { 598 error "element \"$element\" doesn't exist" 599 } 600 } 601 } 602 set Priv(sensitive,$T) $listOfLists 603 return 604} 605 606# ::TreeCtrl::EntryOpen 607# 608# Display a ::tk::entry so the user can edit the specified text element. 609# 610# Arguments: 611# T The treectrl widget. 612# item Item. 613# column Column. 614# element Element. 615 616proc ::TreeCtrl::EntryOpen {T item column element} { 617 618 variable Priv 619 620 set Priv(entry,$T,item) $item 621 set Priv(entry,$T,column) $column 622 set Priv(entry,$T,element) $element 623 set Priv(entry,$T,focus) [focus] 624 625 # Get window coords of the Element 626 scan [$T item bbox $item $column $element] "%d %d" x y 627 628 # Get the font used by the Element 629 set font [$T item element perstate $item $column $element -font] 630 if {$font eq ""} { 631 set font [$T cget -font] 632 } 633 634 # Get the text used by the Element. Could check master Element too. 635 set text [$T item element cget $item $column $element -text] 636 637 # Create the Entry widget if needed 638 set e $T.entry 639 if {[winfo exists $e]} { 640 $e delete 0 end 641 } else { 642 $Priv(entryCmd) $e -borderwidth 1 -relief solid -highlightthickness 0 643 bindtags $e [linsert [bindtags $e] 1 TreeCtrlEntry] 644 } 645 646 # Pesky MouseWheel 647 $T notify bind $e <Scroll> { TreeCtrl::EditClose %T entry 0 1 } 648 649 $e configure -font $font 650 $e insert end $text 651 $e selection range 0 end 652 653 set ebw [$e cget -borderwidth] 654 set ex [expr {$x - $ebw - 1}] 655 place $e -x $ex -y [expr {$y - $ebw - 1}] -bordermode outside 656 657 # Make the Entry as wide as the text plus "W" but keep it within the 658 # TreeCtrl borders 659 set width [font measure $font ${text}W] 660 set width [expr {$width + ($ebw + 1) * 2}] 661 scan [$T contentbox] "%d %d %d %d" left top right bottom 662 if {$ex + $width > $right} { 663 set width [expr {$right - $ex}] 664 } 665 scan [$T item bbox $item $column] "%d %d %d %d" left top right bottom 666 if {$ex + $width > $right} { 667 set width [expr {$right - $ex}] 668 } 669 place configure $e -width $width 670 671 focus $e 672 673 return 674} 675 676# ::TreeCtrl::EntryExpanderOpen 677# 678# Display a ::tk::entry so the user can edit the specified text element. 679# Like EntryOpen, but Entry widget expands/shrinks during typing. 680# 681# Arguments: 682# T The treectrl widget. 683# item Item. 684# column Column. 685# element Element. 686 687proc ::TreeCtrl::EntryExpanderOpen {T item column element} { 688 689 variable Priv 690 691 set Priv(entry,$T,item) $item 692 set Priv(entry,$T,column) $column 693 set Priv(entry,$T,element) $element 694 set Priv(entry,$T,focus) [focus] 695 696 # Get window coords of the Element 697 scan [$T item bbox $item $column $element] "%d %d" x y 698 699 # Get the font used by the Element 700 set font [$T item element perstate $item $column $element -font] 701 if {$font eq ""} { 702 set font [$T cget -font] 703 } 704 705 set Priv(entry,$T,font) $font 706 707 # Get the text used by the Element. Could check master Element too. 708 set text [$T item element cget $item $column $element -text] 709 710 # Create the Entry widget if needed 711 set e $T.entry 712 if {[winfo exists $e]} { 713 $e delete 0 end 714 } else { 715 $Priv(entryCmd) $e -borderwidth 1 -highlightthickness 0 \ 716 -selectborderwidth 0 -relief solid 717 bindtags $e [linsert [bindtags $e] 1 TreeCtrlEntry] 718 719 # Resize as user types 720 bind $e <KeyPress> { 721 after idle [list TreeCtrl::EntryExpanderKeypress [winfo parent %W]] 722 } 723 } 724 725 # Pesky MouseWheel 726 $T notify bind $e <Scroll> { TreeCtrl::EditClose %T entry 0 1 } 727 728 $e configure -font $font -background [$T cget -background] 729 $e insert end $text 730 $e selection range 0 end 731 732 set ebw [$e cget -borderwidth] 733 set ex [expr {$x - $ebw - 1}] 734 place $e -x $ex -y [expr {$y - $ebw - 1}] \ 735 -bordermode outside 736 737 # Make the Entry as wide as the text plus "W" but keep it within the 738 # TreeCtrl borders 739 set width [font measure $font ${text}W] 740 set width [expr {$width + ($ebw + 1) * 2}] 741 scan [$T contentbox] "%d %d %d %d" left top right bottom 742 if {$ex + $width > $right} { 743 set width [expr {$right - $ex}] 744 } 745 place configure $e -width $width 746 747 focus $e 748 749 return 750} 751 752# ::TreeCtrl::EditClose 753# 754# Hides the text-edit widget and restores the focus if needed. 755# Generates <Edit-accept> and <Edit-end> events as needed. 756# 757# Arguments: 758# T The treectrl widget. 759# type "entry" or "text". 760# accept 0/1: should an <Edit-accept> event be generated. 761# refocus 0/1: should the focus be restored to what it was before editing. 762 763proc ::TreeCtrl::EditClose {T type accept {refocus 0}} { 764 variable Priv 765 766 set w $T.$type 767 # We need the double-idle to get winfo ismapped to report properly 768 # so this don't get the FocusOut following Escape immediately 769 update idletasks 770 place forget $w 771 focus $T 772 update idletasks 773 774 if {$accept} { 775 if {$type eq "entry"} { 776 set t [$w get] 777 } else { 778 set t [$w get 1.0 end-1c] 779 } 780 TryEvent $T Edit accept \ 781 [list I $Priv($type,$T,item) C $Priv($type,$T,column) \ 782 E $Priv($type,$T,element) t $t] 783 } 784 785 $T notify unbind $w <Scroll> 786 787 TryEvent $T Edit end \ 788 [list I $Priv($type,$T,item) C $Priv($type,$T,column) \ 789 E $Priv($type,$T,element)] 790 791 if {$refocus} { 792 focus $Priv($type,$T,focus) 793 } 794 795 return 796} 797 798# ::TreeCtrl::EntryExpanderKeypress 799# 800# Maintains the width of the text-edit widget during typing. 801# 802# Arguments: 803# T The treectrl widget. 804 805proc ::TreeCtrl::EntryExpanderKeypress {T} { 806 807 variable Priv 808 809 set font $Priv(entry,$T,font) 810 set text [$T.entry get] 811 set ebw [$T.entry cget -borderwidth] 812 set ex [winfo x $T.entry] 813 814 set width [font measure $font ${text}W] 815 set width [expr {$width + ($ebw + 1) * 2}] 816 817 scan [$T contentbox] "%d %d %d %d" left top right bottom 818 if {$ex + $width > $right} { 819 set width [expr {$right - $ex}] 820 } 821 822 place configure $T.entry -width $width 823 824 return 825} 826 827# ::TreeCtrl::TextOpen 828# 829# Display a ::tk::text so the user can edit the specified text element. 830# 831# Arguments: 832# T The treectrl widget. 833# item Item. 834# column Column. 835# element Element. 836# width unused. 837# height unused. 838 839proc ::TreeCtrl::TextOpen {T item column element {width 0} {height 0}} { 840 variable Priv 841 842 set Priv(text,$T,item) $item 843 set Priv(text,$T,column) $column 844 set Priv(text,$T,element) $element 845 set Priv(text,$T,focus) [focus] 846 847 # Get window coords of the Element 848 scan [$T item bbox $item $column $element] "%d %d %d %d" x1 y1 x2 y2 849 850 # Get the font used by the Element 851 set font [$T item element perstate $item $column $element -font] 852 if {$font eq ""} { 853 set font [$T cget -font] 854 } 855 856 # Get the text used by the Element. Could check master Element too. 857 set text [$T item element cget $item $column $element -text] 858 859 set justify [$T element cget $element -justify] 860 if {$justify eq ""} { 861 set justify left 862 } 863 864 set wrap [$T element cget $element -wrap] 865 if {$wrap eq ""} { 866 set wrap word 867 } 868 869 # Create the Text widget if needed 870 set w $T.text 871 if {[winfo exists $w]} { 872 $w delete 1.0 end 873 } else { 874 text $w -borderwidth 1 -highlightthickness 0 -relief solid 875 bindtags $w [linsert [bindtags $w] 1 TreeCtrlText] 876 } 877 878 # Pesky MouseWheel 879 $T notify bind $w <Scroll> { TreeCtrl::EditClose %T text 0 1 } 880 881 $w tag configure TAG -justify $justify 882 $w configure -font $font -background [$T cget -background] -wrap $wrap 883 $w insert end $text 884 $w tag add sel 1.0 end 885 $w tag add TAG 1.0 end 886 887 set tbw [$w cget -borderwidth] 888 set tx [expr {$x1 - $tbw - 1}] 889 place $w -x $tx -y [expr {$y1 - $tbw - 1}] \ 890 -width [expr {$x2 - $x1 + ($tbw + 1) * 2}] \ 891 -height [expr {$y2 - $y1 + ($tbw + 1) * 2}] \ 892 -bordermode outside 893 894 focus $w 895 896 return 897} 898 899# ::TreeCtrl::TextExpanderOpen 900# 901# Display a ::tk::text so the user can edit the specified text element. 902# Like TextOpen, but Text widget expands/shrinks during typing. 903# 904# Arguments: 905# T The treectrl widget. 906# item Item. 907# column Column. 908# element Element. 909# width Width of the text element. 910 911proc ::TreeCtrl::TextExpanderOpen {T item column element width} { 912 913 variable Priv 914 915 set Priv(text,$T,item) $item 916 set Priv(text,$T,column) $column 917 set Priv(text,$T,element) $element 918 set Priv(text,$T,focus) [focus] 919 920 # Get window coords of the Element 921 scan [$T item bbox $item $column $element] "%d %d %d %d" x1 y1 x2 y2 922 923 set Priv(text,$T,center) [expr {$x1 + ($x2 - $x1) / 2}] 924 925 # Get the font used by the Element 926 set font [$T item element perstate $item $column $element -font] 927 if {$font eq ""} { 928 set font [$T cget -font] 929 } 930 931 # Get the text used by the Element. Could check master Element too. 932 set text [$T item element cget $item $column $element -text] 933 934 set justify [$T element cget $element -justify] 935 if {$justify eq ""} { 936 set justify left 937 } 938 939 set wrap [$T element cget $element -wrap] 940 if {$wrap eq ""} { 941 set wrap word 942 } 943 944 # Create the Text widget if needed 945 set w $T.text 946 if {[winfo exists $w]} { 947 $w delete 1.0 end 948 } else { 949 text $w -borderwidth 1 -highlightthickness 0 \ 950 -selectborderwidth 0 -relief solid 951 bindtags $w [linsert [bindtags $w] 1 TreeCtrlText] 952 953 # Resize as user types 954 bind $w <KeyPress> { 955 after idle TreeCtrl::TextExpanderKeypress [winfo parent %W] 956 } 957 } 958 959 # Pesky MouseWheel 960 $T notify bind $w <Scroll> { TreeCtrl::EditClose %T text 0 1 } 961 962 $w tag configure TAG -justify $justify 963 $w configure -font $font -background [$T cget -background] -wrap $wrap 964 $w insert end $text 965 $w tag add sel 1.0 end 966 $w tag add TAG 1.0 end 967 968 set Priv(text,$T,font) $font 969 set Priv(text,$T,justify) $justify 970 set Priv(text,$T,width) $width 971 972 scan [textlayout $font $text -justify $justify -width $width] \ 973 "%d %d" width height 974 975 set tbw [$w cget -borderwidth] 976 incr tbw 977 place $w -x [expr {$x1 - $tbw}] -y [expr {$y1 - $tbw}] \ 978 -width [expr {$width + $tbw * 2}] \ 979 -height [expr {$height + $tbw * 2}] \ 980 -bordermode outside 981 982 focus $w 983 984 return 985} 986 987# ::TreeCtrl::TextExpanderKeypress 988# 989# Maintains the size of the text-edit widget during typing. 990# 991# Arguments: 992# T The treectrl widget. 993 994proc ::TreeCtrl::TextExpanderKeypress {T} { 995 996 variable Priv 997 998 set font $Priv(text,$T,font) 999 set justify $Priv(text,$T,justify) 1000 set width $Priv(text,$T,width) 1001 set center $Priv(text,$T,center) 1002 1003 set text [$T.text get 1.0 end-1c] 1004 1005 scan [textlayout $font $text -justify $justify -width $width] \ 1006 "%d %d" width height 1007 1008 set tbw [$T.text cget -borderwidth] 1009 incr tbw 1010 place configure $T.text \ 1011 -x [expr {$center - ($width + $tbw * 2) / 2}] \ 1012 -width [expr {$width + $tbw * 2}] \ 1013 -height [expr {$height + $tbw * 2}] 1014 1015 $T.text tag add TAG 1.0 end 1016 1017 return 1018} 1019 1020