843 lines
25 KiB
Tcl
843 lines
25 KiB
Tcl
|
#
|
||
|
# Copyright 2007-2013 the Boeing Company.
|
||
|
# See the LICENSE file included in this distribution.
|
||
|
#
|
||
|
|
||
|
#
|
||
|
# Copyright 2007-2008 University of Zagreb, Croatia.
|
||
|
#
|
||
|
# Redistribution and use in source and binary forms, with or without
|
||
|
# modification, are permitted provided that the following conditions
|
||
|
# are met:
|
||
|
# 1. Redistributions of source code must retain the above copyright
|
||
|
# notice, this list of conditions and the following disclaimer.
|
||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||
|
# notice, this list of conditions and the following disclaimer in the
|
||
|
# documentation and/or other materials provided with the distribution.
|
||
|
#
|
||
|
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
# SUCH DAMAGE.
|
||
|
#
|
||
|
|
||
|
#****h* imunes/annotations.tcl
|
||
|
# NAME
|
||
|
# annotations.tcl -- oval, rectangle, text, background, ...
|
||
|
# FUNCTION
|
||
|
# This module is used for configuration/image annotations, such as oval,
|
||
|
# rectangle, text, background or some other.
|
||
|
#****
|
||
|
|
||
|
#****f* annotations.tcl/annotationConfig
|
||
|
# NAME
|
||
|
# annotationConfig --
|
||
|
# SYNOPSIS
|
||
|
# annotationConfig $canvas $target
|
||
|
# FUNCTION
|
||
|
# . . .
|
||
|
# INPUTS
|
||
|
# * canvas --
|
||
|
# * target -- oval or rectangle object
|
||
|
#****
|
||
|
|
||
|
proc annotationConfig { c target } {
|
||
|
switch -exact -- [nodeType $target] {
|
||
|
oval {
|
||
|
popupAnnotationDialog $c $target "true"
|
||
|
}
|
||
|
rectangle {
|
||
|
popupAnnotationDialog $c $target "true"
|
||
|
}
|
||
|
text {
|
||
|
popupAnnotationDialog $c $target "true"
|
||
|
}
|
||
|
default {
|
||
|
puts "Unknown type [nodeType $target] for target $target"
|
||
|
}
|
||
|
}
|
||
|
redrawAll
|
||
|
}
|
||
|
|
||
|
|
||
|
#****f* annotations.tcl/popupOvalDialog
|
||
|
# NAME
|
||
|
# popupOvalDialog -- creates a new oval or modifies existing oval
|
||
|
# SYNOPSIS
|
||
|
# popupOvalDialog $canvas $modify $color $label $lcolor
|
||
|
# FUNCTION
|
||
|
# Called from:
|
||
|
# - editor.tcl/button1-release when new oval is drawn
|
||
|
# - annotationConfig which is called from popupConfigDialog bound to
|
||
|
# Double-1 on various objects
|
||
|
# - configureOval called from button3annotation procedure which creates
|
||
|
# a menu for configuration and deletion (bound to 3 on oval,
|
||
|
# rectangle and text)
|
||
|
# INPUTS
|
||
|
# * canvas --
|
||
|
# * modify -- create new oval "newoval" if modify=false or
|
||
|
# modify an existing oval "newoval" if modify=true
|
||
|
# * color -- oval color
|
||
|
# * label -- label text
|
||
|
# * lcolor -- label (text) color
|
||
|
#****
|
||
|
|
||
|
|
||
|
#****f* annotations.tcl/destroyNewoval
|
||
|
# NAME
|
||
|
# destroyNewoval -- helper for popupOvalDialog and popupOvalApply
|
||
|
# SYNOPSIS
|
||
|
# destroyNewoval $canvas
|
||
|
# FUNCTION
|
||
|
# . . .
|
||
|
# INPUTS
|
||
|
# * canvas --
|
||
|
#****
|
||
|
|
||
|
proc destroyNewoval { c } {
|
||
|
global newoval
|
||
|
$c delete -withtags newoval
|
||
|
set newoval ""
|
||
|
}
|
||
|
|
||
|
|
||
|
# oval/rectangle/text right-click menu
|
||
|
|
||
|
proc button3annotation { type c x y } {
|
||
|
|
||
|
if { $type == "oval" } {
|
||
|
set procname "Oval"
|
||
|
set item [lindex [$c gettags {oval && current}] 1]
|
||
|
} elseif { $type == "rectangle" } {
|
||
|
set procname "Rectangle"
|
||
|
set item [lindex [$c gettags {rectangle && current}] 1]
|
||
|
} elseif { $type == "label" } {
|
||
|
set procname "Label"
|
||
|
set item [lindex [$c gettags {label && current}] 1]
|
||
|
} elseif { $type == "text" } {
|
||
|
set procname "Text"
|
||
|
set item [lindex [$c gettags {text && current}] 1]
|
||
|
} elseif { $type == "marker" } {
|
||
|
# erase markings
|
||
|
$c delete -withtags {marker && current}
|
||
|
return
|
||
|
} else {
|
||
|
# ???
|
||
|
return
|
||
|
}
|
||
|
if { $item == "" } {
|
||
|
return
|
||
|
}
|
||
|
set menutext "$type $item"
|
||
|
|
||
|
.button3menu delete 0 end
|
||
|
|
||
|
.button3menu add command -label "Configure $menutext" \
|
||
|
-command "annotationConfig $c $item"
|
||
|
.button3menu add command -label "Delete $menutext" \
|
||
|
-command "deleteAnnotation $c $type $item"
|
||
|
|
||
|
set x [winfo pointerx .]
|
||
|
set y [winfo pointery .]
|
||
|
tk_popup .button3menu $x $y
|
||
|
}
|
||
|
|
||
|
|
||
|
proc deleteAnnotation { c type target } {
|
||
|
global changed annotation_list
|
||
|
|
||
|
$c delete -withtags "$type && $target"
|
||
|
$c delete -withtags "new$type"
|
||
|
set i [lsearch -exact $annotation_list $target]
|
||
|
set annotation_list [lreplace $annotation_list $i $i]
|
||
|
set changed 1
|
||
|
updateUndoLog
|
||
|
}
|
||
|
|
||
|
|
||
|
proc drawOval {oval} {
|
||
|
global $oval defOvalColor zoom curcanvas
|
||
|
global defTextFontFamily defTextFontSize
|
||
|
|
||
|
set coords [getNodeCoords $oval]
|
||
|
if { [llength $coords] < 4 } {
|
||
|
puts "Bad coordinates for oval $oval"
|
||
|
return
|
||
|
}
|
||
|
set x1 [expr {[lindex $coords 0] * $zoom}]
|
||
|
set y1 [expr {[lindex $coords 1] * $zoom}]
|
||
|
set x2 [expr {[lindex $coords 2] * $zoom}]
|
||
|
set y2 [expr {[lindex $coords 3] * $zoom}]
|
||
|
set color [lindex [lsearch -inline [set $oval] "color *"] 1]
|
||
|
set label [lindex [lsearch -inline [set $oval] "label *"] 1]
|
||
|
set lcolor [lindex [lsearch -inline [set $oval] "labelcolor *"] 1]
|
||
|
set bordercolor [lindex [lsearch -inline [set $oval] "border *"] 1]
|
||
|
set width [lindex [lsearch -inline [set $oval] "width *"] 1]
|
||
|
set lx [expr $x1 + (($x2 - $x1) / 2)]
|
||
|
set ly [expr ($y1 + 20)]
|
||
|
|
||
|
if { $color == "" } { set color $defOvalColor }
|
||
|
if { $lcolor == "" } { set lcolor black }
|
||
|
if { $width == "" } { set width 0 }
|
||
|
if { $bordercolor == "" } { set bordercolor black }
|
||
|
|
||
|
# -outline red -stipple gray50
|
||
|
set newoval [.c create oval $x1 $y1 $x2 $y2 \
|
||
|
-fill $color -width $width -outline $bordercolor \
|
||
|
-tags "oval $oval annotation"]
|
||
|
.c raise $newoval background
|
||
|
|
||
|
set fontfamily [lindex [lsearch -inline [set $oval] "fontfamily *"] 1]
|
||
|
set fontsize [lindex [lsearch -inline [set $oval] "fontsize *"] 1]
|
||
|
if { $fontfamily == "" } {
|
||
|
set fontfamily $defTextFontFamily
|
||
|
}
|
||
|
if { $fontsize == "" } {
|
||
|
set fontsize $defTextFontSize
|
||
|
}
|
||
|
set newfontsize $fontsize
|
||
|
set font [list "$fontfamily" $fontsize]
|
||
|
set effects [lindex [lsearch -inline [set $oval] "effects *"] 1]
|
||
|
|
||
|
.c create text $lx $ly -tags "oval $oval annotation" -text $label \
|
||
|
-justify center -font "$font $effects" -fill $lcolor
|
||
|
|
||
|
setNodeCanvas $oval $curcanvas
|
||
|
setType $oval "oval"
|
||
|
}
|
||
|
|
||
|
|
||
|
# Color helper for popupOvalDialog and popupLabelDialog
|
||
|
proc popupColor { type l settext } {
|
||
|
# popup color selection dialog with current color
|
||
|
if { $type == "fg" } {
|
||
|
set initcolor [$l cget -fg]
|
||
|
} else {
|
||
|
set initcolor [$l cget -bg]
|
||
|
}
|
||
|
set newcolor [tk_chooseColor -initialcolor $initcolor]
|
||
|
|
||
|
# set fg or bg of the "l" label control
|
||
|
if { $newcolor == "" } {
|
||
|
return
|
||
|
}
|
||
|
if { $settext == "true" } {
|
||
|
$l configure -text $newcolor -$type $newcolor
|
||
|
} else {
|
||
|
$l configure -$type $newcolor
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#****f* annotations.tcl/roundRect
|
||
|
# NAME
|
||
|
# roundRect -- Draw a rounded rectangle in the canvas.
|
||
|
# Called from drawRect procedure
|
||
|
# SYNOPSIS
|
||
|
# roundRect $w $x0 $y0 $x3 $y3 $radius $args
|
||
|
# FUNCTION
|
||
|
# Creates a rounded rectangle as a smooth polygon in the canvas
|
||
|
# and returns the canvas item number of the rounded rectangle.
|
||
|
# INPUTS
|
||
|
# * w -- Path name of the canvas
|
||
|
# * x0, y0 -- Coordinates of the upper left corner, in pixels
|
||
|
# * x3, y3 -- Coordinates of the lower right corner, in pixels
|
||
|
# * radius -- Radius of the bend at the corners, in any form
|
||
|
# acceptable to Tk_GetPixels
|
||
|
# * args -- Other args suitable to a 'polygon' item on the canvas
|
||
|
# Example:
|
||
|
# roundRect .c 100 50 500 250 $rad -fill white -outline black -tags rectangle
|
||
|
#****
|
||
|
|
||
|
proc roundRect { w x0 y0 x3 y3 radius args } {
|
||
|
|
||
|
set r [winfo pixels $w $radius]
|
||
|
set d [expr { 2 * $r }]
|
||
|
|
||
|
# Make sure that the radius of the curve is less than 3/8 size of the box
|
||
|
|
||
|
set maxr 0.75
|
||
|
|
||
|
if { $d > $maxr * ( $x3 - $x0 ) } {
|
||
|
set d [expr { $maxr * ( $x3 - $x0 ) }]
|
||
|
}
|
||
|
if { $d > $maxr * ( $y3 - $y0 ) } {
|
||
|
set d [expr { $maxr * ( $y3 - $y0 ) }]
|
||
|
}
|
||
|
|
||
|
set x1 [expr { $x0 + $d }]
|
||
|
set x2 [expr { $x3 - $d }]
|
||
|
set y1 [expr { $y0 + $d }]
|
||
|
set y2 [expr { $y3 - $d }]
|
||
|
|
||
|
set cmd [list $w create polygon]
|
||
|
lappend cmd $x0 $y0 $x1 $y0 $x2 $y0 $x3 $y0 $x3 $y1 $x3 $y2
|
||
|
lappend cmd $x3 $y3 $x2 $y3 $x1 $y3 $x0 $y3 $x0 $y2 $x0 $y1
|
||
|
lappend cmd -smooth 1
|
||
|
return [eval $cmd $args]
|
||
|
}
|
||
|
|
||
|
proc drawRect {rectangle} {
|
||
|
global $rectangle defRectColor zoom curcanvas
|
||
|
global defTextFontFamily defTextFontSize
|
||
|
|
||
|
set coords [getNodeCoords $rectangle]
|
||
|
if {$coords == "" || [llength $coords] != 4 } {
|
||
|
puts "Bad coordinates for rectangle $rectangle"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
set x1 [expr {[lindex $coords 0] * $zoom}]
|
||
|
set y1 [expr {[lindex $coords 1] * $zoom}]
|
||
|
set x2 [expr {[lindex $coords 2] * $zoom}]
|
||
|
set y2 [expr {[lindex $coords 3] * $zoom}]
|
||
|
set color [lindex [lsearch -inline [set $rectangle] "color *"] 1]
|
||
|
set label [lindex [lsearch -inline [set $rectangle] "label *"] 1]
|
||
|
set lcolor [lindex [lsearch -inline [set $rectangle] "labelcolor *"] 1]
|
||
|
set bordercolor [lindex [lsearch -inline [set $rectangle] "border *"] 1]
|
||
|
set width [lindex [lsearch -inline [set $rectangle] "width *"] 1]
|
||
|
set rad [lindex [lsearch -inline [set $rectangle] "rad *"] 1]
|
||
|
set lx [expr $x1 + (($x2 - $x1) / 2)]
|
||
|
set ly [expr ($y1 + 20)]
|
||
|
|
||
|
if { $color == "" } { set color $defRectColor }
|
||
|
if { $lcolor == "" } { set lcolor black }
|
||
|
if { $bordercolor == "" } { set bordercolor black }
|
||
|
if { $width == "" } { set width 0 }
|
||
|
# rounded-rectangle radius
|
||
|
if { $rad == "" } { set rad 25 }
|
||
|
|
||
|
# Boeing: allow borderless rectangles
|
||
|
if { $width == 0 } {
|
||
|
set newrect [roundRect .c $x1 $y1 $x2 $y2 $rad \
|
||
|
-fill $color -tags "rectangle $rectangle annotation"]
|
||
|
} else {
|
||
|
# end Boeing
|
||
|
set newrect [roundRect .c $x1 $y1 $x2 $y2 $rad \
|
||
|
-fill $color -outline $bordercolor -width $width \
|
||
|
-tags "rectangle $rectangle annotation"]
|
||
|
.c raise $newrect background
|
||
|
# Boeing
|
||
|
}
|
||
|
# end Boeing
|
||
|
|
||
|
set fontfamily [lindex [lsearch -inline [set $rectangle] "fontfamily *"] 1]
|
||
|
set fontsize [lindex [lsearch -inline [set $rectangle] "fontsize *"] 1]
|
||
|
if { $fontfamily == "" } {
|
||
|
set fontfamily $defTextFontFamily
|
||
|
}
|
||
|
if { $fontsize == "" } {
|
||
|
set fontsize $defTextFontSize
|
||
|
}
|
||
|
set newfontsize $fontsize
|
||
|
set font [list "$fontfamily" $fontsize]
|
||
|
set effects [lindex [lsearch -inline [set $rectangle] "effects *"] 1]
|
||
|
|
||
|
.c create text $lx $ly -tags "rectangle $rectangle annotation" \
|
||
|
-text $label -justify center -font "$font $effects" -fill $lcolor
|
||
|
|
||
|
setNodeCanvas $rectangle $curcanvas
|
||
|
setType $rectangle "rectangle"
|
||
|
}
|
||
|
|
||
|
|
||
|
proc popupAnnotationDialog { c target modify } {
|
||
|
global $target newrect newoval
|
||
|
global width rad fontfamily fontsize
|
||
|
global defFillColor defTextColor defTextFontFamily defTextFontSize
|
||
|
|
||
|
# do nothing, return, if coords are empty
|
||
|
if { $target == 0 \
|
||
|
&& [$c coords "$newrect"] == "" \
|
||
|
&& [$c coords "$newoval"] == "" } {
|
||
|
return
|
||
|
}
|
||
|
if { $target == 0 } {
|
||
|
set width 0
|
||
|
set rad 25
|
||
|
set coords [$c bbox "$newrect"]
|
||
|
if { [$c coords "$newrect"] == "" } {
|
||
|
set coords [$c bbox "$newoval"]
|
||
|
set annotationType "oval"
|
||
|
} else {
|
||
|
set annotationType "rectangle"
|
||
|
}
|
||
|
set fontfamily ""
|
||
|
set fontsize ""
|
||
|
set effects ""
|
||
|
set color ""
|
||
|
set label ""
|
||
|
set lcolor ""
|
||
|
set bordercolor ""
|
||
|
} else {
|
||
|
set width [lindex [lsearch -inline [set $target] "width *"] 1]
|
||
|
set rad [lindex [lsearch -inline [set $target] "rad *"] 1]
|
||
|
set coords [$c bbox "$target"]
|
||
|
set color [lindex [lsearch -inline [set $target] "color *"] 1]
|
||
|
set fontfamily [lindex [lsearch -inline [set $target] "fontfamily *"] 1]
|
||
|
set fontsize [lindex [lsearch -inline [set $target] "fontsize *"] 1]
|
||
|
set effects [lindex [lsearch -inline [set $target] "effects *"] 1]
|
||
|
|
||
|
set label [lindex [lsearch -inline [set $target] "label *"] 1]
|
||
|
set lcolor [lindex [lsearch -inline [set $target] "labelcolor *"] 1]
|
||
|
set bordercolor [lindex [lsearch -inline [set $target] "border *"] 1]
|
||
|
set annotationType [nodeType $target]
|
||
|
}
|
||
|
|
||
|
if { $color == "" } {
|
||
|
# Boeing: use default shape colors
|
||
|
if { $annotationType == "oval" } {
|
||
|
global defOvalColor
|
||
|
set color $defOvalColor
|
||
|
} elseif { $annotationType == "rectangle" } {
|
||
|
global defRectColor
|
||
|
set color $defRectColor
|
||
|
} else {
|
||
|
set color $defFillColor
|
||
|
}
|
||
|
}
|
||
|
if { $lcolor == "" } { set lcolor black }
|
||
|
if { $bordercolor == "" } { set bordercolor black }
|
||
|
if { $width == "" } { set width 0 }
|
||
|
if { $rad == "" } { set rad 25 }
|
||
|
if { $fontfamily == "" } { set fontfamily $defTextFontFamily }
|
||
|
if { $fontsize == "" } { set fontsize $defTextFontSize }
|
||
|
|
||
|
set textBold 0
|
||
|
set textItalic 0
|
||
|
set textUnderline 0
|
||
|
if { [lsearch $effects bold ] != -1} {set textBold 1}
|
||
|
if { [lsearch $effects italic ] != -1} {set textItalic 1}
|
||
|
if { [lsearch $effects underline ] != -1} {set textUnderline 1}
|
||
|
|
||
|
set x1 [lindex $coords 0]
|
||
|
set y1 [lindex $coords 1]
|
||
|
set x2 [lindex $coords 2]
|
||
|
set y2 [lindex $coords 3]
|
||
|
set xx [expr {abs($x2 - $x1)}]
|
||
|
set yy [expr {abs($y2 - $y1)}]
|
||
|
if { $xx > $yy } {
|
||
|
set maxrad [expr $yy * 3.0 / 8.0]
|
||
|
} else {
|
||
|
set maxrad [expr $xx * 3.0 / 8.0]
|
||
|
}
|
||
|
|
||
|
set wi .popup
|
||
|
catch {destroy $wi}
|
||
|
toplevel $wi
|
||
|
|
||
|
wm transient $wi .
|
||
|
wm resizable $wi 0 0
|
||
|
|
||
|
if { $modify == "true" } {
|
||
|
set windowtitle "Configure $annotationType $target"
|
||
|
} else {
|
||
|
set windowtitle "Add a new $annotationType"
|
||
|
}
|
||
|
wm title $wi $windowtitle
|
||
|
|
||
|
frame $wi.text -relief groove -bd 2
|
||
|
frame $wi.text.lab
|
||
|
label $wi.text.lab.name_label -text "Text for top of $annotationType:"
|
||
|
entry $wi.text.lab.name -bg white -fg $lcolor -width 32 \
|
||
|
-validate focus -invcmd "focusAndFlash %W"
|
||
|
$wi.text.lab.name insert 0 $label
|
||
|
pack $wi.text.lab.name_label $wi.text.lab.name -side left -anchor w \
|
||
|
-padx 2 -pady 2 -fill x
|
||
|
pack $wi.text.lab -side top -fill x
|
||
|
|
||
|
frame $wi.text.format
|
||
|
|
||
|
set fontmenu [tk_optionMenu $wi.text.format.fontmenu fontfamily "$fontfamily"]
|
||
|
set sizemenu [tk_optionMenu $wi.text.format.fontsize fontsize "$fontsize"]
|
||
|
|
||
|
|
||
|
# color selection
|
||
|
if { $color == "" } {
|
||
|
set color $defTextColor
|
||
|
}
|
||
|
button $wi.text.format.fg -text "Text color" -command \
|
||
|
"popupColor fg $wi.text.lab.name false"
|
||
|
checkbutton $wi.text.format.bold -text "Bold" -variable textBold \
|
||
|
-command [list fontupdate $wi.text.lab.name bold]
|
||
|
checkbutton $wi.text.format.italic -text "Italic" -variable textItalic \
|
||
|
-command [list fontupdate $wi.text.lab.name italic]
|
||
|
checkbutton $wi.text.format.underline -text "Underline" \
|
||
|
-variable textUnderline \
|
||
|
-command [list fontupdate $wi.text.lab.name underline]
|
||
|
|
||
|
if {$textBold == 1} { $wi.text.format.bold select
|
||
|
} else { $wi.text.format.bold deselect }
|
||
|
if {$textItalic == 1} { $wi.text.format.italic select
|
||
|
} else { $wi.text.format.italic deselect }
|
||
|
if {$textUnderline == 1} { $wi.text.format.underline select
|
||
|
} else { $wi.text.format.underline deselect }
|
||
|
|
||
|
pack $wi.text.format.fontmenu \
|
||
|
$wi.text.format.fontsize \
|
||
|
$wi.text.format.fg \
|
||
|
$wi.text.format.bold \
|
||
|
$wi.text.format.italic \
|
||
|
$wi.text.format.underline \
|
||
|
-side left -pady 2
|
||
|
|
||
|
pack $wi.text.format -side top -fill x
|
||
|
|
||
|
pack $wi.text -side top -fill x
|
||
|
|
||
|
fontupdate $wi.text.lab.name fontfamily $fontfamily
|
||
|
fontupdate $wi.text.lab.name fontsize $fontsize
|
||
|
|
||
|
$fontmenu delete 0
|
||
|
foreach f [lsort -dictionary [font families]] {
|
||
|
$fontmenu add radiobutton -value "$f" -label $f \
|
||
|
-variable fontfamily \
|
||
|
-command [list fontupdate $wi.text.lab.name fontfamily $f]
|
||
|
}
|
||
|
|
||
|
$sizemenu delete 0
|
||
|
foreach f {8 9 10 11 12 14 16 18 20 22 24 26 28 36 48 72} {
|
||
|
$sizemenu add radiobutton -value "$f" -label $f \
|
||
|
-variable fontsize \
|
||
|
-command [list fontupdate $wi.text.lab.name fontsize $f]
|
||
|
}
|
||
|
|
||
|
if { "$annotationType" == "rectangle" || "$annotationType" == "oval" } {
|
||
|
|
||
|
# fill color, border color
|
||
|
frame $wi.colors -relief groove -bd 2
|
||
|
# color selection controls
|
||
|
label $wi.colors.label -text "Fill color:"
|
||
|
|
||
|
label $wi.colors.color -text $color -width 8 \
|
||
|
-bg $color -fg $lcolor
|
||
|
button $wi.colors.bg -text "Color" -command \
|
||
|
"popupColor bg $wi.colors.color true"
|
||
|
pack $wi.colors.label $wi.colors.color $wi.colors.bg \
|
||
|
-side left -padx 2 -pady 2 -anchor w -fill x
|
||
|
pack $wi.colors -side top -fill x
|
||
|
|
||
|
# border selection controls
|
||
|
frame $wi.border -relief groove -bd 2
|
||
|
label $wi.border.label -text "Border color:"
|
||
|
label $wi.border.color -text $bordercolor -width 8 \
|
||
|
-bg $color -fg $bordercolor
|
||
|
label $wi.border.width_label -text "Border width:"
|
||
|
set widthMenu [tk_optionMenu $wi.border.width width "$width"]
|
||
|
$widthMenu delete 0
|
||
|
foreach f {0 1 2 3 4 5 6 7 8 9 10} {
|
||
|
$widthMenu add radiobutton -value $f -label $f \
|
||
|
-variable width
|
||
|
}
|
||
|
button $wi.border.fg -text "Color" -command \
|
||
|
"popupColor fg $wi.border.color true"
|
||
|
pack $wi.border.label $wi.border.color $wi.border.fg \
|
||
|
$wi.border.width_label $wi.border.width \
|
||
|
$wi.border.fg $wi.border.color $wi.border.label \
|
||
|
-side left -padx 2 -pady 2 -anchor w -fill x
|
||
|
pack $wi.border -side top -fill x
|
||
|
|
||
|
}
|
||
|
|
||
|
if { $annotationType == "rectangle" } {
|
||
|
frame $wi.radius -relief groove -bd 2
|
||
|
scale $wi.radius.rad -from 0 -to [expr int($maxrad)] \
|
||
|
-length 400 -variable rad \
|
||
|
-orient horizontal -label "Radius of the bend at the corners: " \
|
||
|
-tickinterval [expr int($maxrad / 15) + 1] -showvalue true
|
||
|
pack $wi.radius.rad -side left -padx 2 -pady 2 -anchor w -fill x
|
||
|
pack $wi.radius -side top -fill x
|
||
|
}
|
||
|
|
||
|
# Add new oval or modify old one?
|
||
|
if { $modify == "true" } {
|
||
|
set cancelcmd "destroy $wi"
|
||
|
set applytext "Modify $annotationType"
|
||
|
} else {
|
||
|
set cancelcmd "destroy $wi; destroyNewRect $c"
|
||
|
set applytext "Add $annotationType"
|
||
|
}
|
||
|
|
||
|
frame $wi.butt -borderwidth 6
|
||
|
button $wi.butt.apply -text $applytext -command "popupAnnotationApply $c $wi $target $annotationType"
|
||
|
|
||
|
button $wi.butt.cancel -text "Cancel" -command $cancelcmd
|
||
|
bind $wi <Key-Escape> "$cancelcmd"
|
||
|
bind $wi <Key-Return> "popupAnnotationApply $c $wi $target $annotationType"
|
||
|
pack $wi.butt.cancel $wi.butt.apply -side right
|
||
|
pack $wi.butt -side bottom
|
||
|
|
||
|
after 100 {
|
||
|
grab .popup
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# helper for popupOvalDialog and popupOvalApply
|
||
|
proc destroyNewRect { c } {
|
||
|
global newrect
|
||
|
$c delete -withtags newrect
|
||
|
set newrect ""
|
||
|
}
|
||
|
|
||
|
|
||
|
proc popupAnnotationApply { c wi target type } {
|
||
|
global newrect newoval annotation_list
|
||
|
global $target
|
||
|
global changed
|
||
|
global width rad
|
||
|
global fontfamily fontsize textBold textItalic textUnderline
|
||
|
|
||
|
# attributes
|
||
|
set caption [string trim [$wi.text.lab.name get]]
|
||
|
set labelcolor [$wi.text.lab.name cget -fg]
|
||
|
set coords [$c coords "$target"]
|
||
|
set iconcoords "iconcoords"
|
||
|
|
||
|
if {"$type" == "rectangle" || "$type" == "oval" } {
|
||
|
set color [$wi.colors.color cget -text]
|
||
|
set bordercolor [$wi.border.color cget -text]
|
||
|
}
|
||
|
|
||
|
if { $target == 0 } {
|
||
|
# Create a new annotation object
|
||
|
set target [newObjectId annotation]
|
||
|
global $target
|
||
|
lappend annotation_list $target
|
||
|
if {"$type" == "rectangle" } {
|
||
|
set coords [$c coords $newrect]
|
||
|
} elseif { "$type" == "oval" } {
|
||
|
set coords [$c coords $newoval]
|
||
|
}
|
||
|
} else {
|
||
|
set coords [getNodeCoords $target]
|
||
|
}
|
||
|
set $target {}
|
||
|
lappend $iconcoords $coords
|
||
|
lappend $target $iconcoords "label {$caption}" "labelcolor $labelcolor" \
|
||
|
"fontfamily {$fontfamily}" "fontsize $fontsize"
|
||
|
if {"$type" == "rectangle" || "$type" == "oval" } {
|
||
|
lappend $target "color $color" "width $width" "border $bordercolor"
|
||
|
}
|
||
|
if {"$type" == "rectangle" } {
|
||
|
lappend $target "rad $rad"
|
||
|
}
|
||
|
|
||
|
set ef {}
|
||
|
if {"$textBold" == 1} { lappend ef bold}
|
||
|
if {"$textItalic" == 1} { lappend ef italic}
|
||
|
if {"$textUnderline" == 1} { lappend ef underline}
|
||
|
if {"$ef" != ""} { lappend $target "effects {$ef}"}
|
||
|
|
||
|
# draw it
|
||
|
if { $type == "rectangle" } {
|
||
|
drawRect $target
|
||
|
destroyNewRect $c
|
||
|
} elseif { $type == "oval" } {
|
||
|
drawOval $target
|
||
|
destroyNewoval $c
|
||
|
} elseif { $type == "text" } {
|
||
|
drawText $target
|
||
|
}
|
||
|
|
||
|
set changed 1
|
||
|
updateUndoLog
|
||
|
redrawAll
|
||
|
destroy $wi
|
||
|
}
|
||
|
|
||
|
proc selectmarkEnter {c x y} {
|
||
|
set isThruplot false
|
||
|
|
||
|
if {$c == ".c"} {
|
||
|
set obj [lindex [$c gettags current] 1]
|
||
|
set type [nodeType $obj]
|
||
|
if {$type != "oval" && $type != "rectangle"} { return }
|
||
|
} else {
|
||
|
set obj $c
|
||
|
set c .c
|
||
|
set isThruplot true
|
||
|
}
|
||
|
set bbox [$c bbox $obj]
|
||
|
|
||
|
set x1 [lindex $bbox 0]
|
||
|
set y1 [lindex $bbox 1]
|
||
|
set x2 [lindex $bbox 2]
|
||
|
set y2 [lindex $bbox 3]
|
||
|
|
||
|
if {$isThruplot == true} {
|
||
|
set x [expr $x+$x1]
|
||
|
set y [expr $y+$y1]
|
||
|
|
||
|
}
|
||
|
set l 0 ;# left
|
||
|
set r 0 ;# right
|
||
|
set u 0 ;# up
|
||
|
set d 0 ;# down
|
||
|
|
||
|
set x [$c canvasx $x]
|
||
|
set y [$c canvasy $y]
|
||
|
|
||
|
if { $x < [expr $x1+($x2-$x1)/8.0]} { set l 1 }
|
||
|
if { $x > [expr $x2-($x2-$x1)/8.0]} { set r 1 }
|
||
|
if { $y < [expr $y1+($y2-$y1)/8.0]} { set u 1 }
|
||
|
if { $y > [expr $y2-($y2-$y1)/8.0]} { set d 1 }
|
||
|
|
||
|
if {$l==1} {
|
||
|
if {$u==1} {
|
||
|
$c config -cursor top_left_corner
|
||
|
} elseif {$d==1} {
|
||
|
$c config -cursor bottom_left_corner
|
||
|
} else {
|
||
|
$c config -cursor left_side
|
||
|
}
|
||
|
} elseif {$r==1} {
|
||
|
if {$u==1} {
|
||
|
$c config -cursor top_right_corner
|
||
|
} elseif {$d==1} {
|
||
|
$c config -cursor bottom_right_corner
|
||
|
} else {
|
||
|
$c config -cursor right_side
|
||
|
}
|
||
|
} elseif {$u==1} {
|
||
|
$c config -cursor top_side
|
||
|
} elseif {$d==1} {
|
||
|
$c config -cursor bottom_side
|
||
|
} else {
|
||
|
$c config -cursor left_ptr
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proc selectmarkLeave {c x y} {
|
||
|
global thruplotResize
|
||
|
.bottom.textbox config -text {}
|
||
|
|
||
|
# cursor options for thruplot resize
|
||
|
if {$thruplotResize == true} {
|
||
|
|
||
|
} else {
|
||
|
# no resize update cursor
|
||
|
$c config -cursor left_ptr
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
proc textEnter { c x y } {
|
||
|
global annotation_list
|
||
|
global curcanvas
|
||
|
|
||
|
set object [newObjectId annotation]
|
||
|
set newtext [$c create text $x $y -text "" \
|
||
|
-anchor w -justify left -tags "text $object annotation"]
|
||
|
|
||
|
set coords [$c coords "text && $object"]
|
||
|
set iconcoords "iconcoords"
|
||
|
|
||
|
global $object
|
||
|
set $object {}
|
||
|
setType $object "text"
|
||
|
lappend $iconcoords $coords
|
||
|
lappend $object $iconcoords
|
||
|
lappend $object "label {}"
|
||
|
setNodeCanvas $object $curcanvas
|
||
|
|
||
|
lappend annotation_list $object
|
||
|
popupAnnotationDialog $c $object "false"
|
||
|
}
|
||
|
|
||
|
|
||
|
proc drawText {text} {
|
||
|
global $text defTextColor defTextFont defTextFontFamily defTextFontSize
|
||
|
global zoom curcanvas newfontsize
|
||
|
|
||
|
set coords [getNodeCoords $text]
|
||
|
if { [llength $coords] < 2 } {
|
||
|
puts "Bad coordinates for text $text"
|
||
|
return
|
||
|
}
|
||
|
set x [expr {[lindex $coords 0] * $zoom}]
|
||
|
set y [expr {[lindex $coords 1] * $zoom}]
|
||
|
set color [lindex [lsearch -inline [set $text] "labelcolor *"] 1]
|
||
|
if { $color == "" } {
|
||
|
set color $defTextColor
|
||
|
}
|
||
|
set label [lindex [lsearch -inline [set $text] "label *"] 1]
|
||
|
set fontfamily [lindex [lsearch -inline [set $text] "fontfamily *"] 1]
|
||
|
set fontsize [lindex [lsearch -inline [set $text] "fontsize *"] 1]
|
||
|
if { $fontfamily == "" } {
|
||
|
set fontfamily $defTextFontFamily
|
||
|
}
|
||
|
if { $fontsize == "" } {
|
||
|
set fontsize $defTextFontSize
|
||
|
}
|
||
|
set newfontsize $fontsize
|
||
|
set font [list "$fontfamily" $fontsize]
|
||
|
set effects [lindex [lsearch -inline [set $text] "effects *"] 1]
|
||
|
set newtext [.c create text $x $y -text $label -anchor w \
|
||
|
-font "$font $effects" -justify left -fill $color \
|
||
|
-tags "text $text annotation"]
|
||
|
|
||
|
.c addtag text withtag $newtext
|
||
|
.c raise $text background
|
||
|
setNodeCanvas $text $curcanvas
|
||
|
setType $text "text"
|
||
|
}
|
||
|
|
||
|
|
||
|
proc fontupdate { label type args} {
|
||
|
global fontfamily fontsize
|
||
|
global textBold textItalic textUnderline
|
||
|
|
||
|
if {"$textBold" == 1} {set bold "bold"} else {set bold {} }
|
||
|
if {"$textItalic"} {set italic "italic"} else {set italic {} }
|
||
|
if {"$textUnderline"} {set underline "underline"} else {set underline {} }
|
||
|
switch $type {
|
||
|
fontsize {
|
||
|
set fontsize $args
|
||
|
}
|
||
|
fontfamily {
|
||
|
set fontfamily "$args"
|
||
|
}
|
||
|
}
|
||
|
set f [list "$fontfamily" $fontsize]
|
||
|
lappend f "$bold $italic $underline"
|
||
|
$label configure -font "$f"
|
||
|
}
|
||
|
|
||
|
|
||
|
proc drawAnnotation { obj } {
|
||
|
switch -exact -- [nodeType $obj] {
|
||
|
oval {
|
||
|
drawOval $obj
|
||
|
}
|
||
|
rectangle {
|
||
|
drawRect $obj
|
||
|
}
|
||
|
text {
|
||
|
drawText $obj
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# shift annotation coordinates by dx, dy; does not redraw the annotation
|
||
|
proc moveAnnotation { obj dx dy } {
|
||
|
set coords [getNodeCoords $obj]
|
||
|
lassign $coords x1 y1 x2 y2
|
||
|
set pt1 "[expr {$x1 + $dx}] [expr {$y1 + $dy}]"
|
||
|
if { [nodeType $obj] == "text" } {
|
||
|
# shift one point
|
||
|
setNodeCoords $obj $pt1
|
||
|
} else { ;# oval/rectangle
|
||
|
# shift two points
|
||
|
set pt2 "[expr {$x2 + $dx}] [expr {$y2 + $dy}]"
|
||
|
setNodeCoords $obj "$pt1 $pt2"
|
||
|
}
|
||
|
}
|