# hiertable.tcl # ---------------------------------------------------------------------- # Bindings for the BLT hiertable widget # ---------------------------------------------------------------------- # AUTHOR: George Howlett # Bell Labs Innovations for Lucent Technologies # gah@lucent.com # http://www.tcltk.com/blt # # RCS: $Id: hiertable.tcl,v 1.1.1.1 2009/05/09 16:27:21 pcmacdon Exp $ # # ---------------------------------------------------------------------- # Copyright (c) 1998 Lucent Technologies, Inc. # ====================================================================== # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies and that # both that the copyright notice and warranty disclaimer appear in # supporting documentation, and that the names of Lucent Technologies # any of their entities not be used in advertising or publicity # pertaining to distribution of the software without specific, written # prior permission. # # Lucent Technologies disclaims all warranties with regard to this # software, including all implied warranties of merchantability and # fitness. In no event shall Lucent be liable for any special, indirect # or consequential damages or any damages whatsoever resulting from loss # of use, data or profits, whether in an action of contract, negligence # or other tortuous action, arising out of or in connection with the use # or performance of this software. # # ====================================================================== namespace eval blt::Hiertable { variable afterId "" variable scroll 0 variable column "" variable space off variable x 0 variable y 0 } # # ButtonPress assignments # # B1-Enter start auto-scrolling # B1-Leave stop auto-scrolling # ButtonPress-2 start scan # B2-Motion adjust scan # ButtonRelease-2 stop scan # bind Hiertable { set blt::Hiertable::cursor [%W cget -cursor] %W configure -cursor hand1 %W scan mark %x %y } bind Hiertable { %W scan dragto %x %y } bind Hiertable { %W configure -cursor $blt::Hiertable::cursor } bind Hiertable { if { $blt::Hiertable::scroll } { blt::Hiertable::AutoScroll %W } } bind Hiertable { after cancel $blt::Hiertable::afterId } # # KeyPress assignments # # Up # Down # Shift-Up # Shift-Down # Prior (PageUp) # Next (PageDn) # Left # Right # space Start selection toggle of entry currently with focus. # Return Start selection toggle of entry currently with focus. # Home # End # F1 # F2 # ASCII char Go to next open entry starting with character. # # KeyRelease # # space Stop selection toggle of entry currently with focus. # Return Stop selection toggle of entry currently with focus. bind Hiertable { blt::Hiertable::MoveFocus %W up if { $blt::Hiertable::space } { %W selection toggle focus } } bind Hiertable { blt::Hiertable::MoveFocus %W down if { $blt::Hiertable::space } { %W selection toggle focus } } bind Hiertable { blt::Hiertable::MoveFocus %W prevsibling } bind Hiertable { blt::Hiertable::MoveFocus %W nextsibling } bind Hiertable { blt::Hiertable::MovePage %W top } bind Hiertable { blt::Hiertable::MovePage %W bottom } bind Hiertable { %W close focus } bind Hiertable { %W open focus %W see focus -anchor w } bind Hiertable { if { [%W cget -selectmode] == "single" } { if { [%W selection includes focus] } { %W selection clearall } else { %W selection clearall %W selection set focus } } else { %W selection toggle focus } set blt::Hiertable::space on } bind Hiertable { set blt::Hiertable::space off } bind Hiertable { blt::Hiertable::MoveFocus %W focus set blt::Hiertable::space on } bind Hiertable { set blt::Hiertable::space off } bind Hiertable { blt::Hiertable::NextMatchingEntry %W %A } bind Hiertable { blt::Hiertable::MoveFocus %W top } bind Hiertable { blt::Hiertable::MoveFocus %W bottom } bind Hiertable { %W open -r root } bind Hiertable { eval %W close -r [%W entry children root] } # # Differences between "current" and nearest. # # set index [$widget index current] # set index [$widget nearest $x $y] # # o Nearest gives you the closest entry. # o current is "" if # 1) the pointer isn't over an entry. # 2) the pointer is over a open/close button. # 3) # # # ---------------------------------------------------------------------- # # USAGE: blt::Hiertable::Init # # Invoked by internally by Hiertable_Init routine. Initializes the # default bindings for the hiertable widget entries. These are local # to the widget, so they can't be set through the widget's class # bind tags. # # Arguments: hiertable hierarchy widget # # ---------------------------------------------------------------------- proc blt::Hiertable::Init { widget } { # # Active entry bindings # $widget bind Entry { %W entry highlight current } $widget bind Entry { %W entry highlight "" } # # Button bindings # $widget button bind all { %W see -anchor nw current %W toggle current } $widget button bind all { %W button highlight current } $widget button bind all { %W button highlight "" } # # ButtonPress-1 # # Performs the following operations: # # 1. Clears the previous selection. # 2. Selects the current entry. # 3. Sets the focus to this entry. # 4. Scrolls the entry into view. # 5. Sets the selection anchor to this entry, just in case # this is "multiple" mode. # $widget bind Entry { blt::Hiertable::SetSelectionAnchor %W current set blt::Hiertable::scroll 1 } $widget bind Entry { %W toggle current } # # B1-Motion # # For "multiple" mode only. Saves the current location of the # pointer for auto-scrolling. Resets the selection mark. # $widget bind Entry { set blt::Hiertable::x %x set blt::Hiertable::y %y set index [%W nearest %x %y] if { [%W cget -selectmode] == "multiple" } { %W selection mark $index } else { blt::Hiertable::SetSelectionAnchor %W $index } } # # ButtonRelease-1 # # For "multiple" mode only. # $widget bind Entry { if { [%W cget -selectmode] == "multiple" } { %W selection anchor current } after cancel $blt::Hiertable::afterId set blt::Hiertable::scroll 0 } # # Shift-ButtonPress-1 # # For "multiple" mode only. # $widget bind Entry { if { [%W cget -selectmode] == "multiple" && [%W selection present] } { if { [%W index anchor] == "" } { %W selection anchor current } set index [%W index anchor] %W selection clearall %W selection set $index current } else { blt::Hiertable::SetSelectionAnchor %W current } } $widget bind Entry { puts # do nothing } $widget bind Entry { # do nothing } $widget bind Entry { after cancel $blt::Hiertable::afterId set blt::Hiertable::scroll 0 } # # Control-ButtonPress-1 # # For "multiple" mode only. # $widget bind Entry { if { [%W cget -selectmode] == "multiple" } { set index [%W index current] %W selection toggle $index %W selection anchor $index } else { blt::Hiertable::SetSelectionAnchor %W current } } $widget bind Entry { puts # do nothing } $widget bind Entry { # do nothing } $widget bind Entry { after cancel $blt::Hiertable::afterId set blt::Hiertable::scroll 0 } $widget bind Entry { if { [%W cget -selectmode] == "multiple" && [%W selection present] } { if { [%W index anchor] == "" } { %W selection anchor current } if { [%W selection includes anchor] } { %W selection set anchor current } else { %W selection clear anchor current %W selection set current } } else { blt::Hiertable::SetSelectionAnchor %W current } } $widget bind Entry { puts # do nothing } $widget bind Entry { # do nothing } $widget column bind all { %W column highlight [%W column current] } $widget column bind all { %W column highlight "" } $widget column bind Rule { %W column highlight [%W column current] %W column resize activate [%W column current] } $widget column bind Rule { %W column highlight "" %W column resize activate "" } $widget column bind Rule { %W column resize anchor %x } $widget column bind Rule { %W column resize mark %x } $widget column bind Rule { %W column configure [%W column current] -width [%W column resize set] } $widget column bind all { set column [%W column nearest %x %y] if { $column != "" } { %W column invoke $column } } } # ---------------------------------------------------------------------- # USAGE: blt::Hiertable::AutoScroll # # Invoked when the user is selecting elements in a hiertable widget # and drags the mouse pointer outside of the widget. Scrolls the # view in the direction of the pointer. # # Arguments: hiertable hierarchy widget # # ---------------------------------------------------------------------- proc blt::Hiertable::AutoScroll { widget } { if { ![winfo exists $widget] } { return } set x $blt::Hiertable::x set y $blt::Hiertable::y set index [$widget nearest $x $y] if {$y >= [winfo height $widget]} { $widget yview scroll 1 units set neighbor down } elseif {$y < 0} { $widget yview scroll -1 units set neighbor up } else { set neighbor $index } if { [$widget cget -selectmode] == "single" } { blt::Hiertable::SetSelectionAnchor $widget $neighbor } else { $widget selection mark $index } set ::blt::Hiertable::afterId [after 10 blt::Hiertable::AutoScroll $widget] } proc blt::Hiertable::SetSelectionAnchor { widget index } { set index [$widget index $index] # If the anchor hasn't changed, don't do anything if { $index != [$widget index anchor] } { $widget selection clearall $widget see $index $widget focus $index $widget selection set $index $widget selection anchor $index } } # ---------------------------------------------------------------------- # USAGE: blt::Hiertable::MoveFocus # # Invoked by KeyPress bindings. Moves the active selection to the # entry , which is an index such as "up", "down", "prevsibling", # "nextsibling", etc. # ---------------------------------------------------------------------- proc blt::Hiertable::MoveFocus { widget where } { catch {$widget focus $where} if { [$widget cget -selectmode] == "single" } { $widget selection clearall $widget selection set focus } $widget see focus } # ---------------------------------------------------------------------- # USAGE: blt::Hiertable::MovePage # Arguments: hiertable hierarchy widget # # Invoked by KeyPress bindings. Pages the current view up or down. # The argument should be either "top" or "bottom". # ---------------------------------------------------------------------- proc blt::Hiertable::MovePage { widget where } { # If the focus is already at the top/bottom of the window, we want # to scroll a page. It's really one page minus an entry because we # want to see the last entry on the next/last page. if { [$widget index focus] == [$widget index view.$where] } { if {$where == "top"} { $widget yview scroll -1 pages $widget yview scroll 1 units } else { $widget yview scroll 1 pages $widget yview scroll -1 units } } update # Adjust the entry focus and the view. Also activate the entry. # just in case the mouse point is not in the widget. $widget entry highlight view.$where $widget focus view.$where $widget see view.$where if { [$widget cget -selectmode] == "single" } { $widget selection clearall $widget selection set focus } } # ---------------------------------------------------------------------- # USAGE: blt::Hiertable::NextMatchingEntry # Arguments: hiertable hierarchy widget # # Invoked by KeyPress bindings. Searches for an entry that starts # with the letter and makes that entry active. # ---------------------------------------------------------------------- proc blt::Hiertable::NextMatchingEntry { widget key } { if {[string match {[ -~]} $key]} { set last [$widget index focus] set next [$widget index next] while { $next != $last } { set label [$widget entry cget $next -label] if { [string index $label 0] == $key } { break } set next [$widget index -at $next next] } $widget focus $next if {[$widget cget -selectmode] == "single"} { $widget selection clearall $widget selection set focus } $widget see focus } } # # Edit mode assignments # # ButtonPress-3 Enables/disables edit mode on entry. Sets focus to # entry. # # KeyPress # # Left Move insertion position to previous. # Right Move insertion position to next. # Up Move insertion position up one line. # Down Move insertion position down one line. # Return End edit mode. # Shift-Return Line feed. # Home Move to first position. # End Move to last position. # ASCII char Insert character left of insertion point. # Del Delete character right of insertion point. # Delete Delete character left of insertion point. # Ctrl-X Cut # Ctrl-V Copy # Ctrl-P Paste # # KeyRelease # # ButtonPress-1 Start selection if in entry, otherwise clear selection. # B1-Motion Extend/reduce selection. # ButtonRelease-1 End selection if in entry, otherwise use last selection. # B1-Enter Disabled. # B1-Leave Disabled. # ButtonPress-2 Same as above. # B2-Motion Same as above. # ButtonRelease-2 Same as above. # # All bindings in editting mode will "break" to override other bindings. # # bind xEditor { set node [%W nearest %x %y] %W entry insert $node @%x,%y "" # %W entry insert $node 2 "" } image create photo blt::Hiertable::CloseNormalFolder -format gif -data { R0lGODlhEAANAMIAAAAAAH9/f///////AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A AAM8WBrM+rAEQWmIb5KxiWjNInCkV32AJHRlGQBgDA7vdN4vUa8tC78qlrCWmvRKsJTquHkp ZTKAsiCtWq0JADs= } image create photo blt::Hiertable::OpenNormalFolder -format gif -data { R0lGODlhEAANAMIAAAAAAH9/f///////AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A AAM1WBrM+rAEMigJ8c3Kb3OSII6kGABhp1JnaK1VGwjwKwtvHqNzzd263M3H4n2OH1QBwGw6 nQkAOw== } image create photo blt::Hiertable::CloseActiveFolder -format gif -data { R0lGODlhEAANAMIAAAAAAH9/f/////+/AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A AAM8WBrM+rAEQWmIb5KxiWjNInCkV32AJHRlGQBgDA7vdN4vUa8tC78qlrCWmvRKsJTquHkp ZTKAsiCtWq0JADs= } image create photo blt::Hiertable::OpenActiveFolder -format gif -data { R0lGODlhEAANAMIAAAAAAH9/f/////+/AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A AAM1WBrM+rAEMigJ8c3Kb3OSII6kGABhp1JnaK1VGwjwKwtvHqNzzd263M3H4n2OH1QBwGw6 nQkAOw== } if { $tcl_platform(platform) == "windows" } { if { $tk_version >= 8.3 } { set cursor "@[file join $blt_library treeview.cur]" } else { set cursor "size_we" } option add *Hiertable.ResizeCursor [list $cursor] } else { option add *Hiertable.ResizeCursor \ "@$blt_library/treeview.xbm $blt_library/treeview_m.xbm black white" } # Standard Motif bindings: bind HiertableEditor { %W text icursor @%x,%y } bind HiertableEditor { %W text icursor last } bind HiertableEditor { %W text icursor next } bind HiertableEditor { set new [expr {[%W text index insert] - 1}] if {![%W text selection present]} { %W text selection from insert %W text selection to $new } else { %W text selection adjust $new } %W text icursor $new } bind HiertableEditor { set new [expr {[%W text index insert] + 1}] if {![%W text selection present]} { %W text selection from insert %W text selection to $new } else { %W text selection adjust $new } %W text icursor $new } bind HiertableEditor { %W text icursor 0 } bind HiertableEditor { set new 0 if {![%W text selection present]} { %W text selection from insert %W text selection to $new } else { %W text selection adjust $new } %W text icursor $new } bind HiertableEditor { %W text icursor end } bind HiertableEditor { set new end if {![%W text selection present]} { %W text selection from insert %W text selection to $new } else { %W text selection adjust $new } %W text icursor $new } bind HiertableEditor { if { [%W text selection present]} { %W text delete sel.first sel.last } else { %W text delete insert } } bind HiertableEditor { if { [%W text selection present] } { %W text delete sel.first sel.last } else { set index [expr [%W text index insert] - 1] if { $index >= 0 } { %W text delete $index $index } } } bind HiertableEditor { %W text selection from insert } bind HiertableEditor