1 # Variable tree implementation for Insight.
2 # Copyright (C) 2002 Red Hat, Inc.
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License (GPL) as published by
6 # the Free Software Foundation; either version 2 of the License, or (at
7 # your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 itcl::body VarTree::constructor {args} {
19 eval itk_initialize $args
21 itk_component add canvas {
22 iwidgets::scrolledcanvas $itk_interior.c -autoresize 1 -hscrollmode dynamic -vscrollmode dynamic \
23 -background $::Colors(textbg) -borderwidth 0 -highlightthickness 0
25 set c [$itk_component(canvas) childsite]
26 pack $itk_component(canvas) -side top -fill both -expand 1
27 bind $c <1> "[code $this clicked %W %x %y 0]"
29 # Add popup menu - we populate it in _but3
30 itk_component add popup {
31 menu $itk_interior.pop -tearoff 0
33 set pop $itk_component(popup)
34 $pop configure -disabledforeground $::Colors(fg)
35 bind $c <3> [code $this _but3 %x %y %X %Y]
39 after idle [code $this build]
42 itcl::body VarTree::destructor {} {
46 itcl::body VarTree::build {} {
49 catch {unset var_to_items}
50 catch {unset item_to_var}
52 buildlayer $rootlist 10
53 $c config -scrollregion [$c bbox all] -background $::Colors(textbg) -borderwidth 0 -highlightthickness 0
58 itcl::body VarTree::buildlayer {tlist in} {
59 set start [expr $_y - 10]
66 $c create line $in $y [expr $in+10] $y -fill $colors(line)
70 set j1 [$c create text $x $y -text "[$var name] = " -fill $colors(name) -anchor w -font global/fixed]
71 set x [expr [lindex [$c bbox $j1] 2] + 5]
72 set j2 [$c create text $x $y -text "([$var type])" -fill $colors(type) -anchor w -font global/fixed]
73 set x [expr [lindex [$c bbox $j2] 2] + 5]
74 if {[catch {$var value} val]} {
75 # error accessing memory, etc.
76 set j3 [$c create text $x $y -text $val -fill $colors(error) -anchor w -font global/fixed]
78 set j3 [$c create text $x $y -text $val -fill $colors(value) -anchor w -font global/fixed]
81 set var_to_items($var) [list $j1 $j2 $j3]
82 set item_to_var($j1) $var
83 set item_to_var($j2) $var
84 set item_to_var($j3) $var
86 $c bind $j1 <Double-1> "[code $this clicked %W %x %y 1]"
87 $c bind $j2 <Double-1> "[code $this clicked %W %x %y 1]"
88 $c bind $j3 <Double-1> "[code $this edit $j3];break"
90 if {[$var numChildren]} {
92 set j [$c create image $in $y -image closedbm]
93 $c bind $j <1> "[code $this open $var]"
95 set j [$c create image $in $y -image openbm]
96 $c bind $j <1> "[code $this close $var]"
97 buildlayer [$var children] [expr $in+18]
102 $c lower [$c create line $in $start $in [expr $y+1] -fill $colors(line) ]
106 # add: add a list of varobj to the tree
107 itcl::body VarTree::add {var} {
109 if {$var == ""} {return}
110 set rootlist [concat $rootlist $var]
111 after idle [code $this build]
114 # remove: remove a varobj from the tree
115 # if the name is "all" then remove all
116 itcl::body VarTree::remove {name} {
118 if {$name == ""} {return}
119 if {$name == "all"} {
122 set rootlist [lremove $rootlist $name]
124 after idle [code $this build]
128 itcl::body VarTree::update_var {var enabled check} {
129 if {$enabled && $check} {return}
130 lassign $var_to_items($var) nam typ val
132 $c itemconfigure $nam -fill $colors(name)
133 $c itemconfigure $typ -fill $colors(type)
135 if {[catch {$var value} value]} {
136 set color $colors(error)
137 } elseif {[$c itemcget $val -text] != $value} {
138 set color $colors(change)
140 set color $colors(value)
142 $c itemconfigure $val -text $value -fill $color
144 $c itemconfigure $nam -fill $colors(disabled)
145 $c itemconfigure $typ -fill $colors(disabled)
146 $c itemconfigure $val -fill $colors(disabled)
149 if {![closed $var] && [$var numChildren]} {
150 foreach child [$var children] {
151 update_var $child $enabled $check
156 # update: update the values of the vars in the tree.
157 # The "check" argument is a hack we have to do because
158 # [$varobj value] does not return an error; only [$varobj update]
159 # does. So after changing the tree layout in build, we must then
160 # do an update. The "check" argument just optimizes things a bit over
161 # a normal update by not fetching values, just calling update.
162 itcl::body VarTree::update {{check 0}} {
165 # delete selection box if it is visible
170 # update all the root variables
171 foreach var $rootlist {
172 if {[$var update] == "-1"} {
177 update_var $var $enabled $check
181 # Draw the selection highlight
182 itcl::body VarTree::drawselection {} {
183 #debug "selidx=$selidx selection=$selection"
187 if {$selection == ""} return
188 if {![info exists var_to_items($selection)]} return
189 set bbox [eval "$c bbox $var_to_items($selection)"]
190 if {[llength $bbox] == 4} {
191 set selidx [eval $c create rectangle $bbox -fill $::Colors(sbg) -outline {{}}]
199 itcl::body VarTree::clicked {w x y open} {
200 #debug "clicked $w $x $y $open"
201 set x [$w canvasx $x]
202 set y [$w canvasy $y]
203 foreach m [$w find overlapping $x $y $x $y] {
204 if {[info exists item_to_var($m)]} {
206 set var $item_to_var($m)
212 after idle [code $this build]
214 setselection $item_to_var($m)
226 # Change the selection to the indicated item
228 itcl::body VarTree::setselection {var} {
229 #debug "setselection $var"
234 # Check if a node is closed.
235 # If it is a new node, set it to closed
236 itcl::body VarTree::closed {name} {
237 if {![info exists closed($name)]} {
240 return $closed($name)
244 itcl::body VarTree::open {name} {
246 after idle [code $this build]
250 itcl::body VarTree::close {name} {
252 after idle [code $this build]
256 # creates an entry widget in place of the current value
257 itcl::body VarTree::edit {j} {
260 # if another edit is in progress, cancel it
261 if {$entry != ""} { unedit $j }
263 set entryobj $item_to_var($j)
264 set entry [entry $c.entry -bg $::Colors(bg) -fg $::Colors(fg) -font global/fixed]
265 set entrywin [$c create window [$c coords $j] -window $entry -anchor w]
267 bind $entry <Return> [code $this changeValue $j]
268 bind $entry <Escape> [code $this unedit $j]
271 # cancel or clean up after an edit
272 itcl::body VarTree::unedit {j} {
281 # change the value of a varobj.
282 itcl::body VarTree::changeValue {j} {
283 #debug "value = [$entry get]"
284 set new [string trim [$entry get] \ \r\n]
289 if {[catch {$entryobj value $new} errTxt]} {
290 # gdbtk-varobj doesn't actually return meaningful error messages
291 # so use a generic one.
292 set errTxt "GDB could not evaluate that expression"
293 tk_messageBox -icon error -type ok -message $errTxt \
294 -title "Error in Expression" -parent [winfo toplevel $itk_interior]
296 $entry selection to end
300 # We may have changed a register or something else that is
301 # being displayed in another window
306 # change the format for a var
307 itcl::body VarTree::_change_format {var} {
308 #debug "$var $popup_temp"
309 catch {$var format $popup_temp}
310 after idle [code $this update]
313 # button 3 callback. Pops up a menu.
314 itcl::body VarTree::_but3 {x y X Y} {
315 set x [$c canvasx $x]
316 set y [$c canvasy $y]
317 catch {destroy $pop.format}
320 foreach item [$c find overlapping $x $y $x $y] {
321 if {![catch {set var $item_to_var($item)}]} {
327 _do_default_menu $X $Y
330 set popup_temp [$var format]
331 set j3 [lindex $var_to_items($var) 2]
332 #debug "var=$var [$var name] format=$popup_temp this=$this"
334 $pop add command -label [$var name] -state disabled
336 $pop add cascade -menu $pop.format -label "Format" -underline 0
337 set f [menu $pop.format -tearoff 0]
338 $f add radio -label "Natural" -variable [scope popup_temp] -value "natural" -command [code $this _change_format $var]
339 $f add radio -label "Decimal" -variable [scope popup_temp] -value "decimal" -command [code $this _change_format $var]
340 $f add radio -label "Hex" -variable [scope popup_temp] -value "hexadecimal" -command [code $this _change_format $var]
341 $f add radio -label "Octal" -variable [scope popup_temp] -value "octal" -command [code $this _change_format $var]
342 $f add radio -label "Binary" -variable [scope popup_temp] -value "binary" -command [code $this _change_format $var]
343 $pop add command -label "Edit" -command [code $this edit $j3]
344 $pop add command -label "Delete" -command [code $this remove $var]
345 if {![catch {$var value} value]} {
347 $pop add command -label "Dump Memory at [$var name]" -command [list ManagedWin::open MemWin -force -addr_exp [$var name]]
350 if {$type == "local"} {
351 $pop add command -label "Help" -command "open_help watch.html"
353 $pop add command -label "Help" -command "open_help locals.html"
356 $pop add command -label "Close" -command "destroy [winfo toplevel $itk_interior]"
360 # popup menu over empty space
361 itcl::body VarTree::_do_default_menu {X Y} {
364 if {$type == "local"} {
365 $pop add command -label "Local Variables" -state disabled
367 $pop add command -label "Watch Window" -state disabled
370 $pop add command -label "Sort" -command [code $this _sort]
371 if {$type == "local"} {
372 $pop add command -label "Help" -command "open_help watch.html"
374 $pop add command -label "Help" -command "open_help locals.html"
377 $pop add command -label "Close" -command "destroy [winfo toplevel $itk_interior]"
381 # alphabetize the variable names in the list
382 itcl::body VarTree::_sort {} {
384 set rootlist [lsort -command [code $this _compare] $rootlist]
385 after idle [code $this build]
388 # comparison function for lsort.
389 itcl::body VarTree::_compare {a b} {
390 return [string compare [$a name] [$b name]]
393 # ititialize common data
394 itcl::body VarTree::_init_data {} {
395 set colors(name) "\#0000C0"
396 set colors(type) "red"
397 set colors(error) "red"
398 set colors(value) "black"
399 set colors(change) $::Colors(change)
400 set colors(disabled) "gray50"
401 set colors(line) "gray50"
403 set maskdata "#define solid_width 9\n#define solid_height 9"
405 static unsigned char solid_bits[] = {
406 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
407 0xff, 0x01, 0xff, 0x01, 0xff, 0x01
410 set data "#define open_width 9\n#define open_height 9"
412 static unsigned char open_bits[] = {
413 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7d, 0x01, 0x01, 0x01,
414 0x01, 0x01, 0x01, 0x01, 0xff, 0x01
417 image create bitmap openbm -data $data -maskdata $maskdata \
418 -foreground black -background white
419 set data "#define closed_width 9\n#define closed_height 9"
421 static unsigned char closed_bits[] = {
422 0xff, 0x01, 0x01, 0x01, 0x11, 0x01, 0x11, 0x01, 0x7d, 0x01, 0x11, 0x01,
423 0x11, 0x01, 0x01, 0x01, 0xff, 0x01
426 image create bitmap closedbm -data $data -maskdata $maskdata \
427 -foreground black -background white