domtree.tcl

Go to the documentation of this file.
00001 /*  domtree.tcl --*/
00002 /* */
00003 /*  Extension to tree (mega)widget to support display of a DOM hierarchy.*/
00004 /* */
00005 /*  This widget both generates and reacts to DOM Events.*/
00006 /* */
00007 /*  This package features ordered and non-unique directories and items.*/
00008 /*  Paths are managed as live links into a DOM hierarchy.*/
00009 /* */
00010 /*  Copyright (c) 1999-2003 Zveno Pty Ltd*/
00011 /*  http://www.zveno.com/*/
00012 /* */
00013 /*  See the file "LICENSE" in this distribution for information on usage and*/
00014 /*  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00015 /* */
00016 /*  $Id: domtree.tcl,v 1.5 2003/12/09 04:56:40 balls Exp $*/
00017 
00018 package provide domtree 2.5
00019 
00020 /*  We need BWidgets*/
00021 
00022 package require BWidget 1.4
00023 
00024 /*  We need the DOM*/
00025 /*  V2.0 gives us Level 2 event model*/
00026 /*  V2.1 gives us libxml2*/
00027 
00028 package require dom 2.5
00029 
00030 namespace domtree {
00031     Tree::use
00032 
00033     Widget::bwinclude domtree Tree .tree
00034 
00035     Widget::declare domtree {
00036         {-rootnode         String  ""        0}
00037     {-showlength       Int     20        0}
00038     {-showtextcontent  Boolean 0         0}
00039     {-showelementid    Boolean 0         0}
00040     }
00041 
00042     ret  ::domtree ( type path , type args ) { return [eval domtree::create $path $args] }
00043     ret  use () {}
00044 
00045     variable eventTypeMap
00046     array  eventTypeMap =  {
00047     ButtonPress mousedown
00048     ButtonRelease   mouseup
00049     Enter       mouseover
00050     Leave       mouseout
00051     Motion      mousemove
00052     FocusIn     DOMFocusIn
00053     FocusOut    DOMFocusOut
00054     }
00055 }
00056 
00057 /*  domtree::create --*/
00058 /* */
00059 /*  Create a DOM Tree widget*/
00060 /* */
00061 /*  Arguments:*/
00062 /*  path    widget path*/
00063 /*  args    configuration options*/
00064 /* */
00065 /*  Results:*/
00066 /*  Tree widget created*/
00067 
00068 ret  domtree::create (type path , type args) {
00069     array set maps [list Tree {} :cmd {} .tree {}]
00070     array set maps [Widget::parseArgs domtree $args]
00071 
00072     eval frame $path $maps(:cmd) -bd 0 -relief flat -takefocus 0 \
00073         -class domtree -highlightthickness 0
00074 
00075     Widget::initFromODB domtree $path $maps(Tree)
00076 
00077     bindtags $path [list $path Bwdomtree [winfo toplevel $path] all]
00078 
00079     set tree [eval ::Tree::create $path.tree $maps(.tree) \
00080         -opencmd [list [namespace code [list _node_open $path]]] \
00081         -selectcommand [list [namespace code [list _select_node $path]]]]
00082 
00083     $tree configure -xscrollcommand [Widget::cget $path -xscrollcommand] \
00084     -yscrollcommand [Widget::cget $path -yscrollcommand]
00085 
00086     # Set various bindings to generate DOM events
00087 
00088     foreach event {ButtonRelease ButtonPress Enter Leave Motion} {
00089     $path.tree bindImage <$event> [namespace code [list _node_mouse_event $event {} $path]]
00090     $path.tree bindText <$event> [namespace code [list _node_mouse_event $event {} $path]]
00091     foreach modifier {Control Shift Alt Meta Double} {
00092         $path.tree bindImage <$modifier-$event> [namespace code [list _node_mouse_event $event $modifier $path]]
00093         $path.tree bindText <$modifier-$event> [namespace code [list _node_mouse_event $event $modifier $path]]
00094     }
00095     }
00096 
00097     grid $tree -row 0 -column 0 -sticky news
00098     grid rowconfigure $path 0 -weight 1
00099     grid columnconfigure $path 0 -weight 1
00100 
00101     $path configure -background [Widget::cget $path -background]
00102         
00103     rename $path ::$path:cmd
00104     proc ::$path { cmd args } "return \[eval domtree::\$cmd $path \$args\]"
00105 
00106     set root [Widget::getMegawidgetOption $path -rootnode]
00107     if {[string length $root]} {
00108     _add_node $path root $root
00109     }
00110 
00111     return $path
00112 }
00113 
00114 /*  domtree::cget --*/
00115 /* */
00116 /*  Implements the cget method*/
00117 /* */
00118 /*  Arguments:*/
00119 /*  path    widget path*/
00120 /*  option  configuration option*/
00121 /* */
00122 /*  Results:*/
00123 /*  Returns value of option*/
00124 
00125 ret  domtree::cget (type path , type option) {
00126     return [Widget::getoption $path $option]
00127 }
00128 
00129 /*  domtree::configure --*/
00130 /* */
00131 /*  Implements the configure method*/
00132 /* */
00133 /*  Arguments:*/
00134 /*  path    widget path*/
00135 /*  args    configuration options*/
00136 /* */
00137 /*  Results:*/
00138 /*  Sets value of options*/
00139 
00140 ret  domtree::configure (type path , type args) {
00141     if {[catch {eval configure:dbg [list $path] $args} msg]} {
00142     puts stderr "domtree::configure incurred error\n$msg"
00143     } else {
00144     #puts stderr [list domtree::configure ran OK]
00145     }
00146 }
00147 
00148 ret  domtree::configure:dbg (type path , type args) {
00149     set res [Widget::configure $path $args]
00150 
00151     set rn [Widget::hasChanged $path -rootnode root]
00152     if {$rn} {
00153 
00154     eval Tree::delete $path.tree [Tree::nodes $path.tree root]
00155     # Remove event listeners from previous DOM tree
00156 
00157     if {[llength $root]} {
00158         #puts stderr [list domtree::configure root $root]
00159         set docel [dom::document cget $root -documentElement]
00160         if {[string length $docel]} {
00161         _refresh $path $root
00162         _add_node $path root $root
00163 
00164         # Listen for UI events
00165         dom::node addEventListener $docel DOMActivate [namespace code [list _node_selected $path]] -usecapture 1
00166 
00167         # Listen for mutation events
00168         dom::node addEventListener $docel DOMSubtreeModified [namespace code [list _node_tree_modified $path]] -usecapture 1
00169         dom::node addEventListener $docel DOMNodeInserted [namespace code [list _node_inserted $path]] -usecapture 1
00170         dom::node addEventListener $docel DOMNodeRemoved [namespace code [list _node_removed $path]] -usecapture 1
00171         dom::node addEventListener $docel DOMCharacterDataModified [namespace code [list _node_data_modified $path]] -usecapture 1
00172         dom::node addEventListener $docel DOMAttrModified [namespace code [list _node_attr_modified $path]] -usecapture 1
00173         dom::node addEventListener $docel DOMAttrRemoved [namespace code [list _node_attr_removed $path]] -usecapture 1
00174         }
00175     }
00176     }
00177 
00178     if {!$rn && [Widget::hasChanged $path -showtextcontent showtext]} {
00179     _refresh_all $path root
00180     }
00181 
00182     return $res
00183 }
00184 
00185 /*  domtree::refresh --*/
00186 /* */
00187 /*  Updates the Tree display with the value of a node*/
00188 /* */
00189 /*  Arguments:*/
00190 /*  path    widget path*/
00191 /*  node    DOM node*/
00192 /* */
00193 /*  Results:*/
00194 /*  May change node display*/
00195 
00196 ret  domtree::refresh (type path , type node) {
00197     _refresh $path $node
00198     return {}
00199 }
00200 
00201 /*  domtree::xview --*/
00202 /* */
00203 /*  Implement xview method*/
00204 /* */
00205 /*  Arguments:*/
00206 /*  path    widget path*/
00207 /*  args    additional arguments*/
00208 /* */
00209 /*  Results:*/
00210 /*  Depends on Tree xview method*/
00211 
00212 ret  domtree::xview (type path , type args) {
00213     eval $path.tree xview $args
00214 }
00215 
00216 /*  domtree::yview --*/
00217 /* */
00218 /*  Implement yview method*/
00219 /* */
00220 /*  Arguments:*/
00221 /*  path    widget path*/
00222 /*  args    additional arguments*/
00223 /* */
00224 /*  Results:*/
00225 /*  Depends on Tree yview method*/
00226 
00227 ret  domtree::yview (type path , type args) {
00228     eval $path.tree yview $args
00229 }
00230 
00231 /*  domtree::find --*/
00232 /* */
00233 /*  Find DOM node at given location*/
00234 /* */
00235 /*  Arguments:*/
00236 /*  path    widget path*/
00237 /*  findInfo    location*/
00238 /*  confine*/
00239 /* */
00240 /*  Results:*/
00241 /*  DOM node at location*/
00242 
00243 ret  domtree::find (type path , type findInfo , optional confine ={)} {
00244     set tnode [$path.tree find $findInfo $confine]
00245     return [_tree_to_dom $tnode]
00246 }
00247 
00248 # domtree::_dom_to_tree --
00249 #
00250 #   Map a DOM node to a tree node
00251 #
00252 # Arguments:
00253 #   node    DOM node id
00254 #
00255 # Results:
00256 #   A string suitable for use as a tree node path
00257 
00258 proc domtree::_dom_to_tree node {
00259     if {[catch {dom::document cget $node -documentElement} docel]} {
00260     return $node
00261     } else {
00262     return root
00263     }
00264 }
00265 
00266 /*  domtree::_tree_to_dom --*/
00267 /* */
00268 /*  Map a tree node to a DOM node*/
00269 /* */
00270 /*  Arguments:*/
00271 /*  node    Tree node path*/
00272 /* */
00273 /*  Results:*/
00274 /*  A string suitable for use as a DOM node id*/
00275 
00276 ret  domtree::_tree_to_dom node (
00277     type if , optional [string =compare $node ="root"] , optional 
00278     return =$node
00279      , type else , optional 
00280     # =Really want =to return =the document =node,
00281     # =but don't =know it =here
00282     return ={
00283     )
00284 }
00285 
00286 # domtree::_open_ancestors --
00287 #
00288 #   Make sure that all ancestors of the given node are open.
00289 #   Don't use "opentree", since that will recursively open
00290 #   all children.
00291 #
00292 # Arguments:
00293 #   path    widget path
00294 #   node    tree node
00295 #
00296 # Results:
00297 #   All ancestors of the node are opened
00298 
00299 proc domtree::_open_ancestors {path node} {
00300     while {[string compare $node root]} {
00301     /* $path.tree opentree $node*/
00302     if {[namespace ::Tree [list Widget::getoption $path.tree.$node -open]] != 1} {
00303         namespace ::Tree [list Widget::option =  $path.tree.$node -open 1]
00304         uplevel /* 0 [namespace eval ::Tree [list Widget::getoption $path.tree -opencmd]] [list $node]*/
00305     }
00306      node =  [$path.tree parent $node]
00307     }
00308 }
00309 
00310 /*  Procedures to implement display*/
00311 
00312 /*  domtree::_refresh --*/
00313 /* */
00314 /*  Configure node with appropriate images, labels, etc*/
00315 /* */
00316 /*  Arguments:*/
00317 /*  path    widget path*/
00318 /*  node    DOM node*/
00319 /*  args    additional options*/
00320 /* */
00321 /*  Results:*/
00322 /*  Tree node may have image or label changed*/
00323 
00324 ret  domtree::_refresh (type path , type node , type args) {
00325 
00326     #puts stderr [list domtree::_refresh $path $node]
00327 
00328     switch [set nodetype [::dom::node cget $node -nodeType]] {
00329     document -
00330     documentFragment -
00331     element {
00332         set label [dom::node cget $node -nodeName]
00333         set icon ::domtree::element
00334 
00335         if {![string compare $nodetype element]} {
00336 
00337         # ID attribute display
00338         if {[Widget::getoption $path -showelementid]} {
00339             array set attributes [array get [::dom::node cget $node -attributes]]
00340             if {[catch {
00341             append label "    (id $attributes(id))"
00342             }] && [catch {
00343             append label "    (ID $attributes(ID))"
00344             }]} {}
00345         }
00346 
00347         if {[Widget::getoption $path -showtextcontent]} {
00348             # Text content display
00349             set temp [_refresh_text_content_display_find_text $node [Widget::getoption $path -showlength]]
00350             if {[string length $temp]} {
00351             append label "    \[ [_refresh_string_trim $temp [Widget::getoption $path -showlength]] \]"
00352             }
00353         }
00354 
00355         }
00356 
00357         if {![string length [dom::node parent $node]]} {
00358         # Root node is special
00359         return {}
00360         }
00361 
00362     }
00363     textNode {
00364         array set opts [list -label [dom::node cget $node -nodeValue]]
00365         array set opts $args
00366         set label [_refresh_string_trim [string trim $opts(-label)] [Widget::getoption $path -showlength]]
00367         set icon ::domtree::textNode
00368 
00369         # Also do the ancestors
00370         foreach ancestor [lrange [lreplace [::dom::node path $node] end end] 1 end] {
00371         _refresh $path $ancestor
00372         }
00373     }
00374     processingInstruction {
00375         set label [string trim [dom::node cget $node -nodeName]]
00376         set icon ::domtree::PI
00377     }
00378     docType {
00379         set label {}
00380         set icon ::domtree::DocType
00381     }
00382     comment {
00383         set label [_refresh_string_trim [string trim [::dom::node cget $node -nodeValue]] [Widget::getoption $path -showlength]]
00384         set icon ::domtree::Comment
00385     }
00386     entityReference {
00387         set label [::dom::node cget $node -nodeName]
00388         set icon ::domtree::EntityReference
00389     }
00390     default {
00391         set label $nodetype
00392         set icon ::domtree::other
00393     }
00394     }
00395 
00396     catch {
00397     $path.tree itemconfigure [_dom_to_tree $node] -image $icon
00398     $path.tree itemconfigure [_dom_to_tree $node] -text $label
00399     }
00400 
00401     return {}
00402 }
00403 
00404 /*  domtree::_refresh_text_content_display_find_text --*/
00405 /* */
00406 /*  Searches given element for text.*/
00407 /*  In future could use XPath - just get the string value*/
00408 /*  of the node.*/
00409 /* */
00410 /*  Arguments:*/
00411 /*  node    DOM element node to search*/
00412 /*  len amount of text to return*/
00413 /* */
00414 /*  Results:*/
00415 /*  Returns string*/
00416 
00417 ret  domtree::_refresh_text_content_display_find_text (type node , type len) {
00418     switch -- $len {
00419     0 {
00420         return {}
00421     }
00422     default {
00423         set text {}
00424         foreach child [::dom::node children $node] {
00425         switch [::dom::node cget $child -nodeType] {
00426             document -
00427             documentFragment -
00428             element {
00429             append text \
00430                 [_refresh_text_content_display_find_text $child [expr $len - [string length $text]]]
00431             }
00432             textNode {
00433             append text [string range \
00434                 [::dom::node cget $child -nodeValue] \
00435                 0 [expr $len - [string length $text]] \
00436             ]
00437             }
00438             default {
00439             # Nothing to do
00440             }
00441         }
00442         if {[string length $text] >= $len} {
00443             return $text
00444         }
00445         }
00446 
00447         return $text
00448 
00449     }
00450     }
00451 
00452     return {}
00453 }
00454 
00455 /*  domtree::_refresh_all --*/
00456 /* */
00457 /*  Updates display of all tree nodes*/
00458 /* */
00459 /*  Arguments:*/
00460 /*  path    widget pathname*/
00461 /*  node    Tree node*/
00462 /* */
00463 /*  Results:*/
00464 /*  Returns empty string*/
00465 
00466 ret  domtree::_refresh_all (type path , type node) {
00467     foreach child [$path.tree nodes $node] {
00468     _refresh $path [_tree_to_dom $child]
00469     _refresh_all $path $child
00470     }
00471 
00472     return {}
00473 }
00474 
00475 /*  domtree::_refresh_string_trim --*/
00476 /* */
00477 /*  Massage text for display*/
00478 /* */
00479 /*  Arguments:*/
00480 /*  text    text string*/
00481 /*  max maximum length for string*/
00482 /* */
00483 /*  Results:*/
00484 /*  Returns string*/
00485 
00486 ret  domtree::_refresh_string_trim (type text , type max) {
00487     if {[string length $text] > $max} {
00488     set text [string range $text 0 [expr $max - 3]]...
00489     }
00490     if {[info tclversion] >= 8.1} {
00491     set dot \u2022
00492     } else {
00493     set dot { }
00494     }
00495     regsub -all [format {[%s%s%s%s]+} \n \r { } \t] $text $dot text
00496     return $text
00497 }
00498 
00499 /*  domtree::_node_selected --*/
00500 /* */
00501 /*  A node has been selected.*/
00502 /* */
00503 /*  This is invoked via a DOM event.*/
00504 /* */
00505 /*  Arguments:*/
00506 /*  path    widget path*/
00507 /*  evid    event node*/
00508 
00509 ret  domtree::_node_selected (type path , type evid) {
00510 
00511     set domnode [dom::event cget $evid -target]
00512 
00513     # Temporarily remove the -selectcommand callback
00514     # to avoid an infinite loop (continually posting DOM click events)
00515     set cmd [$path.tree cget -selectcommand]
00516     $path.tree configure -selectcommand {}
00517 
00518     $path.tree selection set [_dom_to_tree $domnode]
00519 
00520     $path.tree configure -selectcommand $cmd
00521 
00522     return {}
00523 }
00524 
00525 /*  domtree::_select_node --*/
00526 /* */
00527 /*  A tree node has been selected.*/
00528 /* */
00529 /*  Arguments:*/
00530 /*  path    widget path*/
00531 /*  tree    tree path*/
00532 /*  tnode   tree node*/
00533 
00534 ret  domtree::_select_node (type path , type tree , type tnode) {
00535 
00536     dom::event postMouseEvent [_tree_to_dom $tnode] click -detail 1
00537 
00538     return {}
00539 }
00540 
00541 /*  domtree::_node_mouse_event --*/
00542 /* */
00543 /*  Generate DOM Mouse Event*/
00544 /* */
00545 /*  Arguments:*/
00546 /*  event   event type*/
00547 /*  mod modifier*/
00548 /*  path    widget path*/
00549 /*  tnode   tree node*/
00550 /* */
00551 /*  Results:*/
00552 /*  Event synthesized for DOM*/
00553 
00554 ret  domtree::_node_mouse_event (type event , type mod , type path , type tnode) {
00555     variable eventTypeMap
00556 
00557     set type $event
00558     catch {set type $eventTypeMap($event)}
00559 
00560     set evid [dom::document createEvent [_tree_to_dom $tnode] $type]
00561     dom::event initMouseEvent $evid $type 1 1 {} 0 0 0 0 0 \
00562         [expr {$mod == "Control"}] \
00563         [expr {$mod == "Alt"}] \
00564         [expr {$mod == "Shift"}] \
00565         [expr {$mod == "Meta"}] \
00566         0 {}
00567     dom::node dispatchEvent [_tree_to_dom $tnode] $evid
00568     dom::destroy $evid
00569 
00570     # ButtonRelease events also generate DOMActivate events
00571 
00572     if {![string compare $event "ButtonRelease"]} {
00573     set detail 1
00574     if {![string compare $mod "Double"]} {
00575         set detail 2
00576     }
00577     dom::event postUIEvent [_tree_to_dom $tnode] DOMActivate -detail $detail
00578     }
00579 
00580     return {}
00581 }
00582 
00583 /*  domtree::_node_ui_event --*/
00584 /* */
00585 /*  Generate DOM UI Event*/
00586 /* */
00587 /*  Arguments:*/
00588 /*  event   event type*/
00589 /*  path    widget path*/
00590 /*  tnode   tree node*/
00591 /* */
00592 /*  Results:*/
00593 /*  Event synthesized for DOM*/
00594 
00595 ret  domtree::_node_ui_event (type event , type path , type tnode) {
00596     variable eventTypeMap
00597 
00598     set type $event
00599     catch {set type $eventTypeMap($event)}
00600     dom::event postUIEvent [_tree_to_dom $tnode] $type
00601 
00602     return {}
00603 }
00604 
00605 /*  domtree::_add_node --*/
00606 /* */
00607 /*  Recurse DOM structure, inserting tree nodes as we go.*/
00608 /* */
00609 /*  Trouble is, this is very expensive when beyond a certain*/
00610 /*  depth we're not going to see the nodes anyway.*/
00611 /*  Instead, build the tree as the user opens nodes.*/
00612 /*  This will spread the cost of building the tree, and the*/
00613 /*  user may never open certain nodes anyway.*/
00614 /* */
00615 /*  Arguments:*/
00616 /*  path    widget path*/
00617 /*  tnode   tree node to add children to*/
00618 /*  dnode   DOM node corresponding to tree path above*/
00619 /* */
00620 /*  Results:*/
00621 /*  Nodes added to tree*/
00622 
00623 ret  domtree::_add_node (type path , type tnode , type dnode) {
00624 
00625     if {[string compare $tnode "root"]} {
00626 
00627     # If the grandparent is open, then do add the items
00628     # This is so that the open/close toggle is added to the parent
00629 
00630     set parent [$path.tree parent $tnode]
00631 
00632     if {[string compare $parent "root"]} {
00633         set grandParent [$path.tree parent $parent]
00634         if {[string compare $grandParent "root"]} {
00635 
00636         # We are beyond the second level from the root
00637 
00638         array set ParentInfo [$path.tree itemcget $parent -data]
00639         array set GrandParentInfo [$path.tree itemcget $grandParent -data]
00640         if {[info exists ParentInfo(nodeOpen)]} {
00641             # Parent is open, so add ourself
00642         } elseif {[info exists GrandParentInfo(nodeOpen)]} {
00643             # Grandparent is open, so add ourself
00644         } else {
00645             return {}
00646         }
00647 
00648         } else {
00649         # We are two levels down from the root.  Go ahead and build,
00650         # but don't automatically mark this node as being open.
00651         }
00652 
00653     } else {
00654         # We are a child of the root, so go ahead and build here
00655         _set_client_data $path $tnode nodeOpen 1
00656     }
00657 
00658     } else {
00659     # We are the root node, so definitely go ahead and build children
00660     }
00661 
00662     foreach child [::dom::node children $dnode] {
00663     # Due to lazy population of the tree, the node may already exist
00664     catch {$path.tree insert end $tnode [_dom_to_tree $child]}
00665     _refresh $path $child
00666 
00667     _add_node $path [_dom_to_tree $child] $child
00668     }
00669 
00670     return {}
00671 }
00672 
00673 /*  domtree::_set_client_data --*/
00674 /* */
00675 /*  Manage data for tree nodes*/
00676 /* */
00677 /*  Arguments:*/
00678 /*  path    widget path*/
00679 /*  node    tree node*/
00680 /*  field   field name*/
00681 /*  value   value for field*/
00682 /* */
00683 /*  Results:*/
00684 /*  Item's configuration changed*/
00685 
00686 ret  domtree::_set_client_data (type path , type node , type field , type value) {
00687     array set nodeinfo [$path.tree itemcget $node -data]
00688     set nodeinfo($field) $value
00689     $path.tree itemconfigure $node -data [array get nodeinfo]
00690 }
00691 
00692 /*  domtree::_unset_client_data --*/
00693 /* */
00694 /*  Manage data for tree nodes*/
00695 /* */
00696 /*  Arguments:*/
00697 /*  path    widget path*/
00698 /*  node    tree node*/
00699 /*  field   field name to unset*/
00700 /* */
00701 /*  Results:*/
00702 /*  Item's configuration changed*/
00703 
00704 ret  domtree::_unset_client_data (type path , type node , type field) {
00705     array set nodeinfo [$path.tree itemcget $node -data]
00706     catch {unset nodeinfo($field)}
00707     $path.tree itemconfigure $node -data [array get nodeinfo]
00708 }
00709 
00710 /*  domtree::_node_open --*/
00711 /* */
00712 /*  Invoked when a tree item is opened.*/
00713 /*  If we haven't done this node's children yet, */
00714 /*  do it now.  This lazily populates the tree.*/
00715 /* */
00716 /*  Arguments:*/
00717 /*  path    widget path*/
00718 /*  node    tree node*/
00719 /* */
00720 /*  Results:*/
00721 /*  Tree nodes may be added*/
00722 
00723 ret  domtree::_node_open (type path , type node) {
00724 
00725     _set_client_data $path $node nodeOpen 1
00726     _add_node $path $node [_tree_to_dom $node]
00727 
00728     return {}
00729 }
00730 
00731 /*  domtree::_node_tree_modified --*/
00732 /* */
00733 /*  Invoked when the node's subtree has changed.*/
00734 /*  Could be because a child node has been removed.*/
00735 /* */
00736 /*  Refresh the*/
00737 /*  display of the node, since if textual content*/
00738 /*  is enabled the node's string value may have*/
00739 /*  changed.*/
00740 /* */
00741 /*  Arguments:*/
00742 /*  path    widget path*/
00743 /*  evid    DOM event node*/
00744 /* */
00745 /*  Results:*/
00746 /*  Tree nodes inserted or removed*/
00747 
00748 ret  domtree::_node_tree_modified (type path , type evid) {
00749 
00750     set target [dom::event cget $evid -target]
00751     set children [dom::node children $target]
00752     set branch [Tree::nodes $path.tree [_dom_to_tree $target]]
00753     if {[llength $children] < [llength $branch]} {
00754     for {set idx 0} {$idx < [llength $branch]} {incr idx} {
00755         if {![string length [lindex $children $idx]] || \
00756             [_dom_to_tree [lindex $children $idx]] != [lindex $branch $idx]} {
00757         $path.tree delete [lindex $branch $idx]
00758         break
00759         }
00760     }
00761     }
00762 
00763     _refresh $path [dom::event cget $evid -currentNode]
00764 
00765     return {}
00766 }
00767 
00768 /*  domtree::_node_inserted --*/
00769 /* */
00770 /*  A node has been inserted.*/
00771 /* */
00772 /*  Arguments:*/
00773 /*  path    widget path*/
00774 /*  evid    DOM event node*/
00775 /* */
00776 /*  Results:*/
00777 /*  Insert tree node*/
00778 
00779 ret  domtree::_node_inserted (type path , type evid) {
00780 
00781     # Find where the node was inserted into the child list
00782     set newnode [dom::event cget $evid -target]
00783     set parent [dom::node parent $newnode]
00784     set children [dom::node children $parent]
00785     set idx [lsearch $children $newnode]
00786 
00787     # Get old tree info
00788     set tparent [_dom_to_tree $parent]
00789     set branch [Tree::nodes $path.tree $tparent]
00790 
00791     if {$idx > [llength $branch]} {
00792     # Append the new node to the branch
00793     $path.tree insert end $tparent [_dom_to_tree $newnode]
00794     } else {
00795     # Insert the new node into the branch
00796     $path.tree insert $idx $tparent [_dom_to_tree $newnode]
00797     }
00798 
00799     _refresh $path $newnode
00800     _add_node $path [_dom_to_tree $newnode] $newnode
00801 
00802     return {}
00803 }
00804 
00805 /*  domtree::_node_removed --*/
00806 /* */
00807 /*  A node has been removed.*/
00808 /* */
00809 /*  Arguments:*/
00810 /*  path    widget path*/
00811 /*  evid    DOM event node*/
00812 /* */
00813 /*  Results:*/
00814 /*  Remove tree node*/
00815 
00816 ret  domtree::_node_removed (type path , type evid) {
00817 
00818     set oldnode [dom::event cget $evid -target]
00819     Tree::delete $path.tree [_dom_to_tree $oldnode]
00820 
00821     return {}
00822 }
00823 
00824 /*  domtree::_node_data_modified --*/
00825 /* */
00826 /*  Character data has changed*/
00827 /* */
00828 /*  Arguments:*/
00829 /*  path    widget path*/
00830 /*  evid    DOM L2 event node*/
00831 /* */
00832 /*  Results:*/
00833 /*  Tree display updated*/
00834 
00835 ret  domtree::_node_data_modified (type path , type evid) {
00836     _refresh $path [dom::event cget $evid -target] \
00837         -label [dom::event cget $evid -newValue]
00838     return {}
00839 }
00840 
00841 /*  domtree::_node_attr_modified --*/
00842 /* */
00843 /*  Attribute value modified*/
00844 /* */
00845 /*  Arguments:*/
00846 /*  path    widget path*/
00847 /*  evid    DOM L2 event node*/
00848 /* */
00849 /*  Results:*/
00850 /*  Display updated*/
00851 
00852 ret  domtree::_node_attr_modified (type path , type evid) {
00853     _refresh $path [dom::event cget $evid -target]
00854     return {}
00855 }
00856 
00857 /*  domtree::_node_attr_removed --*/
00858 /* */
00859 /*  Attribute removed*/
00860 /* */
00861 /*  Arguments:*/
00862 /*  path    widget path*/
00863 /*  evid    DOM L2 event node*/
00864 /* */
00865 /*  Results:*/
00866 /*  Display updated*/
00867 
00868 ret  domtree::_node_attr_removed (type path , type evid) {
00869     _refresh $path [dom::event cget $evid -target]
00870     return {}
00871 }
00872 
00873 /*  Image data*/
00874 
00875 image create photo ::domtree::element -data {R0lGODlhEAAQANX/AP7///3//vv+/vn+/fj+/ff9/fb9/fL8/PL6+e/8++78+u37+uz7+ur7
00876 +ef6+d349tv49df18tT289P288718sPz773y7bPw6qzo4qTt5o3o4Ivn4IHb0nTj2XPj2Wrh
00877 107bzzDVxxnQwRecjBCtmRCtmA+AdA6Hew21oQ2NgQq+rQqjlQpoXApmWgm/rQeekAXMuwXG
00878 tQTMu////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C0FET0JFOklS
00879 MS4wAt7tACH5BAEAADMALAAAAAAQABAAAAaRwJlwCBgajZCKBeE4GhuXCCIinQycs+iUA8N4
00880 HgHnZyuTcUoZAyAwIAgA5LKMNGIckksHgiOXoRAnElpUCCB8MlKEGolcGBsiMIwyGCFxHBMd
00881 LpZxZQMPnDJ7fSVConIlKocyJSNChqcjKzEwqyMmQo+0rCYpLyUmwC1CmL/BLBQZIy3KQp7J
00882 yy0KAgUJCwcCQQA7
00883 }
00884 image create photo ::domtree::textNode -data {R0lGODlhEAAOAJH/AP///39/fwAAAP///yH/C0FET0JFOklSMS4wAt7tACH5BAEAAAMALAAA
00885 AAAQAA4AAAI0nIUpxi0AIWoOhAveouPFnHDPhV1CQHmfhFYkmbWMup6p9QbxvbJ3rrNVejuH
00886 4ihjAF+GAgA7
00887 }
00888 image create photo ::domtree::PI -data {R0lGODdhEAAOAPEAALLA3AAAAAAA/////ywAAAAAEAAOAAACL4yPoBvi78Jio9oqJwh3oG90
00889 DfSEF9dhKIioGFmqR4phFL3eaa6g+6ETaTYsw6IAADs=
00890 }
00891 image create photo ::domtree::DocType -data {R0lGODlhEAAQAKL/APfQ0MmZmYJfX2YAAEoBAf///wAAAAAAACH/C0FET0JFOklSMS4wAt7t
00892 ACH5BAEAAAUALAAAAAAQABAAAAM7WDKyUjBGB8AaUl4RQFhZNIxM8D2hQJBNgIUKOZ5wsbJu
00893 fcmNfrM1iEoWnIyKqRGqWHoFd0sdEOmAJAAAOw==
00894 }
00895 image create photo ::domtree::Comment -data {R0lGODlhEAAQAKL/AP///8fHx7CwsJ6enpycnHp6egAAAP///yH/C0FET0JFOklSMS4wAt7t
00896 ACH5BAEAAAcALAAAAAAQABAAAANDeLrcazBGZ4C917CKTegPBnigwmVDJ5iikWbEelpuV8hi
00897 bhTEMY8vGo+VE8Yeswhv1eDsCkuHb8Qj9KSRo9RniDG3CQA7
00898 }
00899 image create photo ::domtree::EntityReference -data {R0lGODlhEAAQALP/AP7+/vfQ0NOsrMmZmci5uYMwMIJfX2YAAEoBAf///wAAAAAAAAAAAAAA
00900 AAAAAAAAACH/C0FET0JFOklSMS4wAt7tACH5BAEAAAkALAAAAAAQABAAAARPMEl5jAlhzJ2O
00901 r1WmbV+CfEdGVtzJTp4xwq90XuvBmZVAeTtbxVAK0nQTYg11mKUGyJJL8ykQOiwAr1nsyDau
00902 mgn3+8xsFwuzeUYopR5NBAA7
00903 }
00904 image create photo ::domtree::other -data {R0lGODlhEAAOAKL/AP///39/fxAQEAAAAP///wAAAAAAAAAAACH/C0FET0JFOklSMS4wAt7t
00905 ACH5BAEAAAQALAAAAAAQAA4AAAM4SDSj/m8E0ByrdtI1wI4aFV6ZR5kiJpmrJ6kj+pbuGMCs
00906 fIO1O/MdhmcHeUkCSGJEIriQIByoIwEAOw==
00907 }
00908 
00909 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1