# plotpack.tcl -- # Implement a pack-like geometry manager for Plotchart # # Note: # The canvas:* procedures are taken directly from the Wiki, # these procedures were written by Maurice (ulis) Bredelet # I have not changed the formatting or the naming convention, # as a small token of my appreciation for his Tcl work # - he died in February 2008. # namespace eval ::Plotchart { variable packing } # GetCanvas -- # Destill the name of the canvas from the plot command # # Arguments: # cmd Plot command # # Result: # Name of the widget # proc ::Plotchart::GetCanvas {cmd} { regsub {^[^_]+_} $cmd "" w return $w } # plotpack -- # Copy an existing plot/chart into another canvas widget # # Arguments: # w Canvas widget to copy to # dir Direction to attach the new plot to the existing contents # args List of plots/charts to be copied # # Result: # None # proc ::Plotchart::plotpack {w dir args} { variable packing if { ![info exists packing($w,top)] } { set packing($w,top) 0 set packing($w,left) 0 set packing($w,right) [WidthCanvas $w] set packing($w,bottom) [HeightCanvas $w] } set top $packing($w,top) set left $packing($w,left) set right $packing($w,right) set bottom $packing($w,bottom) foreach p $args { set save [canvas:save [GetCanvas $p]] switch -- $dir { "top" { set xmove 0 set ymove $top canvas:restore $w $save $w move __NEW__ $xmove $ymove $w dtag all __NEW__ set cwidth [WidthCanvas [GetCanvas $p]] if { $left < $cwidth } { set left $cwidth } set top [expr {$top+[HeightCanvas [GetCanvas $p]]}] } "bottom" { set xmove 0 set ymove [expr {$bottom-[HeightCanvas [GetCanvas $p]]}] canvas:restore $w $save $w move __NEW__ $xmove $ymove $w dtag all __NEW__ set cwidth [WidthCanvas [GetCanvas $p]] if { $left < $cwidth } { set left $cwidth } set bottom $ymove } "left" { set xmove $left set ymove 0 canvas:restore $w $save $w move __NEW__ $xmove $ymove $w dtag all __NEW__ set left [expr {$left+[WidthCanvas [GetCanvas $p]]}] set cheight [HeightCanvas [GetCanvas $p]] if { $top < $cheight } { set top $cheight } } "right" { set xmove [expr {$right-[WidthCanvas [GetCanvas $p]]}] set ymove 0 canvas:restore $w $save $w move __NEW__ $xmove $ymove $w dtag all __NEW__ set right $xmove if { $top < $cheight } { set top $cheight } } } } set packing($w,top) $top set packing($w,left) $left set packing($w,right) $right set packing($w,bottom) $bottom } # canvas:* -- # Procedures for copying the contents of a canvas widget - by "ulis" # namespace eval ::Plotchart { # ============================== # # clone a canvas widget # # ============================== # ---------- # canvas:clone proc # ---------- # parm1: canvas widget # parm2: clone canvas widget # ---------- proc canvas:clone {canvas clone} { canvas:restore $clone [canvas:save $canvas] } # ---------- # options proc # # return non empty options # ---------- # parm: options list # ---------- # return: non empty options list # ---------- proc options {options} \ { set res {} foreach option $options \ { set key [lindex $option 0] set value [lindex $option 4] if {$value != ""} { lappend res [list $key $value] } } return $res } # ---------- # canvas:save proc # # serialize a canvas widget # ---------- # parm1: canvas widget path # ---------- # return: serialized widget # ---------- proc canvas:save {w} \ { # canvas name lappend save $w # canvas option lappend save [options [$w configure]] # canvas focus lappend save [$w focus] # canvas items foreach id [$w find all] \ { set item {} # type & id set type [$w type $id] lappend item [list $type $id] # coords lappend item [$w coords $id] # tags set tags [concat __NEW__ [$w gettags $id]] ;# AM: My change lappend item $tags # binds set binds {} # id binds set events [$w bind $id] foreach event $events \ { lappend binds [list $id $event [$w bind $id $event]] } # tags binds foreach tag $tags \ { set events [$w bind $tag] foreach event $events \ { lappend binds [list $tag $event [$w bind $tag $event]] } } lappend item $binds # options lappend item [options [$w itemconfigure $id]] # type specifics set specifics {} switch -- $type { arc {} bitmap {} image \ { # image name set iname [$w itemcget $id -image] lappend specifics $iname # image type lappend specifics [image type $iname] # image options lappend specifics [options [$iname configure]] } line {} oval {} polygon {} rectangle {} text \ { foreach index {insert sel.first sel.last} \ { # text indexes catch \ { lappend specifics [$w index $id $index] } } } window \ { # window name set wname [$w itemcget $id -window] lappend specifics $wname # window type lappend specifics [string tolower [winfo class $wname]] # window options lappend specifics [options [$wname configure]] } } lappend item $specifics lappend save $item } # return serialized canvas return $save } # ---------- # canvas:restore proc # # restore a serialized canvas widget # ---------- # parm1: canvas widget path # parm2: serialized widget to restore # ---------- proc canvas:restore {w save} \ { # create canvas options # eval canvas $w [join [lindex $save 1]] ;# AM: My change # items foreach item [lrange $save 3 end] \ { foreach {typeid coords tags binds options specifics} $item \ { # get type set type [lindex $typeid 0] # create bitmap or window switch -- $type { image \ { foreach {iname itype ioptions} $specifics break if {![image inuse $iname]} \ { eval image create $itype $iname [join $ioptions] } } window \ { foreach {wname wtype woptions} $specifics break if {![winfo exists $wname]} \ { eval $wtype $wname [join $woptions] } raise $wname } } # create item set id [eval $w create $type $coords [join $options]] $w itemconfigure $id -tags $tags ;# AM: "options" may contain the old list of tags # item bindings foreach bind $binds \ { foreach {id event script} $bind { $w bind $id $event $script } } # item specifics if {$specifics != ""} \ { switch -- $type { text \ { foreach {insert sel.first sel.last} $specifics break $w icursor $id $insert if {${sel.first} != ""} \ { $w select from $id ${sel.first} $w select to $id ${sel.last} } } } } } } # focused item set focus [lindex $save 2] if {$focus != ""} \ { $w focus [lindex $save 2] focus -force $w } # return path return $w } # ---------- # canvas:dump proc # # dump a canvas widget # ---------- # parm: canvas widget path # ---------- # return: widget dump # ---------- proc canvas:dump {w} \ { # canvas name lappend res [lindex $w 0] # canvas options foreach option [lindex $w 1] { lappend res [join $option \t] } # focused item lappend res [join [lindex $w 2] \t] # items foreach item [lrange $w 3 end] \ { foreach {type coords tags binds options specifics} $item \ { # item type lappend res [join $type \t] # item coords lappend res \tcoords\t$coords # item tags lappend res \ttags\t$tags # item bindings lappend res \tbinds foreach bind $binds { lappend res \t\t$bind } # item options lappend res \toptions foreach option $options \ { set key [lindex $option 0] set value [lindex $option 1] lappend res \t\t$key\t$value } # item specifics if {$specifics != ""} \ { lappend res \tspecifics foreach specific $specifics \ { if {[llength $specific] == 1} { lappend res \t\t$specific } \ else { foreach token $specific { lappend res \t\t$token } } } } } } # return dump return [join $res \n] } }