# ----------------------------------------------------------------------------- # Pwline.plug version 1.0.3, 30.4.2004 # Piecewise line drawing plugin for wavesurfer # # (c)2004, Dimitrios Zachariadis # dzach_at_hol.gr # http://users.hol.gr/~dzach/index.htm # # First release 24.4.2004 # # This software is provided as open source, under the GPL license # ----------------------------------------------------------------------------- wsurf::RegisterPlugin pwline \ -description "Plug-in that enables drawing of piecewise lines on wavesurfer panes." \ -addmenuentriesproc pwline::addMenuEntries \ -redrawproc pwline::redraw \ -propertiespageproc pwline::propertyPane \ -applypropertiesproc pwline::applyProperties \ -getconfigurationproc pwline::getConfiguration \ -getboundsproc pwline::getBounds \ -panecreatedproc pwline::paneCreated \ -panedeletedproc pwline::paneDeleted \ -cursormovedproc pwline::cursorMoved \ -url http://users.hol.gr/~dzach/wavesurfer/pwline.htm #proctrace::showTraceGUI #::tkcon::Init namespace eval pwline { variable Info set ::pwline 0 set Info(script) [info script] set Info(path) "" } # ----------------------------------------------------------------------------- proc pwline::getBounds {w pane} { upvar [namespace current]::${pane}::var v if {[info exists v(pwline)]} { set snd [$w cget -sound] list 0 $v(minValue) [$snd length -unit seconds] $v(maxValue) } else { list } } # ---------------------------------------------------------------------------- proc pwline::paneCreated {w pane} { variable Info namespace eval [namespace current]::${pane} {variable var} upvar [namespace current]::${pane}::var v set v(pwline) 0 set v(maxValue) 0 set v(minValue) 0 set v(unit) "" set v(selectedNodes) "" set v(movSel) "" set Info(debug) $::wsurf::Info(debug) } # ---------------------------------------------------------------------------- proc pwline::paneDeleted { w pane } { regsub -all {\.} $pane _ widgetPath catch {destroy .sect$widgetPath} catch {destroy .blowup} catch {destroy .cbctrl$widgetPath} catch {destroy .wactrl$widgetPath} namespace delete [namespace current]::${pane} } # ---------------------------------------------------------------------------- proc pwline::createPwline { w pane} { upvar [namespace current]::${pane}::var v set pane [$w addPane -before $pane -height 100 -scrolled 0 -scrollheight 100 \ -unit "Hz" -fillcolor lightyellow -framecolor blue -minvalue 60 -maxvalue 250 -showyaxis true] init $w $pane events $w $pane 1 } # ---------------------------------------------------------------------------- proc pwline::init { w pane args} { upvar [namespace current]::${pane}::var v array set a [list \ -nodeFill "#c0c0c0" \ -nodeOutline "blue" \ -selectedNodeFill "red" \ -selectedNodeOutline "red" \ -activeNodeFill "blue" \ -activeNodeOutline "blue" \ -lineColor "#0080ff" \ -unit "Hz" \ -sz 3 \ -lineWidth 1 \ -minValue "60" \ -maxValue "250" \ -yState "normal" \ -unitState "normal" \ -showscale "0" \ -scalebase "65.4064" \ -scalecolor "#b5b5b5" \ -pitchline 0 \ -pitchlinecolor "black" \ -pitchdots 0 \ -pitchdotcolor "red" \ ] array set a $args set v(nodeFill) $a(-nodeFill) set v(nodeOutline) $a(-nodeOutline) set v(selectedNodeFill) $a(-selectedNodeFill) set v(selectedNodeOutline) $a(-selectedNodeOutline) set v(activeNodeFill) $a(-activeNodeFill) set v(activeNodeOutline) $a(-activeNodeOutline) set v(lineColor) $a(-lineColor) set v(unit) $a(-unit) set v(sz) $a(-sz) set v(lineWidth) $a(-lineWidth) set v(minValue) $a(-minValue) set v(maxValue) $a(-maxValue) set v(min) $a(-minValue) set v(max) $a(-maxValue) set v(yState) $a(-yState) set v(unitState) $a(-unitState) set v(showScale) $a(-showscale) set v(scaleBase) $a(-scalebase) set v(scaleColor) $a(-scalecolor) set v(pitchLine) $a(-pitchline) set v(pitchLineColor) $a(-pitchlinecolor) set v(pitchDots) $a(-pitchdots) set v(pitchDotColor) $a(-pitchdotcolor) set v(pwline) 1 set v(pps) [$pane cget -pixelspersecond] set v(hpp) 1 return 0 } # ---------------------------------------------------------------------------- proc pwline::events {w pane flag} { upvar [namespace current]::${pane}::var v set c [$pane canvas] bind $c [namespace code [list _mdown $w $pane %x %y]] bind $c [namespace code [list _mdrag $w $pane %x %y]] bind $c [namespace code [list _mup $w $pane %x %y]] bind $c [namespace code [list _shiftMdown $w $pane %x %y]] bind $c [namespace code [list _shiftMdrag $w $pane %x %y]] bind $c [namespace code [list _mup $w $pane %x %y]] bind $c [namespace code [list _ctrlMdown $w $pane %x %y]] bind $c break bind $c [namespace code [list dummy $w $pane]] util::canvasbind $c "pwnode" [namespace code [list _mdownOnNode $w $pane %x %y]] util::canvasbind $c "pwnode" [namespace code [list _shiftMdownNode $w $pane]] util::canvasbind $c "pwnode" [namespace code [list _dragNode $w $pane %x %y]] util::canvasbind $c "pwnode" [namespace code [list _mupOnNode $w $pane]] util::canvasbind $c "pwnode" [namespace code [list _shiftMupNode $w $pane]] util::canvasbind $c "pwnode" [namespace code [list _delNode $w $pane]] util::canvasbind $c "pwnode" [namespace code [list dummy $w $pane]] util::canvasbind $c "pwnode" [namespace code [list _delSelNodes $w $pane]] util::canvasbind $c "pwline" [namespace code [list _mdownLine $w $pane]] util::canvasbind $c "pwline" [namespace code [list _ctrlMdown $w $pane %x %y]] util::canvasbind $c "pwline" [namespace code [list delAllNodes $w $pane]] util::canvasbind $c "pwnode" [namespace code [list _propDragNode $w $pane %x %y]] util::canvasbind $c "pwnode" [namespace code [list _propDragNode $w $pane %x %y]] util::canvasbind $c "pwnode" [namespace code [list _propDragNode $w $pane %x %y]] } # ---------------------------------------------------------------------------- proc pwline::getConfiguration { w pane } { upvar [namespace current]::${pane}::var v set result {} if {$pane != "" && $v(pwline)} { append result "\$widget pwline::init \$pane\ -nodeFill \"$v(nodeFill)\" \ -nodeOutline \"$v(nodeOutline)\" \ -selectedNodeFill \"$v(selectedNodeFill)\" \ -selectedNodeOutline \"$v(selectedNodeOutline)\" \ -activeNodeFill \"$v(activeNodeFill)\" \ -activeNodeOutline \"$v(activeNodeOutline)\" \ -lineColor \"$v(lineColor)\" \ -unit \"$v(unit)\" \ -sz \"$v(sz)\" \ -lineWidth \"$v(lineWidth)\" \ -minValue \"$v(minValue)\" \ -maxValue \"$v(maxValue)\" \ -yState \"$v(yState)\" \ -unitState \"$v(unitState)\" \ -showscale \"$v(showScale)\" \ -scalebase \"$v(scaleBase)\" \ -pitchline \"$v(pitchLine)\" \ -pitchlinecolor \"$v(pitchLineColor)\" \ -pitchdots \"$v(pitchDots)\" \ -pitchdotcolor \"$v(pitchDotColor)\" \ -scalecolor \"$v(scaleColor)\"\n \ \$widget pwline::events \$pane 1\n" } return $result } # ---------------------------------------------------------------------------- proc pwline::addMenuEntries {w pane m hook x y} { if {[string match query $hook] || [string match *wavebar $pane]} { return 0 } if {$hook == "create"} { $m.$hook add command -label "Pwline" -command [namespace code [list createPwline $w $pane]] } } # ---------------------------------------------------------------------------- proc pwline::cursorMoved { w pane time value} { upvar [namespace current]::${pane}::var v if {!$v(pwline)} {return} $w messageProc [format "Cursor at -> 0%.3f, %.0f$v(unit) " $time $value] } # ---------------------------------------------------------------------------- proc pwline::propertyPane { w pane } { upvar [namespace current]::${pane}::var v if {$pane=="" || !$v(pwline)} return #<< "$v(pwline)" return [list "PWline" [namespace code drawPwlinePage]] } # ---------------------------------------------------------------------------- proc pwline::applyProperties {w pane} { upvar [namespace current]::${pane}::var v if {$v(pwline)} { set v(nodeFill) $v(t,nodeFill) set v(nodeOutline) $v(t,nodeOutline) set v(selectedNodeFill) $v(t,selectedNodeFill) set v(selectedNodeOutline) $v(t,selectedNodeOutline) set v(activeNodeFill) $v(t,activeNodeFill) set v(activeNodeOutline) $v(t,activeNodeOutline) set v(lineColor) $v(t,lineColor) set v(lineWidth) $v(t,lineWidth) set v(sz) $v(t,sz) set v(minValue) $v(t,minValue) set v(maxValue) $v(t,maxValue) set v(showScale) $v(t,showScale) set v(scaleBase) $v(t,scaleBase) set v(scaleColor) $v(t,scaleColor) set v(pitchLine) $v(t,pitchLine) set v(pitchLineColor) $v(t,pitchLineColor) set v(pitchDots) $v(t,pitchDots) set v(pitchDotColor) $v(t,pitchDotColor) redraw $w $pane } } # ---------------------------------------------------------------------------- proc pwline::drawPwlinePage { w pane p } { upvar [namespace current]::${pane}::var v if {!$v(pwline)} {return 0} set v(t,nodeFill) $v(nodeFill) set v(t,nodeOutline) $v(nodeOutline) set v(t,selectedNodeFill) $v(selectedNodeFill) set v(t,selectedNodeOutline) $v(selectedNodeOutline) set v(t,activeNodeFill) $v(activeNodeFill) set v(t,activeNodeOutline) $v(activeNodeOutline) set v(t,lineColor) $v(lineColor) set v(t,lineWidth) $v(lineWidth) set v(t,sz) $v(sz) set v(t,minValue) $v(minValue) set v(t,maxValue) $v(maxValue) set v(t,unit) $v(unit) set v(t,showScale) $v(showScale) set v(t,scaleBase) $v(scaleBase) set v(t,scaleColor) $v(scaleColor) set v(t,pitchLine) $v(pitchLine) set v(t,pitchLineColor) $v(pitchLineColor) set v(t,pitchDots) $v(pitchDots) set v(t,pitchDotColor) $v(pitchDotColor) foreach f [winfo children $p] { destroy $f } pack [frame $p.f1] -anchor w label $p.f1.l1 -text "Node fill:" -width 17 -anchor w entry $p.f1.e -textvar [namespace current]::${pane}::var(t,nodeFill) -wi 10 label $p.f1.l2 -text " " -bg $v(t,nodeFill) button $p.f1.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,nodeFill) $p.f1.l2] pack $p.f1.l1 $p.f1.e $p.f1.l2 $p.f1.b -side left -padx 3 pack [frame $p.f2] -anchor w label $p.f2.l1 -text "Node outline:" -width 17 -anchor w entry $p.f2.e -textvar [namespace current]::${pane}::var(t,nodeOutline) -wi 10 label $p.f2.l2 -text " " -bg $v(t,nodeOutline) button $p.f2.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,nodeOutline) $p.f2.l2] pack $p.f2.l1 $p.f2.e $p.f2.l2 $p.f2.b -side left -padx 3 pack [frame $p.f8] -anchor w label $p.f8.l1 -text "Selected node fill:" -width 17 -anchor w entry $p.f8.e -textvar [namespace current]::${pane}::var(t,selectedNodeFill) -wi 10 label $p.f8.l2 -text " " -bg $v(t,selectedNodeFill) button $p.f8.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,selectedNodeFill) $p.f8.l2] pack $p.f8.l1 $p.f8.e $p.f8.l2 $p.f8.b -side left -padx 3 pack [frame $p.f9] -anchor w label $p.f9.l1 -text "Selected node outline:" -width 17 -anchor w entry $p.f9.e -textvar [namespace current]::${pane}::var(t,selectedNodeOutline) -wi 10 label $p.f9.l2 -text " " -bg $v(t,selectedNodeOutline) button $p.f9.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,selectedNodeOutline) $p.f9.l2] pack $p.f9.l1 $p.f9.e $p.f9.l2 $p.f9.b -side left -padx 3 pack [frame $p.f3] -anchor w label $p.f3.l1 -text "Active node fill:" -width 17 -anchor w entry $p.f3.e -textvar [namespace current]::${pane}::var(t,activeNodeFill) -wi 10 label $p.f3.l2 -text " " -bg $v(t,activeNodeFill) button $p.f3.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,activeNodeFill) $p.f3.l2] pack $p.f3.l1 $p.f3.e $p.f3.l2 $p.f3.b -side left -padx 3 pack [frame $p.f4] -anchor w label $p.f4.l1 -text "Active node outline:" -width 17 -anchor w entry $p.f4.e -textvar [namespace current]::${pane}::var(t,activeNodeOutline) -wi 10 label $p.f4.l2 -text " " -bg $v(t,activeNodeOutline) button $p.f4.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,activeNodeOutline) $p.f4.l2] pack $p.f4.l1 $p.f4.e $p.f4.l2 $p.f4.b -side left -padx 3 pack [frame $p.f5] -anchor w label $p.f5.l1 -text "Line color:" -width 17 -anchor w entry $p.f5.e -textvar [namespace current]::${pane}::var(t,lineColor) -wi 10 label $p.f5.l2 -text " " -bg $v(t,lineColor) button $p.f5.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,lineColor) $p.f5.l2] pack $p.f5.l1 $p.f5.e $p.f5.l2 $p.f5.b -side left -padx 3 pack [frame $p.f6] -anchor w label $p.f6.l -text "Line width:" -width 17 -anchor w entry $p.f6.e -textvar [namespace current]::${pane}::var(t,lineWidth) -wi 5 label $p.f6.l1 -text "Node size:" -width 9 -anchor w entry $p.f6.e1 -textvar [namespace current]::${pane}::var(t,sz) -wi 5 pack $p.f6.l $p.f6.e $p.f6.l1 $p.f6.e1 -side left -padx 3 pack [frame $p.f7] -anchor w label $p.f7.l -text "Y_min:" -width 17 -anchor w entry $p.f7.e -textvar [namespace current]::${pane}::var(t,minValue) -wi 5 label $p.f7.l1 -text "Y_max:" -width 9 -anchor w entry $p.f7.e1 -textvar [namespace current]::${pane}::var(t,maxValue) -wi 5 pack $p.f7.l $p.f7.e $p.f7.l1 $p.f7.e1 -side left -padx 3 pack [frame $p.f10] -anchor w label $p.f10.l2 -text "Y-axis units:" -width 17 -anchor w entry $p.f10.e2 -textvar [namespace current]::${pane}::var(t,unit) -wi 5 -state $v(unitState) pack $p.f10.l2 $p.f10.e2 -side left -padx 3 pack [frame $p.f12] -anchor w checkbutton $p.f12.b1 -text "Show music scale" -variable [namespace current]::${pane}::var(t,showScale) pack $p.f12.b1 -side left -padx 0 pack [frame $p.f13] -anchor w label $p.f13.l1 -text "Scale color:" -width 17 -anchor w entry $p.f13.e -textvar [namespace current]::${pane}::var(t,scaleColor) -wi 10 label $p.f13.l2 -text " " -bg $v(t,scaleColor) button $p.f13.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,scaleColor) $p.f13.l2] pack $p.f13.l1 $p.f13.e $p.f13.l2 $p.f13.b -side left -padx 3 pack [frame $p.f11] -anchor w checkbutton $p.f11.b1 -text "Show pitch line" -variable [namespace current]::${pane}::var(t,pitchLine) pack $p.f11.b1 -side left -padx 0 pack [frame $p.f14] -anchor w label $p.f14.l1 -text "Pitch line color:" -width 17 -anchor w entry $p.f14.e -textvar [namespace current]::${pane}::var(t,pitchLineColor) -wi 10 label $p.f14.l2 -text " " -bg $v(t,pitchLineColor) button $p.f14.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,pitchLineColor) $p.f14.l2] pack $p.f14.l1 $p.f14.e $p.f14.l2 $p.f14.b -side left -padx 3 pack [frame $p.f16] -anchor w checkbutton $p.f16.b1 -text "Show pitch dots" -variable [namespace current]::${pane}::var(t,pitchDots) pack $p.f16.b1 -side left -padx 0 pack [frame $p.f15] -anchor w label $p.f15.l1 -text "Dot color:" -width 17 -anchor w entry $p.f15.e -textvar [namespace current]::${pane}::var(t,pitchDotColor) -wi 10 label $p.f15.l2 -text " " -bg $v(t,pitchDotColor) button $p.f15.b -text [::util::mc Choose...] -command [list util::chooseColor [namespace current]::${pane}::var(t,pitchDotColor) $p.f15.l2] pack $p.f15.l1 $p.f15.e $p.f15.l2 $p.f15.b -side left -padx 3 } # ---------------------------------------------------------------------------- proc pwline::redraw {w pane} { upvar [namespace current]::${pane}::var v if {!$v(pwline)} {return} set c [$pane canvas] set new_y_range [expr double($v(maxValue) - $v(minValue))] set new_hpp [expr double($new_y_range) / [$pane cget -scrollheight]] if {[info exists v(nodeCoords)]} { for {set i 0} {$i < [llength $v(nodeCoords)]} {incr i 2} { lset v(nodeCoords) $i [expr [lindex $v(nodeCoords) $i] * [$pane cget -pixelspersecond] / $v(pps)] lset v(nodeCoords) [expr $i + 1] [expr [expr ($v(maxValue) - $v(max))/$new_hpp] + [lindex $v(nodeCoords) [expr $i +1]] * $v(hpp) / $new_hpp] } } set v(max) $v(maxValue) set v(y_range) $new_y_range set v(pps) [$pane cget -pixelspersecond] set v(hpp) $new_hpp $pane configure -minvalue $v(minValue) $pane configure -maxvalue $v(maxValue) ::vtcanvas::drawYAxis $pane $pane.yaxis 0 0 yaxis drawNoteScale $w $pane drawPitch $w $pane [list $v(pitchDots) $v(pitchDotColor) $v(pitchLine) $v(pitchLineColor)] drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::drawPitch {w pane aList} { # pitchDots pitchDotColor pitchLine pitchLineColor set pd [lindex $aList 0];set pdc [lindex $aList 1];set pl [lindex $aList 2];set plc [lindex $aList 3] set c [$pane canvas] # if {$pd==0} { $c delete "dot" # } # if {$pl==0} { $c delete "line" # } if {$pd==0 && $pl==0} {return} set s [$w cget -sound] set fi 0.01 set pt 0 set drawing 0 upvar [namespace current]::${pane}::var v set v(pitchNodes) "" foreach pp [$s pitch -method esps] { set hz [lindex $pp 0] set x [vtcanvas::getCanvasX $pane $pt] set y [vtcanvas::getCanvasY $pane $hz] if {$hz != 0.0} { lappend v(pitchNodes) $pt [expr round($hz)] lappend pitchDots $x $y if {$drawing==0} { set drawing 1 set pitchLine "" } lappend pitchLine $x $y } else { if {$drawing==1} { lappend pitchLines $pitchLine set drawing 0 } } set pt [expr $pt + $fi] } if {$drawing==1} {lappend pitchLines $pitchLine} if {[info exists pitchLines] && $pl} { foreach li $pitchLines { if {[llength $li] >=4 } {$c create line $li -tags "line" -fill $plc} } } if {[info exists pitchDots] && $pd} { foreach {x y} $pitchDots { $c create rect [expr $x - 1] [expr $y - 1] [expr $x + 1] [expr $y + 1] -tags "dot" -fill $pdc -outline $pdc } } } # ---------------------------------------------------------------------------- proc pwline::drawNoteScale {w pane} { upvar [namespace current]::${pane}::var v $w messageProc "Drawing notes..." update idletasks set c [$pane canvas] set height [$pane cget -scrollheight] set width [$pane getCanvasX [$pane cget -maxtime]] $c delete scale set maxv [$pane cget -maxvalue] set minv [$pane cget -minvalue] if {$maxv == $minv} return if {$v(showScale)} { set v(scale) {} foreach i {0 2 4 5 7 9 11 12 14 16 17 19 21 23 24 26 28 29 31 33 35 36 38 40 41 43 45 47 48 50 52 53 55 57 59 60} { set f [expr {$v(scaleBase) * pow(pow(2,1.0/12),$i)}] lappend v(scale) $f set yc [expr {$height-double($height)/($maxv-$minv)*($f-$minv)}] if {$yc < 0} break $c create line 0 $yc $width $yc -fill $v(scaleColor) -tags [list analysis scale] } } $w messageProc "" } # ---------------------------------------------------------------------------- proc pwline::dummy {w pane} {} # ---------------------------------------------------------------------------- proc pwline::_keyPressed {w pane k} { upvar [namespace current]::${pane}::var v set v(akey) $k #<< "$k" } # ---------------------------------------------------------------------------- proc pwline::_ctrlMdown { w pane x y } { set c [$pane canvas] set x [$c canvasx $x] set y [$c canvasy $y] insertNode $w $pane $x $y } # ---------------------------------------------------------------------------- proc pwline::insertNode { w pane x y } { upvar [namespace current]::${pane}::var v set c [$pane canvas] set t1 [$pane cget -maxtime] if {$t1>=0.0} { if {![info exists v(nodeCoords)]} { set v(nodeCoords) [list]; set v(selectedNodes) [list] set v(movSel) 0; } for {set idx 0} {$x > [lindex $v(nodeCoords) $idx] && [lindex $v(nodeCoords) $idx] != ""} {incr idx 2} {} set v(nodeCoords) [linsert $v(nodeCoords) $idx $x $y] for {set i 0} {$i <[llength $v(selectedNodes)]} {incr i} { set aSelNode [lindex $v(selectedNodes) $i] if { $aSelNode >= $idx/2} {lset v(selectedNodes) $i [expr $aSelNode +1]} } drawPwline $w $pane } } # ---------------------------------------------------------------------------- proc pwline::_shiftMupNode {w pane} { upvar [namespace current]::${pane}::var v drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::_selectNode {w pane} { set c [$pane canvas] set curNodeIdx [string range [lindex [$c gettags current] 1] 3 end] selectNode $w $pane $curNodeIdx } # ---------------------------------------------------------------------------- proc pwline::selectNode { w pane nIdx} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set i [lsearch -integer -exact -sorted $v(selectedNodes) $nIdx] if {$i == -1} { lappend v(selectedNodes) $nIdx set v(selectedNodes) [lsort -integer -increasing $v(selectedNodes)]; # dont forget to sort the list } else { set v(selectedNodes) [lreplace $v(selectedNodes) $i $i]} drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::_shiftMdownNode {w pane} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set curNodeIdx [string range [lindex [$c gettags current] 1] 3 end] if {[info exists v(selectedNodes)] && [llength $v(selectedNodes)] == 0} { selectNode $w $pane $curNodeIdx return } set start [lindex $v(selectedNodes) 0] set end [lindex $v(selectedNodes) end] if {$curNodeIdx >= $start} {set end $curNodeIdx} if {$curNodeIdx < $start} {set start $curNodeIdx} selectNodeRange $w $pane [list $start $end] } # ---------------------------------------------------------------------------- proc pwline::_mdownLine {w pane} { upvar [namespace current]::${pane}::var v selectNodeRange $w $pane "all" } # ---------------------------------------------------------------------------- proc pwline::selectNodeRange {w pane range} { upvar [namespace current]::${pane}::var v set v(selectedNodes) "" if {$range == "all"} {set range [list 0 [expr [llength $v(nodeCoords)] /2 - 1]]} for {set i [lindex $range 0]} {$i <= [lindex $range 1]} {incr i} {lappend v(selectedNodes) $i} drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::deselectNodes {w pane} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set v(selectedNodes) [list] if {[info exists v(nodeCoords)]} { drawPwline $w $pane } } # ---------------------------------------------------------------------------- proc pwline::_delNode {w pane} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set v(curNodeIdx) [string range [lindex [$c gettags current] 1] 3 end];# extract the integer part of e.g. pwn1234 delNode $w $pane $v(curNodeIdx) } # ---------------------------------------------------------------------------- proc pwline::delNode {w pane nIdx} { upvar [namespace current]::${pane}::var v set idx [expr $nIdx * 2] set v(nodeCoords) [lreplace $v(nodeCoords) $idx [expr $idx + 1]] set i [lsearch -integer -exact -sorted $v(selectedNodes) $nIdx] if {$i != -1} {lset v(selectedNodes) $i ""} for {incr i} {$i <[llength $v(selectedNodes)]} {incr i} { set aSelNode [lindex $v(selectedNodes) $i] if { $aSelNode >= $v(curNodeIdx)} {lset v(selectedNodes) $i [expr $aSelNode - 1]} } set v(selectedNodes) [join $v(selectedNodes)] drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::_delSelNodes {w pane} { upvar [namespace current]::${pane}::var v set c [$pane canvas] if {[lindex [$c gettags current] 2] == "selected"} {delSelNodes $w $pane} } # ---------------------------------------------------------------------------- proc pwline::delSelNodes {w pane} { upvar [namespace current]::${pane}::var v foreach n $v(selectedNodes) { set idx [expr $n * 2] lset v(nodeCoords) $idx "" lset v(nodeCoords) [expr $idx + 1] "" } set v(nodeCoords) [join $v(nodeCoords)] set v(selectedNodes) "" drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::delAllNodes {w pane} { upvar [namespace current]::${pane}::var v set v(selectedNodes) [list] set v(nodeCoords) [list] drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::drawPwline {w pane} { upvar [namespace current]::${pane}::var v if {[info exists v(nodeCoords)]} { set c [$pane canvas] $c delete pwline pwnode if {[llength $v(nodeCoords)] >= 4} {$c create line $v(nodeCoords) \ -tags [list pwline] -fill $v(lineColor) -width $v(lineWidth) -activefill $v(lineColor)} set pwn 0 foreach {x y} $v(nodeCoords) {;# takes care of drawing selected nodes properly if {[lsearch -integer -exact -sorted $v(selectedNodes) $pwn]!=-1} { set nodeOutline $v(selectedNodeOutline) set nodeFill $v(selectedNodeFill) set selTag "selected" } else { set nodeOutline $v(nodeOutline) set nodeFill $v(nodeFill) set selTag "" } $c create rect [expr $x - $v(sz)] [expr $y - $v(sz)] [expr $x + $v(sz)] [expr $y + $v(sz)] \ -tags [join [list "pwnode" pwn$pwn $selTag]] -activefill $v(activeNodeFill) -activeoutline $v(activeNodeOutline)\ -fill $nodeFill -outline $nodeOutline incr pwn 1 set nodeFill $v(nodeFill) } } } # ---------------------------------------------------------------------------- proc pwline::_mdown {w pane x y} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set x [$c canvasx $x];set y [$c canvasy $y] set v(dragging) 0 set v(selectedNodes) "" set v(x0) $x set v(y0) $y drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::_mdrag {w pane x y} { upvar [namespace current]::${pane}::var v if {![info exists v(x0)]} {return} set v(dragging) 1 set c [$pane canvas] set x [$c canvasx $x];set y [$c canvasy $y] $c delete selSqu $c create rect $v(x0) $v(y0) $x $y -tags "selSqu" -outline black ;#-dash {10 10} if {[info exists v(nodeCoords)]} { set v(selectedNodes) "" for {set i 0} {$i < [llength $v(nodeCoords)]} {incr i 2} { set xn [lindex $v(nodeCoords) $i] set yn [lindex $v(nodeCoords) [expr $i + 1]] if {(($xn >= $v(x0) && $xn <= $x) || ($xn >= $x && $xn <= $v(x0)))&&(($yn >= $v(y0) && $yn <= $y) || ($yn >= $y && $yn <= $v(y0)))} { lappend v(selectedNodes) [expr int($i / 2)] } } } drawPwline $w $pane $w messageProc [format "0%.3f, %.0f$v(unit) " $x $y analysis] } # ---------------------------------------------------------------------------- proc pwline::_mup {w pane x y} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set x [$c canvasx $x] set y [$c canvasy $y] $c delete selSqu set v(t,selectedNodes) "" drawPwline $w $pane if {[info exists v(B1clickAction)] && $v(B1clickAction)!="" && [info exists v(dragging)] && !$v(dragging)} { #<< "Doing others' bussiness with my click." eval $v(B1clickAction) } set v(curNodeIdx) "";set v(lx) "";set v(ly) "";set v(dragging) 0 } # ---------------------------------------------------------------------------- proc pwline::_shiftMdown {w pane x y} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set x [$c canvasx $x];set y [$c canvasy $y] set v(dragging) 0 set v(t,selectedNodes) $v(selectedNodes) set v(x0) $x set v(y0) $y drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::_shiftMdrag {w pane x y} { upvar [namespace current]::${pane}::var v set v(dragging) 1 set c [$pane canvas] #<< "?? [$c gettags current]" set x [$c canvasx $x];set y [$c canvasy $y] $c delete selSqu $c create rect $v(x0) $v(y0) $x $y -tags "selSqu" -outline black set selectedNodes "" if {[info exists v(nodeCoords)]} { for {set i 0} {$i < [llength $v(nodeCoords)]} {incr i 2} { set xn [lindex $v(nodeCoords) $i] set yn [lindex $v(nodeCoords) [expr $i + 1]] if {(($xn >= $v(x0) && $xn <= $x) || ($xn >= $x && $xn <= $v(x0)))&&(($yn >= $v(y0) && $yn <= $y) || ($yn >= $y && $yn <= $v(y0)))} { lappend selectedNodes [expr int($i / 2)] } } set v(selectedNodes) $v(t,selectedNodes) foreach n $selectedNodes { set i [lsearch -integer -exact -sorted $v(t,selectedNodes) $n] if { $i == -1} { lappend v(selectedNodes) $n } else { set v(selectedNodes) [lreplace $v(selectedNodes) $i $i ""] } } set v(selectedNodes) [lsort -integer -increasing [join $v(selectedNodes)]] } drawPwline $w $pane $w messageProc [format "0%.3f, %.0f$v(unit) " $x $y analysis] } # ---------------------------------------------------------------------------- proc pwline::_mdownOnNode {w pane x y} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set xy [tagXY $c current] set v(dragging) 0 set v(lx) [lindex $xy 0];set v(x0) $v(lx) set v(ly) [lindex $xy 1];set v(y0) $v(ly) set v(curNodeIdx) [string range [lindex [$c gettags current] 1] 3 end] set nodeList [$c find withtag pwnode] if {[lindex [$c gettags current] 2] == "selected"} { set selNodeList [$c find withtag selected] foreach n $selNodeList {$c addtag moving withtag $n;} set fn [lindex $selNodeList 0];set ln [lindex $selNodeList end] set fIdx [lsearch -integer -exact -sorted $nodeList $fn];set lIdx [lsearch -integer -exact -sorted $nodeList $ln] set movingLineNodeTags [lrange $nodeList [expr $fIdx - 1] [expr $lIdx + 1]] set v(movSel) 1 } else { set movingLineNodeTags [lrange $nodeList [expr $v(curNodeIdx) - 1] [expr $v(curNodeIdx) + 1]] } set v(movingLineNodeTags) $movingLineNodeTags } # ---------------------------------------------------------------------------- proc pwline::tagXY {canv tag} { set ncoords [$canv coords $tag] set x [expr ([lindex $ncoords 2] - [lindex $ncoords 0]) / 2 + [lindex $ncoords 0]] set y [expr ([lindex $ncoords 3] - [lindex $ncoords 1]) / 2 + [lindex $ncoords 1]] return [list $x $y] } # ---------------------------------------------------------------------------- proc pwline::_propDragNode {w pane x y} { upvar [namespace current]::${pane}::var v #<< "$x $y" } # ---------------------------------------------------------------------------- proc pwline::_dragNode {w pane x y} { upvar [namespace current]::${pane}::var v set v(dragging) 1 set c [$pane canvas] set x [$c canvasx $x] set y [$c canvasy $y] $c delete tempLine $c addtag moving withtag current foreach n $v(movingLineNodeTags) {lappend li [tagXY $c $n]} set li [join $li] if {[llength $li] >= 4} {$c create line $li -tags tempLine -fill black -dash {4 2}} $c move moving [expr {$x-$v(lx)}] [expr {$y-$v(ly)}] set v(lx) $x;set v(ly) $y $c dtag current moving set x [::vtcanvas::getTime $pane $x] set y [::vtcanvas::getValue $pane $y] $w messageProc [format "Node at -> 0%.3f, %.0f$v(unit) " $x $y] } # ---------------------------------------------------------------------------- proc pwline::moveNodes {w pane nIdxList dx dy} { upvar [namespace current]::${pane}::var v foreach i $nIdxList { set xi [expr $i * 2];set yi [expr $i * 2 + 1] set x [lindex $v(nodeCoords) $xi];set y [lindex $v(nodeCoords) $yi] set v(nodeCoords) [lreplace $v(nodeCoords) $xi $yi [expr $x+$dx] [expr $y+$dy]] } drawPwline $w $pane } # ---------------------------------------------------------------------------- proc pwline::_mupOnNode {w pane} { upvar [namespace current]::${pane}::var v set c [$pane canvas] set xy [tagXY $c current];set x [lindex $xy 0];set y [lindex $xy 1] set idx [expr $v(curNodeIdx) * 2] if {$v(dragging)==0} { selectNode $w $pane $v(curNodeIdx) } else { $c delete tempLine set v(movingLineNodeTags) "" set v(nodeCoords) [lreplace $v(nodeCoords) $idx [expr $idx + 1] $x $y] if {$v(movSel)==1} { foreach sn [$c find withtag selected] { set idx [expr [string range [lindex [$c gettags $sn] 1] 3 end] * 2] set xy [tagXY $c $sn];set x [lindex $xy 0];set y [lindex $xy 1] if {$sn != [$c find withtag current]} {set v(nodeCoords) [lreplace $v(nodeCoords) $idx [expr $idx + 1] $x $y]} } set v(movSel) 0 } drawPwline $w $pane set v(curNodeIdx) "";set v(lx) "";set v(ly) "";set v(dragging) 0 foreach n [$c find withtag "moving"] {$c dtag $n "moving"} } } # ----------------------------------------------------------------------------