domtree-treectrl.tcl

Go to the documentation of this file.
00001 /*  domtree-treectrl.tcl --*/
00002 /* */
00003 /*  A megawidget to support display of a DOM hierarchy*/
00004 /*  based on the treectrl widget.*/
00005 /* */
00006 /*  This widget both generates and reacts to DOM Events.*/
00007 /* */
00008 /*  This package features ordered and non-unique directories and items.*/
00009 /*  Paths are managed as live links into a DOM hierarchy.*/
00010 /* */
00011 /*  Copyright (c) 2005 Explain*/
00012 /*  http://www.explain.com.au/*/
00013 /*  Copyright (c) 2004 Zveno Pty Ltd*/
00014 /*  http://www.zveno.com/*/
00015 /* */
00016 /*  See the file "LICENSE" in this distribution for information on usage and*/
00017 /*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00018 /* */
00019 /*  $Id: domtree-treectrl.tcl,v 1.1 2005/11/04 06:31:15 balls Exp $*/
00020 
00021 package provide domtree::treectrl 3.1
00022 
00023 /*  We need the treectrl widget*/
00024 
00025 package require treectrl 1.1
00026 
00027 /*  We need the DOM*/
00028 /*  V2.0 gives us Level 2 event model*/
00029 /*  V2.1 gives us libxml2*/
00030 
00031 package require dom 3.1
00032 
00033 namespace domtree {
00034     /*  Just make sure this namespace exists*/
00035     variable exists {}
00036 }
00037 namespace domtree::treectrl {
00038     variable defaults
00039     array  defaults =  {
00040     showlength 20
00041     showtextcontent 0
00042     showelementid 0
00043     }
00044 
00045     catch {font create [namespace current]::bold -weight bold}
00046 
00047     ret  ::domtree::treectrl ( type path , type args ) { return [eval domtree::treectrl::create $path $args] }
00048 
00049     /*  We may be able to use tktreectrl's event mechanism*/
00050     /*  to exactly match treectrl events to DOM events*/
00051     variable eventTypeMap
00052     array  eventTypeMap =  {
00053     ButtonPress mousedown
00054     ButtonRelease   mouseup
00055     Enter       mouseover
00056     Leave       mouseout
00057     Motion      mousemove
00058     FocusIn     DOMFocusIn
00059     FocusOut    DOMFocusOut
00060     }
00061 }
00062 
00063 /*  domtree::treectrl::create --*/
00064 /* */
00065 /*  Create a DOM Treectrl widget*/
00066 /* */
00067 /*  Arguments:*/
00068 /*  path    widget path*/
00069 /*  args    configuration options*/
00070 /* */
00071 /*  Results:*/
00072 /*  Tree widget created*/
00073 
00074 ret  domtree::treectrl::create (type path , type args) {
00075     upvar \#0 [namespace current]::Widget$path widget
00076 
00077     eval frame $path -bd 0 -relief flat -takefocus 0 \
00078         -class domtree::treectrl -highlightthickness 0
00079 
00080     bindtags $path [list $path domtree::treectrl [winfo toplevel $path] all]
00081 
00082     set tree [eval treectrl $path.tree -showroot yes -showrootbutton yes \
00083           -showbuttons yes -showlines yes \
00084           -itemheight 0 \
00085           -openbuttonimage ::domtree::collapse -closedbuttonimage ::domtree::expand]
00086 
00087     $path.tree column create -expand yes -text Elements -tag element
00088     $path.tree column create -text Attributes -tag attr
00089     $path.tree column create -text Depth -tag depth
00090 
00091     $path.tree element create e1 image -image {::domtree::element {open} ::domtree::element {}}
00092     $path.tree element create Edocument image -image ::domtree::textNode
00093     $path.tree element create EtextNode text
00094     $path.tree element create Ecomment image -image ::domtree::Comment
00095     $path.tree element create e3 text \
00096     -fill [list [$path cget -highlightcolor] {selected focus}] \
00097     -font [list [namespace current]::bold {}]
00098     $path.tree element create e4 text -fill blue
00099     $path.tree element create e6 text
00100     $path.tree element create e5 rect -showfocus yes \
00101     -fill [list [$path cget -highlightbackground] {selected focus} gray {selected !focus}]
00102 
00103     $path.tree style create Selement
00104     $path.tree style elements Selement {e5 e1 e3 e4}
00105     $path.tree style layout Selement e1 -padx {0 4} -expand ns
00106     $path.tree style layout Selement e3 -padx {0 4} -expand ns
00107     $path.tree style layout Selement e4 -padx {0 6} -expand ns
00108     $path.tree style layout Selement e5 -union [list e3] -iexpand ns -ipadx 2
00109 
00110     $path.tree style create Sdocument
00111     $path.tree style elements Sdocument {e5 Edocument e3 e4}
00112     $path.tree style layout Sdocument Edocument -padx {0 4} -expand ns
00113     $path.tree style layout Sdocument e3 -padx {0 4} -expand ns
00114     $path.tree style layout Sdocument e4 -padx {0 6} -expand ns
00115     $path.tree style layout Sdocument e5 -union [list e3] -iexpand ns -ipadx 2
00116 
00117     $path.tree style create StextNode
00118     $path.tree style elements StextNode EtextNode
00119     $path.tree style layout StextNode EtextNode -padx {0 4} -squeeze x
00120 
00121     $path.tree style create Scomment
00122     $path.tree style elements Scomment {e5 Ecomment e3 e4}
00123     $path.tree style layout Scomment Ecomment -padx {0 4} -expand ns
00124     $path.tree style layout Scomment e3 -padx {0 4} -expand ns
00125     $path.tree style layout Scomment e4 -padx {0 6} -expand ns
00126     $path.tree style layout Scomment e5 -union [list e3] -iexpand ns -ipadx 2
00127 
00128     $path.tree style create s3
00129     $path.tree style elements s3 {e6}
00130     $path.tree style layout s3 e6 -padx 6 -expand ns
00131 
00132     # Create custom event to allow mapping to DOM nodes
00133     $path.tree notify install event MapDOMNode
00134 
00135     # Set various bindings to generate DOM events
00136 
00137     if {0} {
00138     foreach event {ButtonRelease ButtonPress Enter Leave Motion} {
00139     $path.tree bindImage <$event> [namespace code [list _node_mouse_event $event {} $path]]
00140     $path.tree bindText <$event> [namespace code [list _node_mouse_event $event {} $path]]
00141     foreach modifier {Control Shift Alt Meta Double} {
00142         $path.tree bindImage <$modifier-$event> [namespace code [list _node_mouse_event $event $modifier $path]]
00143         $path.tree bindText <$modifier-$event> [namespace code [list _node_mouse_event $event $modifier $path]]
00144     }
00145     }
00146     }
00147 
00148     grid $tree -row 0 -column 0 -sticky news
00149     grid rowconfigure $path 0 -weight 1
00150     grid columnconfigure $path 0 -weight 1
00151 
00152     rename $path ::$path:cmd
00153     proc ::$path { cmd args } "return \[eval domtree::treectrl::cmd $path \$cmd \$args\]"
00154 
00155     array set widget {
00156     -rootnode {}
00157     -populate normal
00158     }
00159 
00160     foreach {option value} $args {
00161     configure $path $option $value
00162     }
00163 
00164     return $path
00165 }
00166 
00167 /*  domtree::treectrl::see --*/
00168 /* */
00169 /*  Display a DOM node in the tree.*/
00170 /* */
00171 /*  Arguments:*/
00172 /*  path    widget path*/
00173 /*  dnode   DOM node*/
00174 /* */
00175 /*  Results:*/
00176 /*  The tree node for the corresponding DOM node is expanded,*/
00177 /*  all parent nodes are also expanded.*/
00178 /*  Returns the id of the tree item.*/
00179 
00180 ret  domtree::treectrl::see (type path , type dnode) {
00181     foreach pathnode [dom::node path $dnode] {
00182     $path.tree expand [_dnode_to_treeid $path $pathnode]
00183     update idletasks
00184     }
00185     set id [_dnode_to_treeid $path $dnode]
00186     $path.tree see $id
00187     return $id
00188 }
00189 
00190 /*  domtree::treectrl::cmd --*/
00191 /* */
00192 /*  Widget command*/
00193 /* */
00194 /*  Arguments:*/
00195 /*  path    widget path*/
00196 /*  method  command method*/
00197 /*  args    method arguments*/
00198 /* */
00199 /*  Results:*/
00200 /*  Depends on method.*/
00201 
00202 ret  domtree::treectrl::cmd (type path , type method , type args) {
00203     return [eval [list $method $path] $args]
00204 }
00205 
00206 /*  domtree::treectrl::cget --*/
00207 /* */
00208 /*  Implements the cget method*/
00209 /* */
00210 /*  Arguments:*/
00211 /*  path    widget path*/
00212 /*  option  configuration option*/
00213 /* */
00214 /*  Results:*/
00215 /*  Returns value of option*/
00216 
00217 ret  domtree::treectrl::cget (type path , type option) {
00218     switch -- $option {
00219     -rootnode -
00220     -populate {
00221         upvar \#0 [namespace current]::Widget$path widget
00222 
00223         return $widget($option)
00224     }
00225     default {
00226         return [$path.tree cget $option]
00227     }
00228     }
00229 }
00230 
00231 /*  domtree::treectrl::configure --*/
00232 /* */
00233 /*  Implements the configure method*/
00234 /* */
00235 /*  Arguments:*/
00236 /*  path    widget path*/
00237 /*  args    configuration options*/
00238 /* */
00239 /*  Results:*/
00240 /*  Sets value of options*/
00241 
00242 ret  domtree::treectrl::configure (type path , type args) {
00243     if {[catch {eval configure:dbg [list $path] $args} msg]} {
00244     puts stderr "domtree::treectrl::configure incurred error\n$msg"
00245     }
00246 }
00247 
00248 ret  domtree::treectrl::configure:dbg (type path , type args) {
00249     set res {}
00250 
00251     foreach {option value} $args {
00252     switch -- $option {
00253         -rootnode {
00254         upvar \#0 [namespace current]::Widget$path widget
00255 
00256         if {$widget(-rootnode) != ""} {
00257             $path.tree item delete all
00258             _dom_unmap $path $widget(-rootnode)
00259         }
00260 
00261         if {$value != ""} {
00262             set widget(-rootnode) $value
00263             _add_node $path 0 $value
00264         }
00265         }
00266         -populate {
00267         upvar \#0 [namespace current]::Widget$path widget
00268 
00269         switch -- $value {
00270             {} -
00271             normal {
00272             set widget(-populate) normal
00273             }
00274             lazy {
00275             set widget(-populate) lazy
00276             }
00277             default {
00278             return -code error "unknown value \"$value\" for option \"-populate\""
00279             }
00280         }
00281         }
00282         default {
00283         return [$path.tree configure $option $value]
00284         }
00285     }
00286     }
00287 
00288     # May need to add these to above switch code
00289     if {0} {
00290         # Listen for UI events
00291         dom::node addEventListener $docel DOMActivate [namespace code [list _node_selected $path]] -usecapture 1
00292 
00293         # Listen for mutation events
00294         dom::node addEventListener $docel DOMSubtreeModified [namespace code [list _node_tree_modified $path]] -usecapture 1
00295         dom::node addEventListener $docel DOMNodeInserted [namespace code [list _node_inserted $path]] -usecapture 1
00296         dom::node addEventListener $docel DOMNodeRemoved [namespace code [list _node_removed $path]] -usecapture 1
00297         dom::node addEventListener $docel DOMCharacterDataModified [namespace code [list _node_data_modified $path]] -usecapture 1
00298         dom::node addEventListener $docel DOMAttrModified [namespace code [list _node_attr_modified $path]] -usecapture 1
00299         dom::node addEventListener $docel DOMAttrRemoved [namespace code [list _node_attr_removed $path]] -usecapture 1
00300     }
00301 
00302     return $res
00303 }
00304 
00305 /*  domtree::treectrl::refresh --*/
00306 /* */
00307 /*  Updates the Tree display with the value of a node*/
00308 /* */
00309 /*  Arguments:*/
00310 /*  path    widget path*/
00311 /*  node    DOM node*/
00312 /* */
00313 /*  Results:*/
00314 /*  May change node display*/
00315 
00316 ret  domtree::treectrl::refresh (type path , type node) {
00317     _refresh $path $node
00318     return {}
00319 }
00320 
00321 /*  domtree::treectrl::xview --*/
00322 /* */
00323 /*  Implement xview method*/
00324 /* */
00325 /*  Arguments:*/
00326 /*  path    widget path*/
00327 /*  args    additional arguments*/
00328 /* */
00329 /*  Results:*/
00330 /*  Depends on Tree xview method*/
00331 
00332 ret  domtree::treectrl::xview (type path , type args) {
00333     eval $path.tree xview $args
00334 }
00335 
00336 /*  domtree::treectrl::yview --*/
00337 /* */
00338 /*  Implement yview method*/
00339 /* */
00340 /*  Arguments:*/
00341 /*  path    widget path*/
00342 /*  args    additional arguments*/
00343 /* */
00344 /*  Results:*/
00345 /*  Depends on Tree yview method*/
00346 
00347 ret  domtree::treectrl::yview (type path , type args) {
00348     eval $path.tree yview $args
00349 }
00350 
00351 /*  domtree::treectrl::selection --*/
00352 ret  domtree::treectrl::selection (type path , type args) {
00353     eval $path.tree selection $args
00354 }
00355 
00356 /*  domtree::treectrl::find --*/
00357 /* */
00358 /*  Find DOM node at given location*/
00359 /* */
00360 /*  Arguments:*/
00361 /*  path    widget path*/
00362 /*  findInfo    location*/
00363 /*  confine*/
00364 /* */
00365 /*  Results:*/
00366 /*  DOM node at location*/
00367 
00368 ret  domtree::treectrl::find (type path , type findInfo , optional confine ={)} {
00369     set tnode [$path.tree find $findInfo $confine]
00370     return [_treeid_to_dnode $tnode]
00371 }
00372 
00373 # Procedures to implement display
00374 
00375 # domtree::treectrl::_refresh --
00376 #
00377 #   Configure node with appropriate images, labels, etc
00378 #
00379 # Arguments:
00380 #   path    widget path
00381 #   node    DOM node
00382 #   args    additional options
00383 #
00384 # Results:
00385 #   Tree node may have image or label changed
00386 
00387 proc domtree::treectrl::_refresh {path node args} {
00388 
00389     switch [set nodetype [::dom::node cget $node -nodeType]] {
00390     document -
00391     documentFragment -
00392     element {
00393         set label [dom::node cget $node -nodeName]
00394         set icon ::domtree::element
00395 
00396         if {![string compare $nodetype element]} {
00397 
00398         # ID attribute display
00399         if {[Widget::getoption $path -showelementid]} {
00400             array set attributes [array get [::dom::node cget $node -attributes]]
00401             if {[catch {
00402             append label "    (id $attributes(id))"
00403             }] && [catch {
00404             append label "    (ID $attributes(ID))"
00405             }]} {}
00406         }
00407 
00408         if {[Widget::getoption $path -showtextcontent]} {
00409             # Text content display
00410             set temp [_refresh_text_content_display_find_text $node [Widget::getoption $path -showlength]]
00411             if {[string length $temp]} {
00412             append label "    \[ [_refresh_string_trim $temp [Widget::getoption $path -showlength]] \]"
00413             }
00414         }
00415 
00416         }
00417 
00418         if {![string length [dom::node parent $node]]} {
00419         # Root node is special
00420         return {}
00421         }
00422 
00423     }
00424     textNode {
00425         array set opts [list -label [dom::node cget $node -nodeValue]]
00426         array set opts $args
00427         set label [_refresh_string_trim [string trim $opts(-label)] [Widget::getoption $path -showlength]]
00428         set icon ::domtree::textNode
00429 
00430         # Also do the ancestors
00431         foreach ancestor [lrange [lreplace [::dom::node path $node] end end] 1 end] {
00432         _refresh $path $ancestor
00433         }
00434     }
00435     processingInstruction {
00436         set label [string trim [dom::node cget $node -nodeName]]
00437         set icon ::domtree::PI
00438     }
00439     docType {
00440         set label {}
00441         set icon ::domtree::DocType
00442     }
00443     comment {
00444         set label [_refresh_string_trim [string trim [::dom::node cget $node -nodeValue]] [Widget::getoption $path -showlength]]
00445         set icon ::domtree::Comment
00446     }
00447     entityReference {
00448         set label [::dom::node cget $node -nodeName]
00449         set icon ::domtree::EntityReference
00450     }
00451     default {
00452         set label $nodetype
00453         set icon ::domtree::other
00454     }
00455     }
00456 
00457     catch {
00458     $path.tree itemconfigure [_dom_to_tree $node] -image $icon
00459     $path.tree itemconfigure [_dom_to_tree $node] -text $label
00460     }
00461 
00462     return {}
00463 }
00464 
00465 /*  domtree::treectrl::_refresh_text_content_display_find_text --*/
00466 /* */
00467 /*  Searches given element for text.*/
00468 /*  In future could use XPath - just get the string value*/
00469 /*  of the node.*/
00470 /* */
00471 /*  Arguments:*/
00472 /*  node    DOM element node to search*/
00473 /*  len amount of text to return*/
00474 /* */
00475 /*  Results:*/
00476 /*  Returns string*/
00477 
00478 ret  domtree::treectrl::_refresh_text_content_display_find_text (type node , type len) {
00479     switch -- $len {
00480     0 {
00481         return {}
00482     }
00483     default {
00484         set text {}
00485         foreach child [::dom::node children $node] {
00486         switch [::dom::node cget $child -nodeType] {
00487             document -
00488             documentFragment -
00489             element {
00490             append text \
00491                 [_refresh_text_content_display_find_text $child [expr $len - [string length $text]]]
00492             }
00493             textNode {
00494             append text [string range \
00495                 [::dom::node cget $child -nodeValue] \
00496                 0 [expr $len - [string length $text]] \
00497             ]
00498             }
00499             default {
00500             # Nothing to do
00501             }
00502         }
00503         if {[string length $text] >= $len} {
00504             return $text
00505         }
00506         }
00507 
00508         return $text
00509 
00510     }
00511     }
00512 
00513     return {}
00514 }
00515 
00516 /*  domtree::treectrl::_refresh_all --*/
00517 /* */
00518 /*  Updates display of all tree nodes*/
00519 /* */
00520 /*  Arguments:*/
00521 /*  path    widget pathname*/
00522 /*  node    Tree node*/
00523 /* */
00524 /*  Results:*/
00525 /*  Returns empty string*/
00526 
00527 ret  domtree::treectrl::_refresh_all (type path , type node) {
00528     foreach child [$path.tree nodes $node] {
00529     _refresh $path [_tree_to_dom $child]
00530     _refresh_all $path $child
00531     }
00532 
00533     return {}
00534 }
00535 
00536 /*  domtree::treectrl::_refresh_string_trim --*/
00537 /* */
00538 /*  Massage text for display*/
00539 /* */
00540 /*  Arguments:*/
00541 /*  text    text string*/
00542 /*  max maximum length for string*/
00543 /* */
00544 /*  Results:*/
00545 /*  Returns string*/
00546 
00547 ret  domtree::treectrl::_refresh_string_trim (type text , type max) {
00548     if {[string length $text] > $max} {
00549     set text [string range $text 0 [expr $max - 3]]...
00550     }
00551     if {[info tclversion] >= 8.1} {
00552     set dot \u2022
00553     } else {
00554     set dot { }
00555     }
00556     regsub -all [format {[%s%s%s%s]+} \n \r { } \t] $text $dot text
00557     return $text
00558 }
00559 
00560 /*  domtree::treectrl::_node_selected --*/
00561 /* */
00562 /*  A node has been selected.*/
00563 /* */
00564 /*  This is invoked via a DOM event.*/
00565 /* */
00566 /*  Arguments:*/
00567 /*  path    widget path*/
00568 /*  evid    event node*/
00569 
00570 ret  domtree::treectrl::_node_selected (type path , type evid) {
00571 
00572     set domnode [dom::event cget $evid -target]
00573 
00574     # Temporarily remove the -selectcommand callback
00575     # to avoid an infinite loop (continually posting DOM click events)
00576     set cmd [$path.tree cget -selectcommand]
00577     $path.tree configure -selectcommand {}
00578 
00579     $path.tree selection set [_dom_to_tree $domnode]
00580 
00581     $path.tree configure -selectcommand $cmd
00582 
00583     return {}
00584 }
00585 
00586 /*  domtree::treectrl::_select_node --*/
00587 /* */
00588 /*  A tree node has been selected.*/
00589 /* */
00590 /*  Arguments:*/
00591 /*  path    widget path*/
00592 /*  tree    tree path*/
00593 /*  tnode   tree node*/
00594 
00595 ret  domtree::treectrl::_select_node (type path , type tree , type tnode) {
00596 
00597     dom::event postMouseEvent [_tree_to_dom $tnode] click -detail 1
00598 
00599     return {}
00600 }
00601 
00602 /*  domtree::treectrl::_node_mouse_event --*/
00603 /* */
00604 /*  Generate DOM Mouse Event*/
00605 /* */
00606 /*  Arguments:*/
00607 /*  event   event type*/
00608 /*  mod modifier*/
00609 /*  path    widget path*/
00610 /*  tnode   tree node*/
00611 /* */
00612 /*  Results:*/
00613 /*  Event synthesized for DOM*/
00614 
00615 ret  domtree::treectrl::_node_mouse_event (type event , type mod , type path , type tnode) {
00616     variable eventTypeMap
00617 
00618     set type $event
00619     catch {set type $eventTypeMap($event)}
00620 
00621     set evid [dom::document createEvent [_tree_to_dom $tnode] $type]
00622     dom::event initMouseEvent $evid $type 1 1 {} 0 0 0 0 0 \
00623         [expr {$mod == "Control"}] \
00624         [expr {$mod == "Alt"}] \
00625         [expr {$mod == "Shift"}] \
00626         [expr {$mod == "Meta"}] \
00627         0 {}
00628     dom::node dispatchEvent [_tree_to_dom $tnode] $evid
00629     dom::destroy $evid
00630 
00631     # ButtonRelease events also generate DOMActivate events
00632 
00633     if {![string compare $event "ButtonRelease"]} {
00634     set detail 1
00635     if {![string compare $mod "Double"]} {
00636         set detail 2
00637     }
00638     dom::event postUIEvent [_tree_to_dom $tnode] DOMActivate -detail $detail
00639     }
00640 
00641     return {}
00642 }
00643 
00644 /*  domtree::treectrl::_node_ui_event --*/
00645 /* */
00646 /*  Generate DOM UI Event*/
00647 /* */
00648 /*  Arguments:*/
00649 /*  event   event type*/
00650 /*  path    widget path*/
00651 /*  tnode   tree node*/
00652 /* */
00653 /*  Results:*/
00654 /*  Event synthesized for DOM*/
00655 
00656 ret  domtree::treectrl::_node_ui_event (type event , type path , type tnode) {
00657     variable eventTypeMap
00658 
00659     set type $event
00660     catch {set type $eventTypeMap($event)}
00661     dom::event postUIEvent [_tree_to_dom $tnode] $type
00662 
00663     return {}
00664 }
00665 
00666 /*  domtree::treectrl::_add_node --*/
00667 /* */
00668 /*  Recurse DOM structure, inserting tree nodes as we go.*/
00669 /* */
00670 /* */
00671 /*  Arguments:*/
00672 /*  w   tree widget path*/
00673 /*  tnode   tree node to add children to*/
00674 /*  dnode   DOM node corresponding to tree path above*/
00675 /* */
00676 /*  Results:*/
00677 /*  Nodes added to tree*/
00678 
00679 ret  domtree::treectrl::_add_node (type path , type tnode , type dnode) {
00680     upvar \#0 [namespace current]::Widget$path widget
00681 
00682     switch [dom::node cget $dnode -nodeType] {
00683     document {
00684         set nodename {}
00685         set hasChildren 1
00686         set text {}
00687         set attrs {}
00688     }
00689     element {
00690         set nodename [$dnode cget -nodeName]
00691         set hasChildren [$dnode hasChildNodes]
00692         set text {}
00693         set attrs {}
00694         foreach atnode [dom::node selectNode $dnode @*] {
00695         lappend attrs [dom::node cget $atnode -nodeName]
00696         }
00697     }
00698     textNode {
00699         set nodename {}
00700         set hasChildren 0
00701         set text [$dnode cget -nodeValue]
00702         set attrs {}
00703     }
00704     default {
00705         set nodename [dom::node cget $dnode -nodeType]
00706         set hasChildren 0
00707         set text {}
00708         set attrs {}
00709     }
00710     }
00711 
00712     set id [$path.tree item create]
00713     if {$tnode != ""} {
00714     $path.tree item lastchild $tnode $id
00715     }
00716     $path.tree item configure $id -button $hasChildren
00717     switch [dom::node cget $dnode -nodeType] {
00718     textNode {
00719         $path.tree item style set $id 0 S[dom::node cget $dnode -nodeType]
00720         $path.tree item text $id 0 $text
00721     }
00722     default {
00723         $path.tree item style set $id 0 S[dom::node cget $dnode -nodeType] \
00724         1 s3 2 s3
00725         $path.tree item complex $id \
00726         [list [list e3 -text $nodename]] \
00727         [list [list e6 -text $attrs]] \
00728         [list [list e6 -text [llength [dom::node path $dnode]]]]
00729     }
00730     }
00731 
00732     # Create a two-way mapping between DOM node and tree id
00733     $path.tree notify bind $id <MapDOMNode> [list [namespace current]::_domid $dnode]
00734     dom::node addEventListener $dnode DOMActivate [list [namespace current]::_treeid $path $id]
00735 
00736     # Implement lazy population of the tree widget
00737     if {$widget(-populate) == "lazy"} {
00738     $path.tree collapse $id
00739     after idle [list $path.tree notify bind $id <Expand-before> [namespace code [list _node_open $path %I $id $dnode]]]
00740     }
00741     if {$widget(-populate) == "normal"} {
00742     foreach dchild [dom::node children $dnode] {
00743         _add_node $path $id $dchild
00744     }
00745     }
00746 
00747     return {}
00748 }
00749 /*  These should not be called*/
00750 ret  domtree::treectrl::_domid (type dnode) {
00751     return $dnode
00752 }
00753 ret  domtree::treectrl::_treeid (type id) {
00754     return $id
00755 }
00756 
00757 /*  domtree::treectrl::_dnode_to_treeid --*/
00758 /* */
00759 /*  Find the tree item for a DOM node*/
00760 /* */
00761 /*  Arguments:*/
00762 /*  path    widget path*/
00763 /*  dnode   DOM node*/
00764 /* */
00765 /*  Results:*/
00766 /*  Returns a tree item descriptor*/
00767 
00768 ret  domtree::treectrl::_dnode_to_treeid (type path , type dnode) {
00769     set listener {}
00770     foreach l [dom::node addEventListener $dnode DOMActivate] {
00771     foreach {key dpath value} $l break
00772     if {[string equal $path $dpath] && \
00773         [string equal $key "[namespace current]::_treeid"]} {
00774         return $value
00775     }
00776     }
00777 
00778     return {}
00779 }
00780 
00781 /*  domtree::treectrl::_treeid_to_dnode --*/
00782 /* */
00783 /*  Find the DOM node for a tree item*/
00784 /* */
00785 /*  Arguments:*/
00786 /*  path    widget path*/
00787 /*  id  item descriptor*/
00788 /* */
00789 /*  Results:*/
00790 /*  Returns a DOM node token*/
00791 
00792 ret  domtree::treectrl::_treeid_to_dnode (type path , type id) {
00793     return [lindex [$path.tree notify bind $id <MapDOMNode>] end]
00794 }
00795 
00796 /*  domtree::treectrl::_dom_unmap --*/
00797 /* */
00798 /*  Remove all event listeners for a tree widget.*/
00799 /* */
00800 /*  Arguments:*/
00801 /*  path    widget path*/
00802 /*  node    DOM node*/
00803 /* */
00804 /*  Results:*/
00805 /*  Returns empty string.*/
00806 /*  Event listeners may be removed from DOM document nodes.*/
00807 
00808 ret  domtree::treectrl::_dom_unmap (type path , type node) {
00809     # Crashing bug in TclDOM v3.1 prevents us from cleaning up
00810     return {}
00811 
00812     foreach listener [dom::node addEventListener $node DOMActivate] {
00813     foreach {key dpath value} $listener break
00814     if {[string match [namespace current]::_* $key] && \
00815         [string equal $dpath $path]} {
00816         # This is one of ours
00817         dom::node removeEventListener $node DOMActivate $listener
00818     }
00819     }
00820 
00821     foreach child [dom::node children $node] {
00822     _dom_unmap $path $child
00823     }
00824 }
00825 
00826 /*  domtree::_set_client_data --*/
00827 /* */
00828 /*  Manage data for tree nodes*/
00829 /* */
00830 /*  Arguments:*/
00831 /*  path    widget path*/
00832 /*  node    tree node*/
00833 /*  field   field name*/
00834 /*  value   value for field*/
00835 /* */
00836 /*  Results:*/
00837 /*  Item's configuration changed*/
00838 
00839 ret  domtree::_set_client_data (type path , type node , type field , type value) {
00840     array set nodeinfo [$path.tree itemcget $node -data]
00841     set nodeinfo($field) $value
00842     $path.tree itemconfigure $node -data [array get nodeinfo]
00843 }
00844 
00845 /*  domtree::_unset_client_data --*/
00846 /* */
00847 /*  Manage data for tree nodes*/
00848 /* */
00849 /*  Arguments:*/
00850 /*  path    widget path*/
00851 /*  node    tree node*/
00852 /*  field   field name to unset*/
00853 /* */
00854 /*  Results:*/
00855 /*  Item's configuration changed*/
00856 
00857 ret  domtree::_unset_client_data (type path , type node , type field) {
00858     array set nodeinfo [$path.tree itemcget $node -data]
00859     catch {unset nodeinfo($field)}
00860     $path.tree itemconfigure $node -data [array get nodeinfo]
00861 }
00862 
00863 /*  domtree::_node_open --*/
00864 /* */
00865 /*  Invoked when a tree item is opened and*/
00866 /*  the tree is being populated lazily.*/
00867 /* */
00868 /*  Arguments:*/
00869 /*  path    widget path*/
00870 /*  id  tree item*/
00871 /*  dnode   DOM node*/
00872 /* */
00873 /*  Results:*/
00874 /*  Tree nodes may be added*/
00875 
00876 ret  domtree::treectrl::_node_open (type path , type tnode , type id , type dnode) {
00877     if {[string equal $tnode $id]} {
00878     $path.tree notify bind $id <Expand-before> {}
00879     foreach dchild [dom::node children $dnode] {
00880         _add_node $path $id $dchild
00881     }
00882     }
00883 
00884     return {}
00885 }
00886 
00887 /*  domtree::_node_tree_modified --*/
00888 /* */
00889 /*  Invoked when the node's subtree has changed.*/
00890 /*  Could be because a child node has been removed.*/
00891 /* */
00892 /*  Refresh the*/
00893 /*  display of the node, since if textual content*/
00894 /*  is enabled the node's string value may have*/
00895 /*  changed.*/
00896 /* */
00897 /*  Arguments:*/
00898 /*  path    widget path*/
00899 /*  evid    DOM event node*/
00900 /* */
00901 /*  Results:*/
00902 /*  Tree nodes inserted or removed*/
00903 
00904 ret  domtree::_node_tree_modified (type path , type evid) {
00905 
00906     set target [dom::event cget $evid -target]
00907     set children [dom::node children $target]
00908     set branch [Tree::nodes $path.tree [_dom_to_tree $target]]
00909     if {[llength $children] < [llength $branch]} {
00910     for {set idx 0} {$idx < [llength $branch]} {incr idx} {
00911         if {![string length [lindex $children $idx]] || \
00912             [_dom_to_tree [lindex $children $idx]] != [lindex $branch $idx]} {
00913         $path.tree delete [lindex $branch $idx]
00914         break
00915         }
00916     }
00917     }
00918 
00919     _refresh $path [dom::event cget $evid -currentNode]
00920 
00921     return {}
00922 }
00923 
00924 /*  domtree::_node_inserted --*/
00925 /* */
00926 /*  A node has been inserted.*/
00927 /* */
00928 /*  Arguments:*/
00929 /*  path    widget path*/
00930 /*  evid    DOM event node*/
00931 /* */
00932 /*  Results:*/
00933 /*  Insert tree node*/
00934 
00935 ret  domtree::_node_inserted (type path , type evid) {
00936 
00937     # Find where the node was inserted into the child list
00938     set newnode [dom::event cget $evid -target]
00939     set parent [dom::node parent $newnode]
00940     set children [dom::node children $parent]
00941     set idx [lsearch $children $newnode]
00942 
00943     # Get old tree info
00944     set tparent [_dom_to_tree $parent]
00945     set branch [Tree::nodes $path.tree $tparent]
00946 
00947     if {$idx > [llength $branch]} {
00948     # Append the new node to the branch
00949     $path.tree insert end $tparent [_dom_to_tree $newnode]
00950     } else {
00951     # Insert the new node into the branch
00952     $path.tree insert $idx $tparent [_dom_to_tree $newnode]
00953     }
00954 
00955     _refresh $path $newnode
00956     _add_node $path [_dom_to_tree $newnode] $newnode
00957 
00958     return {}
00959 }
00960 
00961 /*  domtree::_node_removed --*/
00962 /* */
00963 /*  A node has been removed.*/
00964 /* */
00965 /*  Arguments:*/
00966 /*  path    widget path*/
00967 /*  evid    DOM event node*/
00968 /* */
00969 /*  Results:*/
00970 /*  Remove tree node*/
00971 
00972 ret  domtree::_node_removed (type path , type evid) {
00973 
00974     set oldnode [dom::event cget $evid -target]
00975     Tree::delete $path.tree [_dom_to_tree $oldnode]
00976 
00977     return {}
00978 }
00979 
00980 /*  domtree::_node_data_modified --*/
00981 /* */
00982 /*  Character data has changed*/
00983 /* */
00984 /*  Arguments:*/
00985 /*  path    widget path*/
00986 /*  evid    DOM L2 event node*/
00987 /* */
00988 /*  Results:*/
00989 /*  Tree display updated*/
00990 
00991 ret  domtree::_node_data_modified (type path , type evid) {
00992     _refresh $path [dom::event cget $evid -target] \
00993         -label [dom::event cget $evid -newValue]
00994     return {}
00995 }
00996 
00997 /*  domtree::_node_attr_modified --*/
00998 /* */
00999 /*  Attribute value modified*/
01000 /* */
01001 /*  Arguments:*/
01002 /*  path    widget path*/
01003 /*  evid    DOM L2 event node*/
01004 /* */
01005 /*  Results:*/
01006 /*  Display updated*/
01007 
01008 ret  domtree::_node_attr_modified (type path , type evid) {
01009     _refresh $path [dom::event cget $evid -target]
01010     return {}
01011 }
01012 
01013 /*  domtree::_node_attr_removed --*/
01014 /* */
01015 /*  Attribute removed*/
01016 /* */
01017 /*  Arguments:*/
01018 /*  path    widget path*/
01019 /*  evid    DOM L2 event node*/
01020 /* */
01021 /*  Results:*/
01022 /*  Display updated*/
01023 
01024 ret  domtree::_node_attr_removed (type path , type evid) {
01025     _refresh $path [dom::event cget $evid -target]
01026     return {}
01027 }
01028 
01029 /*  Image data*/
01030 
01031 image create photo ::domtree::element -data {R0lGODlhEAAQANX/AP7///3//vv+/vn+/fj+/ff9/fb9/fL8/PL6+e/8++78+u37+uz7+ur7
01032 +ef6+d349tv49df18tT289P288718sPz773y7bPw6qzo4qTt5o3o4Ivn4IHb0nTj2XPj2Wrh
01033 107bzzDVxxnQwRecjBCtmRCtmA+AdA6Hew21oQ2NgQq+rQqjlQpoXApmWgm/rQeekAXMuwXG
01034 tQTMu////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C0FET0JFOklS
01035 MS4wAt7tACH5BAEAADMALAAAAAAQABAAAAaRwJlwCBgajZCKBeE4GhuXCCIinQycs+iUA8N4
01036 HgHnZyuTcUoZAyAwIAgA5LKMNGIckksHgiOXoRAnElpUCCB8MlKEGolcGBsiMIwyGCFxHBMd
01037 LpZxZQMPnDJ7fSVConIlKocyJSNChqcjKzEwqyMmQo+0rCYpLyUmwC1CmL/BLBQZIy3KQp7J
01038 yy0KAgUJCwcCQQA7
01039 }
01040 image create photo ::domtree::textNode -data {R0lGODlhEAAOAJH/AP///39/fwAAAP///yH/C0FET0JFOklSMS4wAt7tACH5BAEAAAMALAAA
01041 AAAQAA4AAAI0nIUpxi0AIWoOhAveouPFnHDPhV1CQHmfhFYkmbWMup6p9QbxvbJ3rrNVejuH
01042 4ihjAF+GAgA7
01043 }
01044 image create photo ::domtree::PI -data {R0lGODdhEAAOAPEAALLA3AAAAAAA/////ywAAAAAEAAOAAACL4yPoBvi78Jio9oqJwh3oG90
01045 DfSEF9dhKIioGFmqR4phFL3eaa6g+6ETaTYsw6IAADs=
01046 }
01047 image create photo ::domtree::DocType -data {R0lGODlhEAAQAKL/APfQ0MmZmYJfX2YAAEoBAf///wAAAAAAACH/C0FET0JFOklSMS4wAt7t
01048 ACH5BAEAAAUALAAAAAAQABAAAAM7WDKyUjBGB8AaUl4RQFhZNIxM8D2hQJBNgIUKOZ5wsbJu
01049 fcmNfrM1iEoWnIyKqRGqWHoFd0sdEOmAJAAAOw==
01050 }
01051 image create photo ::domtree::Comment -data {R0lGODlhEAAQAKL/AP///8fHx7CwsJ6enpycnHp6egAAAP///yH/C0FET0JFOklSMS4wAt7t
01052 ACH5BAEAAAcALAAAAAAQABAAAANDeLrcazBGZ4C917CKTegPBnigwmVDJ5iikWbEelpuV8hi
01053 bhTEMY8vGo+VE8Yeswhv1eDsCkuHb8Qj9KSRo9RniDG3CQA7
01054 }
01055 image create photo ::domtree::EntityReference -data {R0lGODlhEAAQALP/AP7+/vfQ0NOsrMmZmci5uYMwMIJfX2YAAEoBAf///wAAAAAAAAAAAAAA
01056 AAAAAAAAACH/C0FET0JFOklSMS4wAt7tACH5BAEAAAkALAAAAAAQABAAAARPMEl5jAlhzJ2O
01057 r1WmbV+CfEdGVtzJTp4xwq90XuvBmZVAeTtbxVAK0nQTYg11mKUGyJJL8ykQOiwAr1nsyDau
01058 mgn3+8xsFwuzeUYopR5NBAA7
01059 }
01060 image create photo ::domtree::other -data {R0lGODlhEAAOAKL/AP///39/fxAQEAAAAP///wAAAAAAAAAAACH/C0FET0JFOklSMS4wAt7t
01061 ACH5BAEAAAQALAAAAAAQAA4AAAM4SDSj/m8E0ByrdtI1wI4aFV6ZR5kiJpmrJ6kj+pbuGMCs
01062 fIO1O/MdhmcHeUkCSGJEIriQIByoIwEAOw==
01063 }
01064 image create photo ::domtree::collapse -data {R0lGODlhEAAQALIAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMyH5BAUAAAYA
01065 LAAAAAAQABAAggAAAGZmzIiIiLu7u5mZ/8zM/////wAAAAMlaLrc/jDKSRm4
01066 OAMHiv8EIAwcYRKBSD6AmY4S8K4xXNFVru9SAgAh/oBUaGlzIGFuaW1hdGVk
01067 IEdJRiBmaWxlIHdhcyBjb25zdHJ1Y3RlZCB1c2luZyBVbGVhZCBHSUYgQW5p
01068 bWF0b3IgTGl0ZSwgdmlzaXQgdXMgYXQgaHR0cDovL3d3dy51bGVhZC5jb20g
01069 dG8gZmluZCBvdXQgbW9yZS4BVVNTUENNVAAh/wtQSUFOWUdJRjIuMAdJbWFn
01070 ZQEBADs=
01071 }
01072 image create photo ::domtree::expand -data {R0lGODlhEAAQALIAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMyH5BAUAAAYA
01073 LAAAAAAQABAAggAAAGZmzIiIiLu7u5mZ/8zM/////wAAAAMnaLrc/lCB6MCk
01074 C5SLNeGR93UFQQRgVaLCEBasG35tB9Qdjhny7vsJACH+gFRoaXMgYW5pbWF0
01075 ZWQgR0lGIGZpbGUgd2FzIGNvbnN0cnVjdGVkIHVzaW5nIFVsZWFkIEdJRiBB
01076 bmltYXRvciBMaXRlLCB2aXNpdCB1cyBhdCBodHRwOi8vd3d3LnVsZWFkLmNv
01077 bSB0byBmaW5kIG91dCBtb3JlLgFVU1NQQ01UACH/C1BJQU5ZR0lGMi4wB0lt
01078 YWdlAQEAOw==
01079 }
01080 
01081 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1