edge
TCL/TK UseCase2
Abstract : Contains all procedure for creating and maintaining an edge object.
Comments : The procedures in this file for getting and setting can easily be
converted to call propagation patterns.
###
# Bend node ovels...
###
proc calcOval { x y } {
set width 6
set left [expr $x - ($width / 2)]
set top [expr $y - ($width / 2)]
set right [expr $left + $width]
set bottom [expr $top + $width]
return "$left $top $right $bottom"
}
proc findListEntry { theList itemID } {
set index 0
foreach i $theList {
if {[lindex $i 0] == $itemID} {
return $index
}
incr index
}
return -1
}
###
# Set up an edge "data structure."
###
proc newEdge { name type srcVert dstVert {lblOff {0 -20}} {nodes {}}} {
global Edge iGraph inform changes
set Edge($name,Label) $name
set Edge($name,LabelOff) $lblOff
set Edge($name,srcVert) $srcVert
set Edge($name,dstVert) $dstVert
set Edge($name,nodeCoords) $nodes
set Edge($name,Type) $type
set Edge($name,cmdCreate) createEdge_$type
set Edge($name,cmdCreateLbl) createEdgeLabel_$type
# initialize the item IDs
set Edge($name,LabelID) -1
set Edge($name,LineIDs) {}
set Edge($name,OvalIDs) {}
puts $nodes
if {$nodes != ""} {
set formatted "{$nodes}"
} else {
set formatted ""
}
set changes yes
set formatted2 "{$lblOff}"
# call the C++ to initialize a new edge
if {$inform == 1} {
if {$type == "Constr"} {
puts "Sending: $name $srcVert $dstVert $formatted2"
# $formatted"
$iGraph cppCreCEdge: $name $srcVert $dstVert $formatted2
# $formatted
} else {
puts "Sending: $srcVert $dstVert"
# $formatted2 $formatted"
$iGraph cppCreAEdge: $srcVert $dstVert
# $formatted2 $formatted
}
}
appendVertexEdgeOut $srcVert $name
appendVertexEdgeIn $dstVert $name
}
###
# The following functions are used to set and obtain data
# relating to edge objects. If the need be, these functions
# could be used to call propogation patterns that would
# set or return the item requested.
###
proc getEdgeType { name } {
global Edge
return $Edge($name,Type)
}
proc setEdgeLabel { name lbl } {
global Edge
set Edge($name,Label) $lbl
}
proc getEdgeLabel { name } {
global Edge
return $Edge($name,Label)
}
# Sends label update to C++
proc setEdgeLabelOff { name offset } {
global Edge iGraph
set Edge($name,LabelOff) $offset
set formatted "{$offset}"
puts "Sending: $name [getEdgeSrcVert $name] [getEdgeDstVert $name]\
$formatted"
$iGraph cppUpdELabel: $name [getEdgeSrcVert $name] [getEdgeDstVert $name]\
$formatted
}
proc getEdgeLabelOff { name } {
global Edge
return $Edge($name,LabelOff)
}
proc getEdgeCreateCmd { name } {
global Edge
return $Edge($name,cmdCreate)
}
proc getEdgeCreateLblCmd { name } {
global Edge
return $Edge($name,cmdCreateLbl)
}
proc setEdgeSrcVert { name vert } {
global Edge
set Edge($name,srcVert) $vert
}
proc getEdgeSrcVert { name } {
global Edge
return $Edge($name,srcVert)
}
proc setEdgeDstVert { name vert } {
global Edge
set Edge($name,dstVert) $vert
}
proc getEdgeDstVert { name } {
global Edge
return $Edge($name,dstVert)
}
# Informs C++ of start/end node for an edge.
proc setEdgeNodeCoords { name coords } {
global Edge iGraph
set Edge($name,nodeCoords) $coords
set formatted "{$coords}"
if {[getEdgeType $name] == "Constr"} {
puts "Sending: $name [getEdgeSrcVert $name] \
[getEdgeDstVert $name] $formatted"
$iGraph cppUpdCEdge: $name [getEdgeSrcVert $name] \
[getEdgeDstVert $name] $formatted
} else {
puts "Sending: [getEdgeSrcVert $name] [getEdgeDstVert $name]\
$formatted"
$iGraph cppUpdAEdge: [getEdgeSrcVert $name] [getEdgeDstVert $name] $formatted
}
}
proc getEdgeNodeCoords { name } {
global Edge
return $Edge($name,nodeCoords)
}
proc setEdgeLabelID { name id } {
global Edge
set Edge($name,LabelID) $id
}
proc getEdgeLabelID { name } {
global Edge
return $Edge($name,LabelID)
}
proc setEdgeLineIDs { name ids } {
global Edge
set Edge($name,LineIDs) $ids
}
proc getEdgeLineIDs { name } {
global Edge
return $Edge($name,LineIDs)
}
proc setEdgeOvalIDs { name ids } {
global Edge
set Edge($name,OvalIDs) $ids
}
proc getEdgeOvalIDs { name } {
global Edge
return $Edge($name,OvalIDs)
}
proc clearEdgeIDs { name } {
global Edge
set Edge($name,LineIDs) {}
set Edge($name,OvalIDs) {}
}
###
#
###
proc deleteEdgeObjects { name } {
global Edge can
foreach i $Edge($name,LineIDs) {
for {set x 0} {$x < [llength $i]} {incr x 2} {
$can delete [lindex $i $x]
}
}
foreach i $Edge($name,OvalIDs) { $can delete [lindex $i 0] }
$can delete [getEdgeLabelID $name]
clearEdgeIDs $name
setEdgeLabelID $name -1
}
proc createEdge_Constr { name srcCoords dstCoords lst index {arrow 1} } {
global can
upvar $lst List
set itemID [$can create line \
[lindex $srcCoords 0] [lindex $srcCoords 1] \
[lindex $dstCoords 0] [lindex $dstCoords 1] \
-tags "$name"]
if {$arrow != 0} {
$can itemconfigure $itemID -arrow last
}
lappend List "$itemID $index"
$can raise $itemID
$can bind $itemID " onEdgeLineDbl $name %x %y "
return $itemID
}
###
# Calulate || lines for alternation edges.
###
proc calcAlterSlope { SourceX SourceY DestX DestY } {
set space 3
if {[expr ($DestX - $SourceX)] != 0} {
set slope [expr abs((($DestY - $SourceY) * 100) / ($DestX - $SourceX))]
if {[expr $slope] >= 100} {
set xspace $space
set yspace 0
} else {
set xspace 0
set yspace $space
}
} else {
set yspace 0
set xspace $space
}
return "$xspace $yspace"
}
proc createEdge_Alter { name srcCoords dstCoords lst index {arrow 1} } {
global can
upvar $lst List
set slope [calcAlterSlope [getXCoord $srcCoords] [getYCoord $srcCoords] \
[getXCoord $dstCoords] [getYCoord $dstCoords]]
set xspace [getXCoord $slope]
set yspace [getYCoord $slope]
set itemID [$can create line \
[expr [lindex $srcCoords 0] - $xspace ] \
[expr [lindex $srcCoords 1] - $yspace ] \
[expr [lindex $dstCoords 0] - $xspace ] \
[expr [lindex $dstCoords 1] - $yspace ] \
-tags "$name"]
if {$arrow != 0} {
$can itemconfigure $itemID -arrow last
}
set itemID2 [$can create line \
[expr [lindex $srcCoords 0] + $xspace ] \
[expr [lindex $srcCoords 1] + $yspace ] \
[expr [lindex $dstCoords 0] + $xspace ] \
[expr [lindex $dstCoords 1] + $yspace ] \
-tags "$name"]
if {$arrow != 0} {
$can itemconfigure $itemID2 -arrow last
}
lappend List "$itemID $index $itemID2 $index"
$can raise $itemID
$can raise $itemID2
$can bind $itemID " onEdgeLineDbl $name %x %y "
$can bind $itemID2 " onEdgeLineDbl $name %x %y "
return "$itemID $itemID2"
}
###
# Find midpoint between 2 nodes.
###
proc edgeCalcMidpoint { name } {
set srcVertName [getEdgeSrcVert $name]
set dstVertName [getEdgeDstVert $name]
set srcCoords [getVertexCoords $srcVertName]
set dstCoords [getVertexCoords $dstVertName]
# calculate midpoint
set srcCoords [getVertexCoords $srcVertName]
set dstCoords [getVertexCoords $dstVertName]
set midX [expr (([getXCoord $dstCoords] - [getXCoord $srcCoords]) / 2) + \
[getXCoord $srcCoords]]
set midY [expr (([getYCoord $dstCoords] - [getYCoord $srcCoords]) / 2) + \
[getYCoord $srcCoords]]
return "$midX $midY"
}
proc createEdgeLabel_Constr { name } {
global can
set srcVertName [getEdgeSrcVert $name]
set dstVertName [getEdgeDstVert $name]
set srcCoords [getVertexCoords $srcVertName]
set dstCoords [getVertexCoords $dstVertName]
# calculate midpoint
set srcCoords [getVertexCoords $srcVertName]
set dstCoords [getVertexCoords $dstVertName]
set midX [expr (([getXCoord $dstCoords] - [getXCoord $srcCoords]) / 2) + \
[getXCoord $srcCoords]]
set midY [expr (([getYCoord $dstCoords] - [getYCoord $srcCoords]) / 2) + \
[getYCoord $srcCoords]]
set labelX [expr $midX + [getXCoord [getEdgeLabelOff $name]]]
set labelY [expr $midY + [getYCoord [getEdgeLabelOff $name]]]
set labelName [getEdgeLabel $name]
set label [$can create text $labelX $labelY \
-text $labelName -tags "_label_ $name"]
$can bind $label " onEdgeLblMove $name %x %y "
setEdgeLabelID $name $label
}
proc createEdgeLabel_Alter { name } {
}
proc createEdge { name } {
global can
deleteEdgeObjects $name
set createEdgeCmd [getEdgeCreateCmd $name]
set srcVertName [getEdgeSrcVert $name]
set dstVertName [getEdgeDstVert $name]
set lnCoords [getEdgeNodeCoords $name]
set lnCoords [linsert $lnCoords 0 [getVertexCoords $srcVertName]]
lappend lnCoords [getVertexCoords $dstVertName]
set srcCoords [lindex $lnCoords 0]
set Lines {}
set Ovals {}
for {set index 1} { $index < [expr [llength $lnCoords] - 1]} {incr index} {
set dstCoords [lindex $lnCoords $index]
set itemID [$createEdgeCmd $name $srcCoords $dstCoords Lines $index]
# lappend Lines "$itemID $index"
set ovalCoords [calcOval [lindex $dstCoords 0] [lindex $dstCoords 1]]
set itemID [$can create oval \
[lindex $ovalCoords 0] [lindex $ovalCoords 1] \
[lindex $ovalCoords 2] [lindex $ovalCoords 3] \
-fill red]
lappend Ovals "$itemID $index"
$can raise $itemID
# $can bind $itemID { onOvalDown %x %y }
$can bind $itemID " onOvalMove $name %x %y "
$can bind $itemID " onEdgeOvalUp $name %x %y "
$can bind $itemID " onEdgeOvalDbl $name %x %y "
set srcCoords $dstCoords
}
set dstCoords [lindex $lnCoords $index]
set itemID [$createEdgeCmd $name $srcCoords $dstCoords Lines $index 0]
# lappend Lines "$itemID $index"
if {$index == 1} {
foreach i $itemID {
$can itemconfigure $i -arrow last
}
}
setEdgeLineIDs $name $Lines
setEdgeOvalIDs $name $Ovals
set cmdCreateLabel [getEdgeCreateLblCmd $name]
$cmdCreateLabel $name
$can bind $name " onEdgeEnter $name %x %y "
$can bind $name " onEdgeLeave $name %x %y "
$can bind $name " onEdgeUp $name %x %y "
}
proc getEdgeItemIndex { theList itemID } {
set index 0
foreach i $theList {
for {set x 0} {$x < [llength $i]} {incr x 2} {
if {[lindex $i $x] == $itemID} {
return $index
}
incr index
}
}
return -1
}