diff options
Diffstat (limited to 'desiredata/src/desire.tk')
-rw-r--r-- | desiredata/src/desire.tk | 8712 |
1 files changed, 0 insertions, 8712 deletions
diff --git a/desiredata/src/desire.tk b/desiredata/src/desire.tk deleted file mode 100644 index c4dac9d7..00000000 --- a/desiredata/src/desire.tk +++ /dev/null @@ -1,8712 +0,0 @@ -#!/usr/bin/env wish -set svnid {$Id$} -#-----------------------------------------------------------------------------------# -# -# DesireData -# Copyright (c) 2004 by Mathieu Bouchard -# Copyright (c) 2005,2006,2007 by Mathieu Bouchard and Chun Lee -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. - -# See file ../COPYING.desire-client.txt for further informations on licensing terms. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# Note that this is not under the same license as the rest of PureData. -# Even the DesireData server-side modifications stay on the same license -# as the rest of PureData. -# -#-----------------------------------------------------------------------------------# - -# this command rebuilds the package index: echo pkg_mkIndex . | tclsh - -set debug 0 ;# DON'T TOUCH THIS, make yourself a debug.tcl instead! - -if {$tcl_version < 8.5} {puts "Please upgrade to Tcl/Tk 8.5... Thank You.\n(your version is $tcl_version)"; exit 84} - -if {[catch {winfo children .}]} {set tk 0} {set tk 1} - -set argh0 [file normalize [file join [pwd] $argv0]] -set auto_path [concat . \ - [list [file join [file dirname [file dirname $argh0]] lib/pd/bin]] \ - /usr/share/tcltk/tcllib1.10/profiler \ - /usr/lib/tclx8.4 \ - $auto_path] - -package require poe -if {$tk} {package require bgerror} - -catch {package require Tclx} -#if {[catch {source /home/matju/src/svn-pd/desiredata/src/profile_dd.tcl}]} {error_dump} -if {[file exists debug.tcl]} {source debug.tcl} - -proc which {file} { - global env - foreach dir [split $::env(PATH) ":"] { - if {[file exists $dir/$file]} {return $dir/$file} - } - return "" -} - -#-----------------------------------------------------------------------------------# -# some list processing functions and some math too -# these could become another library like objective.tcl -# if they become substantial enough - -# min finds the smallest of two values -# max finds the biggest of two values -# [clip $v $min $max] does [max $min [min $max $v]] -proc min {x y} {expr {$x<$y?$x:$y}} -proc max {x y} {expr {$x>$y?$x:$y}} -proc clip {x min max} { - if {$x<$min} {return $min} - if {$x>$max} {return $max} - return $x -} - -# set several variables from elements of a list -# WARNING: for @-variables, use [list @a @b @c] instead of {@a @b @c} -proc mset {vars list} { - uplevel 1 "foreach {$vars} {$list} {break}" -} - -# add or subtract two lists -proc l+ { al bl} {set r {}; foreach a $al b $bl {lappend r [expr {$a+$b}]}; return $r} -proc l- { al bl} {set r {}; foreach a $al b $bl {lappend r [expr {$a-$b}]}; return $r} -# halve a list -proc l/2 { al } {set r {}; foreach a $al {lappend r [expr {$a/2 }]}; return $r} - -# like l+ or l- but for any infix supported by expr -proc lzip {op al bl} { - set r {} - set e "\$a $op \$b" - foreach a $al b $bl {lappend r [expr $e]} - return $r -} - -# do an operation between all elements of a list and a second argument -proc lmap {op al b } { - set r {} - set e "\$a $op \$b" - foreach a $al {lappend r [expr $e]} - return $r -} - -# sum and product of a list, like math's capital Sigma and capital Pi. -proc lsum {al} {set r 0; foreach a $al {set r [expr {$r+$a}]}; return $r} -proc lprod {al} {set r 1; foreach a $al {set r [expr {$r*$a}]}; return $r} - -# all elements from end to beginning -proc lreverse {list} { - set r {} - for {set i [expr {[llength $list]-1}]} {$i>=0} {incr i -1} {lappend r [lindex $list $i]} - return $r -} - -# list substraction is like set substraction but order-preserving -# this is the same algorithm as Ruby's - operation on Arrays -proc lwithout {a b} { - set r {} - foreach x $b {set c($x) {}} - foreach x $a {if {![info exists c($x)]} {lappend r $x}} - return $r -} - -proc lintersection {a b} { - set r {} - foreach x $b {set c($x) {}} - foreach x $a {if {[info exists c($x)]} {lappend r $x}} - return $r -} - -# removes duplicates from a list, but it must be already sorted. -proc luniq {a} { - set last [lindex $a 0] - set r [list $last] - set i 0 - foreach x $a { - if {$i && [string compare $last $x]} {lappend r $x} - incr i; set last $x - } - return $r -} - -# one-dimensional intervals (left-closed, right-open); not much in use at the moment, not that they wouldn't deserve to! -# (slightly buggy) -proc inside {x x0 x1} {return [expr {$x>=$x0 && $x<$x1}]} -proc overlap {y0 y1 x0 x1} {return [expr {[inside $y0 $x0 $x1] || [inside $y1 $x0 $x1]}]} - -proc distance {point1 point2} { - set off [l- $point1 $point2] - return [expr {sqrt([lsum [lzip * $off $off]])}] -} - -proc rect_centre {rect} { - mset {x1 y1 x2 y2} $rect - return [list [expr {($x1+$x2)/2}] [expr {($y1+$y2)/2}]] -} - -proc lmake {start end} {for {set i $start} {$i<=$end} {incr i} {lappend l $i}; return $l} -#-----------------------------------------------------------------------------------# -set callback_list {} - -proc append_callback {mode when def} { - global callback_list - dict set callback_list $mode $when $def -} - -proc remove_callback {mode} { - global callback_list - set callback_list [dict remove $callback_list $mode] -} - -proc modes_callback {self def {args}} { - global callback_list - set i 0 - dict for {mode callbacks} $callback_list { - foreach {when call} $callbacks { - if {$def == $when} {eval $self $call $args; incr i} - } - } - if {!$i} {return 0} else {return 1} -} - -#-----------------------------------------------------------------------------------# -# Observer pattern -# there's no class for "observer". -# it's anything that has def $myclass notice {args} {...} in which args indicate -# attributes that have changed, or is an empty list if an unspecified number of -# attributes (maybe all) have changed. - -class_new Observable {} -def Observable init {args} { - eval [concat [list super] $args] - set @subscribers {} -} -def Observable subscribe {observer} { - set i [lsearch $@subscribers $observer] - if {$i<0} {lappend @subscribers $observer} -} -def Observable unsubscribe {observer} { - set i [lsearch $@subscribers $observer] - if {$i>=0} {set @subscribers [lreplace $@subscribers $i $i]} -} - -if {$have_expand} { - #def Observable changed {args} { - # puts "Observable changed $self called from [info level [expr [info level]-2]]" - # foreach x $@subscribers {$x notice $self {expand}$args]} - #} - def Observable changed {args} {foreach x $@subscribers {$x notice $self {expand}$args}} - def Observable child_changed {origin args} {foreach x $@subscribers {$x notice $origin {expand}$args}} -} else { - def Observable changed {args} {foreach x $@subscribers {$x notice $self {*}$args}} - def Observable child_changed {origin args} {foreach x $@subscribers {$x notice $origin {*}$args}} -} -def Observable subscribers {} {return $@subscribers} - -#-----------------------------------------------------------------------------------# -set poolset(foo) bar -array unset poolset foo - -class_new Manager {Thing} - -def Manager init {} { - set @q {} - $self call -} - -def Manager call {} { - #if {[llength $@q]} {post "client queue %d" [llength $@q]} - for {set i 0} {$i < [llength $@q]} {incr i} { - set o [lindex $@q $i] - unset ::poolset($o) - if {[info exists _($o:_class)]} { - if {[catch {$o draw_maybe}]} {puts [error_dump]} - } else { - puts " tries to draw ZOMBIE $o" - } - if {$i == [expr {[llength $@q]-1}]} {set @q {}} - } - after 25 [list $self call] -} - -def Manager notice {origin args} { - if {[info exists ::poolset($origin)]} { - # post %s "def Manager notice: double dirty" - # nothing for now - } { - set ::poolset($origin) {-1} - lappend @q $origin - } - #post "Manager notice: queue length is now %d" [llength $@q] -} - -set serial 0 -proc serial {n obj} { - if {$n >= $::serial} {error "object creation serial number is in the future"} - eval [concat $::replyset($n) [list $obj]] - array unset ::replyset $n -} - -proc philtre {atoms} { - set r {} - foreach atom $atoms {lappend r [regsub -all {([;,\\ ])} $atom {\\\1}]} - return [join $r] -} - -# you pass the 2nd argument if and only if the message creates an object (or pretends to). -# this happens with #N canvas, and those methods of #X: -# obj, msg, floatatom, symbolatom, text, connect, text_setto, array. -# this does NOT happen with #X coords/restore/pop. -proc netsend {message {callback ""}} { - #if {$message == ""} {error "empty message... surely a mistake"} - if {$::sock == ""} {error "connection to server needed for doing this"} - if {$callback != ""} { - set ::replyset($::serial) $callback - set message [concat [lrange $message 0 0] [list with_reply $::serial] [lrange $message 1 end]] - incr ::serial - } - set text "[philtre $message];" - if {$::debug} {puts "[VTcyan]<- $text[VTgrey]"} - puts $::sock $text -} - -#-----------------------------------------------------------------------------------# -# This is not a real Hash, just the same interface as a Ruby/Python/Perl Hash... or quite like Tcl arrays themselves -class_new Hash {Thing} - -def Hash init {args} { super; foreach {k v} $args {$self set $k $v}} -def Hash reinit {args} {$self clear; foreach {k v} $args {$self set $k $v}} -def Hash set {k v} {set ::hash($self:$k) $v} -def Hash exists {k} {info exists ::hash($self:$k)} -def Hash get {k} {set ::hash($self:$k)} -def Hash size {} {llength [$self keys]} -def Hash unset {k} {unset ::hash($self:$k)} -def Hash list {} {set r {}; foreach k [$self keys] {lappend r $k [$self get $k]}; return $r} -def Hash keys {} { - set r {} - set n [string length $self:] - foreach k [array names ::hash $self:*] {lappend r [string range $k $n end]} - return $r -} -def Hash values {} { - set r {} - foreach k [array names ::hash $self:*] {lappend r $::hash($k)} - return $r -} -def Hash clear {} {foreach k [$self keys] {$self unset $k}} -def Hash delete {} {$self clear; super} - -def Hash search {v} { - foreach k [$self keys] {if {[$self get $k] == $v} {return $k}} - return -1 ;# this is not correct as -1 could be a Hash key, though not in its current context of use... -} - -if 0 { - set h [Hash new foo bar 1 2 3 4] - $h set hello world - puts keys=[$h keys] - puts values=[$h values] - puts list=[$h list] - $h unset foo - puts list=[$h list] - $h clear - puts list=[$h list] - foreach i {1 2 3 4} {puts "exists $i : [$h exists $i]"} -} - -class_new Selection {Hash} -def Selection set {k v} {super $k $v; $v selected?= 1} -def Selection unset {k} { - #set v [$self get $k]; puts "$v ::: [$v class]" - if {[$self exists $k]} {[$self get $k] selected?= 0} - super $k -} -#-----------------------------------------------------------------------------------# -# abstract class: subclass must def {value value= <<} -class_new Clipboard {Observable Thing} -def Clipboard init {{value ""}} {super; $self value= $value; set @copy_count 0} - -# uses system clipboard -class_new Clipboard1 {Clipboard} -def Clipboard1 value= {value} {clipboard clear; clipboard append $value; $self changed} -def Clipboard1 << {value} { clipboard append $value; $self changed} -def Clipboard1 value {} {clipboard get} - -# uses string buffer (not system clipboard) -class_new Clipboard2 {Clipboard} -def Clipboard2 value= {value} {set @value $value; $self changed} -def Clipboard2 << {value} {append @value $value; $self changed} -def Clipboard2 value {} {return $@value} - -if {$tk} { - set clipboard [Clipboard1 new] -} else { - set clipboard [Clipboard2 new] -} - -#-----------------------------------------------------------------------------------# -class_new EventHistory {Observable Thing} - -def EventHistory init {} {super; set @list {}} -def EventHistory add {e} {lappend @list $e; $self changed add $e} -def EventHistory list {{formatted 1}} { - if {!$formatted} {return $@list} - set r {} - foreach event $@list { - mset {type W x y mod K k} $event - lappend r [format "%-13s %9s %4d %4d %4d %4d %s" $type $K $k $x $y $mod $W] - } - return $r -} -set ::event_history [EventHistory new] - -#-----------------------------------------------------------------------------------# -class_new CommandHistory {Observable Thing} - -def CommandHistory init {} { - super - set @undo_stack {} - set @redo_stack {} -} - -def CommandHistory can_undo? {} {return [expr {[llength @undo_stack] > 0}]} -def CommandHistory can_redo? {} {return [expr {[llength @redo_stack] > 0}]} -def CommandHistory next_undo_name {} {return stuff} -def CommandHistory next_redo_name {} {return stuff} -def CommandHistory undo_stack {} {return $@undo_stack} -def CommandHistory redo_stack {} {return $@redo_stack} - -# overload this if you want to control how many levels -# of undo may be kept. -# keep in mind that undo information is kept hierarchically. -def CommandHistory add {message} { - lappend @undo_stack [list do $message [lrange [info level -3] 1 end]] - set @redo_stack {} - $self changed -} - -def CommandHistory can't {} { - lappend @undo_stack [list can't {} [lrange [info level -3] 1 end]] - set @redo_stack {} - $self changed -} - -# runs the restore procedure for the last item in the root undo queue. -def CommandHistory undo {} { - if {![$self can_perform? [lindex $@undo_stack end]]} {error "Can't undo this!"} - set backup $@undo_stack - set @undo_stack $@redo_stack - set @redo_stack {} - #set err [catch {$self perform [lindex $backup end]}]; if {$err} {set err $::errorInfo} - $self atomically [list atomic_undo] { - $self perform [lindex $backup end] - } - set @redo_stack $@undo_stack - set @undo_stack [lrange $backup 0 end-1] - $self changed - #if {$err} {post %s $err; error "undo: $err"} -} - -def CommandHistory redo {} { - if {![$self can_perform? [lindex $@undo_stack end]]} {error "Can't redo this!"} - set backup $@redo_stack - set @redo_stack {} - set err [catch {$self perform [lindex $backup end]}]; if {$err} {set err $::errorInfo} - $self atomically [list atomic_redo] { - $self perform [lindex $backup end] - } - set @redo_stack [lrange $backup 0 end-1] - $self changed - #if {$err} {post %s $err; error "redo: $err"} -} - -def CommandHistory can_perform? {action} { - switch -- [lindex $action 0] { - do {return 1} - can't {return 0} - default { - foreach x [lrange $action 1 end] { - if {![$self can_perform? $x]} {return 0} - } - return 1 - } - } -} - -def CommandHistory perform {action} { - switch -- [lindex $action 0] { - do {eval [lindex $action 1]} - can't {error "can't undo this!"} - default {foreach x [lreverse [lindex $action 1]] {$self perform $x}} - } -} - -def CommandHistory atomically {what code} { - set ubackup @undo_stack; set @undo_stack {} - set rbackup @redo_stack; set @redo_stack {} - uplevel 2 $code - set atom $@undo_stack - set @undo_stack $ubackup - set @redo_stack $rbackup - lappend @undo_stack [list $what $atom [lrange [info level -3] 1 end]] - $self changed -} - -def CommandHistory list {} { - set r {} - set hist [concat [$self undo_stack] [list "You Are Here"] [lreverse [$self redo_stack]]] - set i 0 - foreach e $hist {lappend r "$i: $e"; incr i} - return $r -} - -set command_history [CommandHistory new] - -#-----------------------------------------------------------------------------------# -class_new History {Thing} - -def History init {size} { - set @size $size - set @hist {{}} - set @histi -1 -} - -def History histi= {val} {set @histi $val} -def History histi {} {return $@histi} - -def History set_hist {idx stuff} {set @hist [lreplace $@hist $idx $idx $stuff]} - -def History prepend {stuff} { - set @hist [linsert $@hist 1 $stuff] - if {[llength $@hist] >= $@size} {set @hist [lrange $@hist 0 [expr {$@size-1}]]} -} - -def History traverse {incr} { - set @histi [expr {$@histi + $incr}] - set mod [min [llength $@hist] [expr {$@size+1}]] - if {$@histi >=$mod} {set @histi [expr $@histi%$mod]} - if {$@histi < 0} {set @histi [expr ($@histi+$mod)%$mod]} - return [lindex $@hist $@histi] -} - -History new_as obj_hist 5 -#-----------------------------------------------------------------------------------# -# this is the beginning of the more application-dependent part. - -switch $tcl_platform(os) { - Darwin {set OS osx} - default {set OS $tcl_platform(platform)} -} - -if {$tk} { - option add *foreground #000000 - option add *font {Helvetica -12} - foreach tkclass {Menu Button Checkbutton Radiobutton Entry Text Spinbox Scrollbar Canvas} { - option add *$tkclass*borderWidth 1 - option add *$tkclass*activeBorderWidth 1 - } - foreach tkclass {CheckButton RadioButton} { - option add *$tkclass*selectColor #dd3000 - } - foreach tkclass {Entry Text} { - option add *$tkclass*background #b0c4d8 - option add *$tkclass*selectBackground #6088b0 - } - option add *__tk__messagebox*Canvas*borderWidth 0 - foreach tkclass {Listbox} { - option add *$tkclass*background #c4d8b0 - option add *$tkclass*selectBackground #88b060 - } - foreach tkclass {Label} { - #option add *$tkclass*background #909090 - } - # very small icons: - foreach {name w h values} { - icon_empty 7 7 "0,0,0,0,0,0,0" - icon_plus 7 7 "8,8,8,127,8,8,8" - icon_minus 7 7 "0,0,0,127,0,0,0" - icon_close 7 7 "99,119,62,28,62,119,99" - icon_wedge_up 7 5 "8,28,62,127,0" - icon_wedge_down 7 5 "0,127,62,28,8" - icon_up 7 7 "8,28,62,127,28,28,28" - icon_down 7 7 "28,28,28,127,62,28,8" - icon_right 7 7 "8,24,63,127,63,24,8" - icon_left 7 7 "8,12,126,127,126,12,8" - } { - image create bitmap $name -data "#define z_width $w\n#define z_height $h - static unsigned char z_bits[] = { $values };" - } - - - set main [. cget -class] - set ::current_window . - bind $main <FocusIn> {set ::current_window %W} - bind Toplevel <FocusIn> {set ::current_window %W} - proc tk_messageBox2 {args} {tk_messageBox -parent $::current_window {*}$args} - - # Also we have to get rid of tab's changing the focus. - bind all <Key-Tab> "" - #bind all <Key-Shift-Tab> "" - bind all <<PrevWindow>> "" - set mods {{} 0 Shift- 1 Control- 4 Shift-Control- 5 Alt- 8 Shift-Alt- 9 Control-Alt- 12 Shift-Control-Alt- 13} - foreach type {KeyPress KeyRelease} { - foreach {subtype mod} $mods { - bind all <$subtype$type> "$::event_history add \[list $type %W %x %y $mod %K %k\]" - } - } - foreach type {ButtonPress ButtonRelease} { - foreach {subtype mod} $mods { - bind all <$subtype$type> "$::event_history add \[list $type %W %x %y $mod %b %b\]" - } - } -} - -proc modekey {k mode} { - set s "" - if {$mode&1} {append s Shift-} - if {$mode&4} {append s Control-} - if {$mode&8} {append s Alt-} - if {[regexp {[0-9]} $k]} {set k Key-$k} - return $s$k -} - -proc modeclick {k mode event} { - set s "" - if {$mode&1} {append s Shift-} - if {$mode&4} {append s Control-} - if {$mode&8} {append s Alt-} - if {[regexp {[0-9]} $k]} {set k $event-$k} - return $s$k -} - -# there are two palettes of 30 colours used in Pd -# when placed in a 3*10 grid, the difference is that -# the left corner of 3*3 (the greys) are transposed (matrixwise) -# here is the one used in the swatch color selector: -set preset_colors { - fcfcfc e0e0e0 bcbcbc fce0e0 fce0c0 fcfcc8 d8fcd8 d8fcfc dce4fc f8d8fc - a0a0a0 7c7c7c 606060 fc2828 fcac44 e8e828 14e814 28f4f4 3c50fc f430f0 - 404040 202020 000000 8c0808 583000 782814 285014 004450 001488 580050 -} - -switch $::OS { - osx {set pd_tearoff 0} - default {set pd_tearoff 1} -} - -proc guess_lang {} { - set lang C - if {[info exist ::env(LC_ALL)]} {set lang $::env(LC_ALL)} - if {[info exist ::env(LANG)]} {set lang $::env(LANG)} - set lang [lindex [split $lang {[_.]}] 0] - return $lang -} - -#temporary -set leet 0 - -proc say {k args} { - global text - if {[llength $args]} { - set text($k) [lindex $args 0] - } else { - if {[info exist text($k)]} { - if {$::leet} { - return [string map -nocase {a 4 e 3 t 7 s 5 i 1 o 0 g 9} $text($k)] - } else { - return $text($k) - } - } else {return "{{$k}}"} - } -} - -proc can_say {k args} { - return [info exist ::text($k)] -} - -proc say_namespace {k code} {uplevel 1 $code} -proc say_category {text} {} - -switch -- [lindex [file split $argh0] end] { - desire.tk {set cmdline(server) [file join [file dirname $argh0] pd]} - default {set cmdline(server) [file join [file dirname [file dirname $argh0]] bin/pd]} -} - -set cmdline(rcfilename) ~/.pdrc -set cmdline(ddrcfilename) ~/.ddrc -set cmdline(console) 1000 -if {[file exists ../icons/mode_edit.gif]} { - set cmdline(icons) ../icons -} else { - set cmdline(icons) [file join [file dirname [file dirname $argh0]] lib/pd/icons] -} - -#-----------------------------------------------------------------------------------# -set accels {} -proc read_client_prefs_from {filename} { - global cmdline look key accels - set ::accels {} - puts "reading from $filename" - set fd [open $filename] - set contents [read $fd] - close $fd - foreach {category category_data} $contents { - foreach {class class_data} $category_data { - foreach {var val} $class_data {set ${category}($class:$var) $val} - } - } - foreach k [array names key] { - if {[llength $key($k)]} { - if {![dict exists $accels $key($k)]} { - dict set accels $key($k) $k - } else { - dict lappend accels $key($k) $k - } - } - } -} -proc read_ddrc {} { ;# load defaults then load .ddrc - if {[file exists "defaults.ddrc"]} { - read_client_prefs_from "defaults.ddrc" - } else { - read_client_prefs_from [file join [file dirname [file dirname $::argh0]] "lib/pd/bin/defaults.ddrc"] - } - if {[file exists $::cmdline(ddrcfilename)]} { - read_client_prefs_from $::cmdline(ddrcfilename) - } -} -read_ddrc - -#-----------------------------------------------------------------------------------# - -set cmdline(port) 0 -set cmdline(gdb) 0 -set cmdline(gdbconsole) 1 -set cmdline(valgrind) 0 -if {$look(View:language) eq "auto"} { - set language [guess_lang] -} else { - set language $look(View:language) -} - -set files_to_open {} - -proc cmdline_help {} { - puts "DesireData commandline options: - -serverargs (for future use) - -server select the executable for the pd server - -gdb run pd server through gdb - -manualgdb run gdb in the terminal - -valgrind run pd server through valgrind - -novalgrind ... or don't - -safemode run desiredata with all default settings - -dzinc use zinc emulation" -} - -for {set i 0} {$i < $argc} {incr i} { - global cmdline files_to_open - set o [lindex $argv $i] - switch -regexp -- $o { - ^-port\$ {incr i; set cmdline(port) [lindex $argv $i]} - ^-serverargs\$ {error "not supported yet"} - ^-server\$ {incr i; set cmdline(server) [lindex $argv $i]} - ^-gdb\$ {set cmdline(gdb) 1} - ^-manualgdb\$ {set cmdline(gdbconsole) 0} - ^-valgrind\$ {set cmdline(valgrind) 1} - ^-novalgrind\$ {set cmdline(valgrind) 0} - ^-safemode\$ {set cmdline(safemode) 1} - ^-dzinc\$ {set cmdline(dzinc) 1} - ^(-h|-help|--help)\$ {cmdline_help; exit 1} - ^- {puts "ERROR: command line argument: unknown $o"} - default {lappend files_to_open [lindex $argv $i]} - } -} - -#set cmdline(server) \"$cmdline(server)\" -set encoding "" -if {$language == "C"} {set language en} -proc localedir {x} {file join [file dirname [file dirname $::argh0]] lib/pd/bin/$x} -if {[regexp {desire\.tk$} $argh0]} {source locale/index.tcl} {source [localedir locale/index.tcl]} -puts "locale/index.tcl vs [localedir locale/index.tcl]" -set langentry [figure_out_language $language] -set encoding [lindex $langentry 0] -set langfile locale/[lindex $langentry 1].tcl -if {[regexp {desire\.tk$} $argh0]} { - if {$encoding != ""} {source -encoding $encoding $langfile} else {source $langfile} -} else { - if {$encoding != ""} {source -encoding $encoding [localedir $langfile]} else {source [localedir $langfile]} -} - -if {[info exists ::cmdline(safemode)]} {read_client_prefs_from "defaults.ddrc"} -if {[info exists ::cmdline(dzinc)]} {package require dzinc} - -#-----------------------------------------------------------------------------------# - -#!@#$ is this still valid? -set look(Box:extrapix) [switch $::OS { - osx {concat 2} - default {concat 1}}] - -#font is defined as Thing for now, as the completion needs to get to these ones. - -#!@#$ View->??? -#set look(View:tooltip) 1 - -#!@#$ View->TextBox ? -#set look(View:minobjwidth) 21 - -#!@#$ View->ObjectBox -#set look(View:fg) #000000 -#set look(View:bg) #ffffff -#set look(View:frame1) #99cccc -#set look(View:frame2) #668888 -#set look(View:frame3) #000000 - -set zoom(canned) [list 25 33 50 75 100 125 150 200 250 300 400] -set scale_amount 1.1 -################## set up main window ######################### - -class_new Console {View} - -def Console osx_scroll {axis diff} {$@c.1 yview scroll [expr {-2-abs($diff)/$diff}]} - -def Console init {c} { - set @c $c - frame $c - text $c.1 -width 72 -height 20 -yscrollcommand "$c.2 set" -font [$self look font] - scrollbar $c.2 -command "$c.1 yview" - pack $c.1 -side left -fill both -expand yes - pack $c.2 -side left -fill y -expand no - pack $c -fill both -expand yes - $c.2 set 0.0 1.0 - switch $::OS {osx {bind $c.1 <MouseWheel> [list $self osx_scroll %D]}} - set @lines 0 -} - -def Console widget {} {return $@c} - -def Console post_string {x} { - set oldpos [lindex [$@c.2 get] 1] - $@c.1 insert end $x - regsub -all "\n" $x "" y - set n [expr {[string length $x]-[string length $y]}] - incr @lines $n - set max $::cmdline(console) - if {$@lines >= $max} {$@c.1 delete 1.0 [expr {$@lines-$max+1}].0; set @lines $max} - if {$oldpos > 0.9999} {$@c.1 see end} -} - -#class_new Client {Menuable View} -class_new Client {Menuable Thing} - -set ctrls_audio_on 0 -set ctrls_meter_on 0 - -def Client window {} {return .} - -def Client init_binds {} { - bind . <Control-Key> {$main ctrlkey %x %y %K %A 0} - bind . <Control-Shift-Key> {$main ctrlkey %x %y %K %A 1} - switch $::OS { - osx { - bind . <Mod1-Key> {$main ctrlkey %x %y %K %A 0} - bind . <Mod1-Shift-Key> {$main ctrlkey %x %y %K %A 1} - } - } -# bind . <Motion> {.debug.1 configure -text "widget = %W"} -} - -# miller uses this nowadays (matju fished it in pd-cvs for 0.40). we don't use it for now. -# remember to fix all quoting problems, which in the end may or may not involve the following proc. -proc pdtk_unspace {x} { - set y [string map {" " "_" ";" "" "," "" "{" "" "}" "" "\\" ""} $x] - if {$y == ""} {set y "empty"} - concat $y -} - -proc pdtk_pd_meters {indb outdb inclip outclip} { - foreach {z clip db} [list in $inclip $indb out $outclip $outdb] { - .controls.$z.1.mtr coords m 0 0 $db 0 - .controls.$z.1.clip configure -background [if {$clip==1} {concat red} {concat black}] - } -} - -proc pd_startup {version apilist midiapilist args} { - set ::pd_version $version - set ::pd_apilist $apilist - set ::pd_midiapilist $midiapilist - foreach api $apilist { - lappend ::pd_apilist2 "-[string tolower [lindex $api 0]]" - } - set version [regsub "^DesireData " $::pd_version ""] - post "DesireData server version $version" -} - -def Client init_controls {} { - menu .mbar - pack [frame .controls] -side top -fill x - foreach t {file window help} { - .mbar add cascade -label [say $t] -menu [menu .mbar.$t -tearoff $::pd_tearoff] - } - .mbar.window configure -postcommand "$self fix_window_menu" - foreach {z fill} {in #0060ff out #00ff60} { - set f .controls.$z - frame $f - frame $f.1 -borderwidth 2 -relief groove - canvas $f.1.mtr -width 100 -height 10 -bg #222222 - $f.1.mtr create line [list 0 0 0 0] -width 24 -fill $fill -tags m - canvas $f.1.clip -width 5 -height 10 -bg #222222 - pack $f.1.mtr $f.1.clip -side left - pack [label $f.2 -text [say $z]:] $f.1 -side left - pack $f -side left -pady 0 -padx 0 - } - foreach {w x y z} { - audiobutton audio ctrls_audio_on {netsend [list pd dsp $ctrls_audio_on]} - meterbutton meters ctrls_meter_on {netsend [list pd meters $ctrls_meter_on]} - } { - pack [checkbutton .controls.$w -text [say $x] -variable $y -anchor w -command $z] -side left - } - button .controls.clear -text [say console_clear] -command {.log.1 delete 0.0 end} -padx 2 -pady 0 - button .controls.dio -text [say io_errors] -command {netsend [list pd audiostatus]} -padx 2 -pady 0 - pack .controls.clear .controls.dio -side right - if {$::debug} { - frame .debug - pack [label .debug.1 -anchor w -text ""] -side left - pack [entry .debug.3 -textvariable ::serial -width 5] -side right - pack [label .debug.2 -text "obj.serial: " -justify right] -side right - pack .debug -side bottom -fill x - } - if {$::cmdline(console)} {set ::console [Console new .log]} - . configure -menu .mbar - wm title . "DesireData" - catch {wm iconphoto . icon_pd_32} - if {[regexp {\d\d\d\d-\d\d-\d\d} $::svnid date]} { - regsub -all "/" $date "." date - regexp {desire.tk (\d+)} $::svnid blah revision - set version "svn#$revision ($date)" - } {set version "(unknown svn version)"} - set ::pd_version_client $version - post "DesireData client version %s" $version - post "Running from %s" [info script] - post "Using Tcl %s and Tk %s" $::tcl_patchLevel $::tk_patchLevel -} - -proc pdtk_pd_dsp {value} { - global ctrls_audio_on - set ctrls_audio_on $value -} - -proc pdtk_pd_dio {red} { - .controls.dio configure -background red -activebackground [if {$red==1} {list red} {list lightgrey}] -} - -############### set up global variables ################################ - -set pd_opendir [pwd] - -############### set up socket ########################################## -set sock {} -set sock_lobby {} - -proc poll_sock {} { - global sock sock_lobby cmdline - if {[llength $sock]==0} {return} - while {1} { - set cmd [gets $sock] - if {[eof $sock]} { - if {!$cmdline(gdb)} { - tk_messageBox2 -message "connection ended by server.\n(crash? try: desire -gdb)" -type ok - } - set sock {} - return - } - if {[fblocked $sock]} {break} - if {$::debug} {if {[string first pdtk_post $cmd]!=0} {puts "[VTmagenta]-> $cmd[VTgrey]"}} - append sock_lobby "\n$cmd" - if {[catch {eval $sock_lobby}]} { - switch -regexp -- $::errorInfo { "^missing close-brace" { - #puts "waiting for the end of: [string range $sock_lobby 0 40]" - continue - }} - error_dump - } - set sock_lobby {} - } - flush $sock - after 25 poll_sock -} - -set server_pid 0 -proc poll_gdb {} { - global gdb - while {1} { - set line [gets $gdb] - if {$line=="" || [fblocked $gdb]} {break} ;# which way should i check for no input? - if {[eof $gdb]} {return} - regsub {^\(gdb\) ?} $line {} line - if {[regexp {^\[Thread debug} $line]} {continue} - if {[regexp {^\[New Thread.*LWP (\d+)} $line dummy pid]} { - if {!$::server_pid} { - set ::server_pid $pid - post "server pid=$pid" - continue - } - } - if {[regexp {^Reading symbols from} $line]} {continue} - if {[regexp {^Using host libthread_db} $line]} {continue} - if {[regexp {^Starting program:} $line]} {continue} - if {[regexp {^Program received signal (\w+), (.*)\.} $line bogus sig1 sig2]} { - set where "" - # can anyone figure out why a long backtrace won't be slurped in this case? - set timeout [expr {[clock seconds]+2}] - #fconfigure $gdb -blocking 1 -buffering none - while {![eof $gdb] && [clock seconds] < $timeout} { - set line [gets $gdb] - if {$line eq ""} {continue} ;# busy-wait - regsub {^\(gdb\) ?} $line {} line - append where "$line\n" - #puts "where size = [string length $where]" - } - OopsDialogue new $sig1 $sig2 $where - } - post "\[gdb\] %s" $line - } - after 100 poll_gdb -} - -proc pd_connect {} { - global sock - if {[catch {set sock [socket 127.0.0.1 13666]}]} { - post "can't connect... wait a second" - after 1000 pd_connect - return - } - post "Connected to server" - fconfigure $sock -blocking 0 -buffering line - netsend [list pd init] - poll_sock - foreach f $::files_to_open { - set ff [file split [file normalize $f]] - set ffl [llength $ff] - set file [lindex $ff [expr $ffl-1]] - set dir [join [lrange $ff 0 [expr $ffl-2]] [file separator]] - netsend [join [list pd open $file $dir]] - } -} - -set server_port 13666 -after 1000 pd_connect - -after 0 { - if {$cmdline(port)} { - set server_port $cmdline(port) - # and then do nothing... - } elseif {$cmdline(valgrind)} { - #exec valgrind --tool=memcheck $cmdline(server) -guiport $server_port & - exec valgrind --tool=memcheck --gen-suppressions=all --suppressions=valgrind3.supp $cmdline(server) -guiport $server_port & - } else { - if {$cmdline(gdb)} { - if {$cmdline(console) && $cmdline(gdbconsole)} { - set gdb [open "| gdb --quiet 2&>1" w+] - fconfigure $gdb -blocking 0 -buffering none - puts $gdb "file \"$cmdline(server)\"" ;# bad quoting, sorry - puts $gdb "set width 242" - puts $gdb "run -guiport $server_port" - puts $gdb "where" - puts $gdb "quit" - flush $gdb - after 0 poll_gdb - } else { - exec gdb --args $cmdline(server) -guiport $server_port & - #exec gdb --tui --args $cmdline(server) -guiport $server_port & - } - } else { - exec $cmdline(server) -guiport $server_port & - } - } -} - -################ utility functions ######################### - -proc enquote {x} { - set foo [string map {"," "" ";" "" "\"" ""} $x] - return [string map {" " "\\ " "{" "" "}" ""} $foo] -} - -proc pdtk_watchdog {} {netsend [list pd ping]; after 2000 {pdtk_watchdog}} - -proc accel_munge {acc} { - switch $::OS { - osx { - set tmp [string toupper [string map {Ctrl Meta} $acc] end] - if [string is upper [string index $acc end]] { - return Shift+$tmp - } else { - return $tmp - } - } - default {return $acc} - } -} - -# a menuable must be a View -# and it must have a window so that the Menuable methods work -# it could be renamed to Windowed -class_new Menuable {} -def Menuable init {args} { - eval [concat [list super] $args] - set @accel {} - set @menubar .$self.m -} - -# this doesn't have to do with menus, only with toplevel windows. -def Menuable raise {} { - set w [$self window] - set w $w.c - raise $w - focus -force $w -} - -set untitled_number 1 -set untitled_folder [pwd] - -# just a dummy proc -proc none {args} {} - -def Client new_file {} { - global untitled_number untitled_folder - netsend [list pd filename Untitled-$untitled_number $untitled_folder] - netsend [list #N canvas] - netsend [list #X pop 1] - incr untitled_number -} - - -set patch_filetypes { - {"pd files" ".pd"} - {"max files" ".pat"} - {"all files" "*"} -} - -set image_filetypes { - {"image files" ".gif .png"} - {"gif files" ".gif"} - {"png files" ".png"} - {"all files" "*"} -} - -catch {tk_getOpenFile -load-once} ;#only works with tcltk 8.5 -catch { - set ::tk::dialog::file::showHiddenBtn 1 - set ::tk::dialog::file::showHiddenVar 0 -} - -def Client open_file {} { - global pd_opendir patch_filetypes - set filename [tk_getOpenFile -parent $::current_window -defaultextension .pd -filetypes $patch_filetypes -initialdir $pd_opendir] - if {$filename != ""} {$self open_file_really $filename} -} - -def Client open_file_really {filename} { - set i [string last / $filename] - set folder [string range $filename 0 [expr $i-1]] - set ::pd_opendir $folder - set basename [string range $filename [expr $i+1] end] - if {[string last .pd $filename] >= 0} { - netsend [list pd open $basename $folder] - } -} - -def Client send_message {} { - toplevel .sendpanel - set e .sendpanel.entry - pack [entry $e -textvariable send_textvar] -side bottom -fill both -ipadx 100 - $e select from 0 - $e select adjust end - bind $e <KeyPress-Return> {netsend $send_textvar; after 50 {destroy .sendpanel}} - focus $e -} - -def Client quit {} { - set answer [tk_messageBox2 -message "Do you really wish to quit?" -type yesno -icon question] - switch -- $answer {yes {netsend [list pd quit]; exit}} -} - -def Client abort_server {} { - set answer [tk_messageBox2 -message "Do you really wish to abort?" -type yesno -icon question] - switch -- $answer {yes {exec kill -ABRT $::server_pid}} -} - -def Client server_prefs {} {ServerPrefsDialogue new_as pdrc} -def Client client_prefs {} {ClientPrefsDialogue new_as ddrc} - -proc menu_pop_pd {} {raise .} - -def Menuable populate_menu {menu list} { - global key - if {[string index $menu 0] != "."} {set menu $@menubar.$menu} - foreach name $list { - if {$name == ""} {$menu add separator; continue} - set k "" - if {[info exists key($@_class:$name)]} { - if {[string length $key($@_class:$name)]} {set k $key($@_class:$name)} - } - $menu add command -label [say $name] -command "$self $name" -accelerator [accel_munge $k] - } -} - -def Client init_menus {} { - #removed paths after send_message - $self populate_menu file { - new_file open_file {} - server_prefs client_prefs send_message {} - audio_on audio_off {} - abort_server quit} - $self populate_menu help { - about documentation class_browser do_what_i_mean {} - test_audio_and_midi load_meter latency_meter {} - clipboard_view command_history_view event_history_view keyboard_view client_class_tree} -} - -def Client init {} { - super - set @menubar .mbar - $self init_controls - $self init_binds - $self init_menus - # it's necessary to raise the window on OSX - switch $::OS { osx {raise .; wm iconify .; after 100 {wm deiconify .}}} - after 0 { - Listener new .tcl [say "tcl_console"] tcl_eval - Listener new .pd [say "pd_console"] pd_eval - } - #wm geometry .[$self keyboard_view] -0+0 - #wm geometry .[$self event_history_view] -0-0 -} - -proc post {args} { - set s "[eval [linsert $args 0 format]]\n" - # set s "[info level -1]: $s" - if {$::cmdline(console)} {$::console post_string $s} else {puts stderr $s} -} -proc pdtk_post {s} { - if {$::cmdline(console)} {$::console post_string $s} else {puts stderr $s} -} - -def Menuable eval% {code} { - regsub -all %W $code $self code - uplevel [info level] $code -} - -def Menuable getkey {k} { - global accels - if {[dict exists $accels $k]} { - set vars [dict get $accels $k] - foreach var $vars { - #mset {class key} [split [dict get $accels $k] ":"] - mset {class key} [split $var ":"] - #if {$class != $@_class} {return ""} else {return $key} - if {$class == $@_class} {return $key} - } - } -} - -def Menuable ctrlkey {x y key iso shift} { - set key [if {$shift} {string toupper $key} {string tolower $key}] - set key "Ctrl+$key" - set cmd [$self getkey $key] - if {![string length $cmd]} { - switch [$self class]:$key { - #explicitly listed here to do nothing - Client:Ctrl+c {} - Client:Ctrl+v {} - default {post "unknown key $key"} - } - } else {$self eval% "%W $cmd"} -} - -def Menuable altkey {x y key iso shift} { - set key [if {$shift} {string toupper $key} {string tolower $key}] - set key "Alt+$key" - set cmd [$self getkey $key] - if {[string length $cmd]} {$self eval% "%W $cmd"} else {post "unknown key $key"} -} - -#-----------------------------------------------------------------------------------# -set pd_apilist "{ALSA 1}" -set pd_apilist2 "default" - -#-----------------------------------------------------------------------------------# -#fixme: actually, is it ok that View<Menuable ? --matju -class_new View {Menuable Observable Thing} - -# normally ninlets/noutlets should be in class "Box", but server-side isn't smart enough -def View pdclass= {v} {set @pdclass $v} -def View pdclass {} {return $@pdclass} -def View ninlets= {v} {set @ninlets $v} -def View ninlets {} {return $@ninlets} -def View noutlets= {v} {set @noutlets $v} -def View noutlets {} {return $@noutlets} -def View click {x y f target} {} -def View unclick {x y f target} {} -def View motion {x y f target} {} - -def View subpatch {} {if {[info exists @subpatch]} {return 1} else {return 0}} - -def View look_cache {k} { - global look look_cache - foreach super [$@_class ancestors] { - if {[info exists look($super:$k)]} { - set look_cache($@_class:$k) $super - return $super - } - } -} -def View look {k} { - if {![info exists ::look_cache($@_class:$k)]} {$self look_cache $k} - return $::look($::look_cache($@_class:$k):$k) -} - -def View init {} { - super - set @selected? 0 - set @index 0xDEADBEEF - set @ninlets 1 ;# should be in Box init - set @noutlets 0 ;# should be in Box init - set @canvas "" -# set @inside_box 42 ;# temporary fix - set @ioselect {} -} - -def View classtags {} {return {foo}} - -set item { - set canvas [$self get_canvas] - if {$canvas == ""} {return} - set c [$self cwidget] - set zoom [$canvas zoom] - set coords [lmap * $coords $zoom] - set find [lsearch $args "-width"] - if {$find >= 0} { - incr find - set w [lindex $args $find] - lset args $find [format %.0f [expr {$w*$zoom}]] - } - set find [lsearch $args "-font"] - if {$find >= 0} { - incr find - set fs [lindex [lindex $args $find] 1] - lset args $find 1 [format %.0f [expr {$fs*$zoom}]] - } - #set find [lsearch $args "-fill"] - #if {$find >= 0} { - # incr find - # set fill [lindex $args $find] - # lset args $find [randomise_color $fill] - #} - set tags {} - foreach s $suffixes {lappend tags "$self$s"} - set ss [lindex $tags 0] - lappend tags $self - set tags [concat $tags [$self classtags]] -} -append item [correct_splat { - if {![llength [$c gettags $ss]]} { - $c create $type $coords -tags $tags {*}$args - } { - $c itemconfigure $ss {*}$args - $c coords $ss {*}$coords - } -}] -def View item {suffixes type coords args} $item - -def View item_delete {{suffix all}} { - if {$@canvas == ""} {return} - set c [$@canvas widget] - if {![winfo exists $c]} { - set canvas [$@canvas get_canvas] - if {$canvas == ""} {return} - set c [[$@canvas get_canvas] widget] - if {![winfo exists $c]} {return} - } - switch -- $suffix { - all {$c delete $self} - default {$c delete $self$suffix}} -} - -def View draw {} {} - -def View delete {} {$self erase; super} -def View erase {} {$self item_delete} -def View selected? {} {return $@selected?} -def View selected?= {x} {set @selected? $x; $self changed} ;# this is for use by the Selection class only -def View edit? {} {if {[info exists @edit]} {return $@edit} else {return 0}} -def View select {state} { - set ostate [$self selected?] - set @selected? $state - if {$state!=$ostate} {$self changed} -} - -# give topleft point of an object in the canvas it's rendered in. -# this includes GOP and excludes zoom. -# inheritance problem: this doesn't work for Wire, which doesn't store its positions -def View xy {} { - if {$@canvas == ""} {return [list $@x1 $@y1]} - set type [$@canvas type] - if {$type == "gopabs" || $type == "gopsub"} { - mset {xmargin ymargin} [$@canvas margin] - mset {x y} [$@canvas xy] - set x1 [expr {($@x1-$xmargin)+$x}] - set y1 [expr {($@y1-$ymargin)+$y}] - #if $self's gop is opened - if {[regexp {^.x[0-9a-f]{6,8}.c} [focus] f]} { - if {$f == ".$@canvas.c"} {set x1 $@x1; set y1 $@y1} - } - #if {[focus] != "." && [focus] == ".$@canvas.c"} {set x1 $@x1; set y1 $@y1} - return [list $x1 $y1] - } - return [list $@x1 $@y1] -} - -def View canvas {} {return $@canvas} -def View canvas= {c} { - set @canvas $c - # should "subscribe" call "changed"? (or pretend to?) - $self subscribe $c - $self changed - $self outside_of_the_box -} - -def View visible {} {if {[info exists @inside_box]} {return $@inside_box} {return -1}} - -# this returns the canvas actually exists/drawn -# see also def Canvas get_canvas -def View get_canvas {} { - set canvas $@canvas - if {$canvas == ""} {return ""} - #while {![$canvas havewindow]} {set canvas [$canvas canvas]} - while {![winfo exists [$canvas widget]]} {set canvas [$canvas canvas]} - return $canvas -} -# this will return the top level gop if gop is nested -def View get_parent_gop {canvas} { - set obj $self - while {$canvas != [$obj canvas]} {set obj [$obj canvas]} - return $obj -} - -def View outside_of_the_box {} { - if {$@canvas eq ""} {return} - # always hide these things - if {[$self class] == "Wire"} {set @inside_box 0; return} - if {[$self class] == "ObjectBox"} {set @inside_box 0; return} - if {[$self class] == "MessageBox"} {set @inside_box 0; return} - if {[$self class] == "Comment"} {set @inside_box 0; return} - if {[$self class] == "Array"} {$@canvas visibles+= $self; set @inside_box 1; return} - set x1 $@x1; set y1 $@y1 - if {[$@canvas gop]} { - set mess [$@canvas get_mess] - set pixwidth [lindex $mess 4] - set pixheight [lindex $mess 5] - if {[llength $mess] == 6} { - set xmargin 0; set ymargin 0 - } else { - set xmargin [lindex $mess 6]; set ymargin [lindex $mess 7] - } - if {$x1 < $pixwidth +$xmargin && $x1 > $xmargin && \ - $y1 < $pixheight+$ymargin && $y1 > $ymargin} { - set @inside_box 1 - $@canvas visibles+= $self - } else { - set @inside_box 0 - $@canvas visibles-= $self - } - } else {set @inside_box 1} -} - -def View draw_maybe {} { - if {$@canvas == "" && [winfo exists .$self.c]} {$self draw; return} - if {[$self class] == "Canvas" && $@canvas == ""} {return} - if {$@inside_box} { - #if {[$@canvas mapped] && ![$@canvas abs] && [$self gop_check]} {$self draw} - if {[$@canvas mapped] && [$self gop_check]} {$self draw} - } else { - # for drawing opened gop - if {[winfo exists .$@canvas.c]} {$self draw} - } -} -#this checks if $self can be seen, ie nested gop. -def View gop_check {} { - set canvases $@canvas - while {[lindex $canvases end] != ""} {lappend canvases [[lindex $canvases end] canvas]} - set canvases [lreplace $canvases end-1 end]; # all canvases - foreach canvas $canvases { - # if a canvas is not a gop and its window does not exists - if {![$canvas gop] && ![winfo exists [$canvas widget]]} {return 0; break} - } - return 1 -} - -#-----------------------------------------------------------------------------------# - -class_new Canvas {Menuable ObjectBox} - -def Canvas close {} { - after cancel $@motion_after_id - if {$@subpatch} { - #can't wait till @mapped get updated thru proc change - if {$@gop} {foreach x [$@objects values] {$x outside_of_the_box}} - $self save_geometry - $self copy_times= 0 - netsend [list .$self vis 0] - #netsend [list .$self close] - return - } - if {$@gop} { - foreach x [$@objects values] {$x outside_of_the_box} - netsend [list .$self close] - return - } - switch [tk_messageBox2 -message [say save_changes?] -icon question -type yesnocancel -default cancel] { - yes {$self save; netsend [list .$self close]} - no { netsend [list .$self close]} - cancel {} - } -} - -def Canvas save_geometry {} { - set geometry [wm geometry .$self] - set cw [winfo width [$self widget]]; set ch [winfo height [$self widget]] - foreach {size x y} [split $geometry "+"] {mset {w h} [split $size "x"]; set x1 $x; set y1 $y} - set x2 [expr $x1+$cw]; set y2 [expr $y1+$ch] - netsend [list .$self bounds $x1 $y1 $x2 $y2] -} - -def Canvas save {} { - if {$@subpatch} {return [$@canvas save]} - $self checkgeometry - set c [$self widget] - if {![regexp {^Untitled-[0-9]} $@name]} { - $self save_geometry - netsend [list .$self savetofile $@name $@folder] - } else { - $self save_as - } -} - -def Canvas save_as {} { - $self checkgeometry - set filename [tk_getSaveFile -parent $::current_window -filetypes $::patch_filetypes] - if {$filename != ""} { - set @file [string range $filename [expr [string last / $filename]+1] end] - set @folder [string range $filename 0 [expr [string last / $filename]-1]] - $self save_geometry - puts "save $@file dir to $@folder" - netsend [list .$self savetofile $@file $@folder] - } -} - -def Canvas print {} { - set filename [tk_getSaveFile -parent $::current_window -initialfile pd.ps -defaultextension .ps -filetypes { {{postscript} {.ps}} }] - if {$filename != ""} {[$self widget] postscript -file $filename} -} -def Canvas quit {} {$::main quit} -def Canvas abort_server {} {$::main abort_server} - -proc wonder {} {tk_messageBox2 -message [say ask_cool] -type yesno -icon question} - -def Canvas eval% {code} { - mset {x y} $@curpos - regsub -all %X $code $x code - regsub -all %Y $code $y code - super $code -} - -def Client documentation {} { - set filename [tk_getOpenFile -parent $::current_window -defaultextension .pd -filetypes { {{documentation} {.pd .txt .htm}} } -initialdir $::docdir] - if {$filename != ""} { - if {[string first .txt $filename] >= 0} { - menu_opentext $filename - } elseif {[string first .htm $filename] >= 0} { - menu_openhtml $filename - } else { - set i [string last / $filename] - set help_directory [string range $filename 0 [expr $i-1]] - set basename [string range $filename [expr $i+1] end] - netsend [list pd open [enquote $basename] [enquote $help_directory]] - } - } -} - -def Canvas new_file {} {$::main new_file} -def Canvas open_file {} {$::main open_file} -def Canvas send_message {} {$::main send_message} -def Client test_audio_and_midi {} {menu_doc_open doc/7.stuff/tools testtone.pd } -def Client load_meter {} {menu_doc_open doc/7.stuff/tools load-meter.pd} -def Client latency_meter {} {menu_doc_open doc/7.stuff/tools latency.pd } -def Client about {} {AboutDialogue new} -def Client class_browser {} {Browser new_as browser browser 0 0 ""} -def Client audio_on {} {netsend [list pd dsp 1]} -def Client audio_off {} {netsend [list pd dsp 0]} -def Client keyboard_view {} { KeyboardDialogue new $::event_history} -def Client clipboard_view {} { ClipboardDialogue new $::clipboard} -def Client command_history_view {} { ListDialogue new $::command_history [say command_history_view]} -def Client event_history_view {} {EventHistoryDialogue new $::event_history} -def Client do_what_i_mean {} {wonder} - -set pd_prefix [file dirname [file dirname [which pd]]] -set pd_guidir ${pd_prefix}/lib/pd -set doc_number 1 -set updir [file dirname [file dirname $argh0]] -if {[file exists $updir/lib/pd/doc]} { - set docdir $updir/lib/pd/doc -} else { - set docdir $updir/doc -} - -proc menu_opentext {filename} { - set w [format ".help%d" $::doc_number] - toplevel $w - wm title $w $filename - frame $w.1 - frame $w.2 - pack [text $w.1.text -relief raised -bd 2 -yscrollcommand "$w.1.scroll set"] -side left -fill both -expand 1 - pack [scrollbar $w.1.scroll -command "$w.1.text yview"] -side right -fill y - pack [button $w.2.close -text [say close] -command "destroy $w"] -side right - pack $w.2 -side bottom -fill x -expand 0 - pack $w.1 -side bottom -fill both -expand 1 - set f [open $filename] - while {![eof $f]} { - set bigstring [read $f 1000] - regsub -all PD_BASEDIR $bigstring $::pd_guidir bigstring - regsub -all PD_VERSION $bigstring $::pd_version bigstring - $w.1.text insert end $bigstring - } - $w.1.text configure -state disabled - close $f - incr ::doc_number - return $w -} - -proc menu_doc_open {subdir basename} { - set dirname $::pd_guidir/$subdir - if {[string first .txt $basename] >= 0} { - return [menu_opentext $dirname/$basename] - } else { - netsend [list pd open $basename $dirname] - } -} - -#-----------------------------------------------------------------------------------# -def Canvas editmode {} {return $@editmode} -def Canvas editmode= {mode} { - if {$mode == $@editmode} {return} - if {!$mode} {$self deselect_all} - $self redraw ;# why this??? - set @editmode $mode; $self changed editmode -# catch {.$self.bbar.edit configure -image icon_mode_$mode} - if {$@mapped} { - if {$mode} {set im icon_mode_edit} else {set im icon_mode_run} - [$self window].bbar.edit configure -image $im - if {[$self look hairstate] && !$@editmode} {$@crosshair erase} - if {[$self look gridstate]} { - if {$@editmode} {$@grid draw} else {$@grid erase} - } - } - # comment's look depends on the value of @editmode - foreach child [$@objects values] {if {[[$child class] <= Comment]} {$child changed}} - #!@#$ should update the checkbox in the editmenu -} - -def Canvas editmodeswitch {} {$self editmode= [expr !$@editmode]} - -def Canvas window {} { - #if {$@gop && $@canvas != ""} {return [$@canvas window]} - return .$self -} -def Canvas widget {} {return .$self.c} -def View cwidget {} {return .[$self get_canvas].c} - -#-----------------------------------------------------------------------------------# - -def Canvas atomically {proc} {$@history atomically $proc} -def Canvas undo {} {$@history undo} -def Canvas redo {} {$@history redo} - -def Canvas init {mess} { - set @mapped 0 - set @gop 0 - set @goprect "" - set @abs 0 - set @name "" - set @folder "???" - set @file "" - super {#X obj 666 666 pd} ;# bogus - $self reinit $mess - set @zoom 1.0 ;# must be a float, not int - set @action none - set @objects [Hash new]; set @objectsel [Selection new]; set @visibles {} - set @wires [Hash new]; set @wiresel [Selection new] - - set @focus "" - set @curpos {30 30} - set @bbox {0 0 100 100} - set @dehighlight {} -# if {$@mapped} {$self init_window} ;#!@#$ @mapped can't possibly be 1 at this point - set @history $::command_history - $self subscribe $::manager - $self changed - #$self canvas= $self ;#!@#$ EEVIL - set @coords 0 - set @jump 0 - set @keynav_iocount 0 ;# the io select count - set @keynav_port 0 ;# which in/outlet is selected - set @keynav 0 ;# the list of objects that has io selected - set @keynav_iosel 0 ;# last object that is io selected - set @keynav_iosel_o {} ;# list of objects that has outlet selected - set @keynav_iosel_i {} ;# list of objects that has inlet selected - set @iosel_deselect 0 ;# if selected should be deselected by clicking at empty space - set @keynav_current 0 - set @keynav_last_obj 0 - set @keynav_last_wire 0 - set @keynav_tab_sel "wire" - set @keynav_shift 0 - set @copy_count 0 - set @findbar "" - set @find_string "" - set @iohilite {-1 0 0 0 0} - set @keyprefix 0 - set @coords {0 0 1 1} ;# default #X coords line - set @pixsize {0 0} - set @margin {0 0} - set @macro_q {} - set @macro_delay 200 - set @blinky "" - set @editmode 0 - set @show_id 0 - set @motion_queue {} -} - -def Canvas reinit {mess} { - switch -- [lindex $mess 0] { - "#N" { - # those four are not to be confused with other @variables of similar names. - set @canvas_pos [lrange $mess 2 3] - set @canvas_size [lrange $mess 4 5] - set args [lrange $mess 6 end] - switch [llength $args] { - 1 { - set @subpatch 0 - mset [list @fontsize] $args - set @name "" - set @mapped 1 - } - 2 { - set @subpatch 1 - mset [list @name @mapped] $args - set @fontsize "what?" - } - default {error "wrong number of arguments (expecting 5 or 6, got [expr 4+[llength $args]])"} - } - } - "#X" { - switch -- [lindex $mess 1] { - obj {} - restore { - set @x1 [lindex $mess 2] - set @y1 [lindex $mess 3] - set args [lrange $mess 4 end] - $self text= [lrange $mess 4 end] - if {!$@subpatch && [llength $args] != 0} {set @abs 1} - if {$@mapped && !$@gop} { - #if {!$@subpatch && $@text != ""} {set @abs 1; return} - #if {![winfo exists .$self.c]} {$self init_window} - } - } - coords { - set @coords [lrange $mess 2 5] - set @pixsize [lrange $mess 6 7] - switch [llength $mess] { - 8 {set @gop 0} - 9 {set @gop [lindex $mess 8]} - 11 { - set @gop [lindex $mess 8] - set @margin [lrange $mess 9 10] - } - default {error "what???"} - } - if {$@gop} {set @mapped 1} - } - } - } - "" {return} - default {error "huh? mess=$mess"} - } -} - -# doesn't this look like Canvas deconstruct ? -def Canvas get_mess {} { - return [concat $@coords $@pixsize $@margin] -} - - -def Canvas margin {} {return $@margin} -def Canvas gop {} {return $@gop} -def Canvas hidtext {} {return $@hidetext} -def Canvas abs {} {return $@abs} -#def Canvas abs {} {if {!$@subpatch} {return 1} else {return 0}} -def Canvas subpatch {} {return $@subpatch} -def Canvas get_dimen {} {return $@canvas_size} - -def Canvas gop_rect {} { - mset {pxs pys} $@pixsize - mset {mx my} $@margin - set rect [list $mx $my [expr $mx+$pxs] [expr $my+$pys]] - if {$@goprect == ""} { - set @goprect [GopRect new $self $rect] - } elseif {!$@editmode} {$@goprect delete; set @goprect ""; return} - $@goprect draw - -} - -rename toplevel toplevel_orig -proc toplevel {name args} { - eval [concat [list toplevel_orig $name] $args] - catch {wm iconphoto $name icon_pd_32} -} - -# should be called once and only from init -def Canvas init_window {} { - lappend ::window_list $self - set win .$self - set c [$self widget] - if {$::tcl_platform(platform) == "macintosh"} { - toplevel $win -menu $win.m - } else { - if {[$self look menubar]} {toplevel $win -menu $win.m} else {toplevel $win -menu ""} - } - set @menubar $win.m - $self init_menus - # turn buttonbar on/off - set @buttonbar [ButtonBar new $self] - if {[$self look buttonbar]} {pack [$@buttonbar widget] -side top -fill x -expand no} - set @statusbar [StatusBar new $self] - # turn statusbar on/off - if {[$self look statusbar]} {pack [$@statusbar widget] -side bottom -fill x} - set w [expr [lindex $@canvas_size 0]-4];# dd canvas is 4 pixel out with pd canvas? - set h [expr [lindex $@canvas_size 1]-4] - pack [canvas $c -width $w -height $h -background white] -side left -expand 1 -fill both - set @yscroll $win.yscroll; set @xscroll $win.xscroll - $self init_scrollbars - wm minsize $win 1 1 - wm geometry $win +[lindex $@canvas_pos 0]+[lindex $@canvas_pos 1] - wm protocol $win WM_DELETE_WINDOW "$self close" - focus $c - $self new_binds - $self update_title - $self motion_update - set @runcommand [Runcommand new .$self "command" canvas_eval] - set @crosshair [Crosshair new $self] - set @active [Active new $self] - set @sense [Sense new $self] - set @grid [Grid new $self] -} - -def Canvas activate_menubar= {val} {if {$val} {.$self configure -menu $@menubar} {.$self configure -menu ""}} - -def Canvas activate_buttonbar= {val} { - if {$val} { - pack [$@buttonbar widget] -side top -fill x -expand no -before [$self widget] - } else {pack forget [$@buttonbar widget]} -} - -def Canvas activate_statusbar= {val} { - if {$val} { - if {[winfo exists $@yscroll]} {set w .$self.yscroll} else {set w .$self.c} - pack [$@statusbar widget] -side bottom -fill x -before $w - } else {pack forget [$@statusbar widget]} -} - -def Canvas activate_scrollbars= {val} {if {!$val} {$self init_scrollbars} {$self remove_scrollbars}} - -def Canvas activate_grid= {val} {if {$val} {$@grid draw} {$@grid erase}} - -def Canvas init_scrollbars {} { - set win .$self - set c [$self widget] - if {[winfo exists $win.yscroll]} {return} - set size [$c bbox foo] - mset {xs ys} $@canvas_size - pack [scrollbar $win.yscroll -command "$c yview" ] -side right -fill y -before $c - pack [scrollbar $win.xscroll -command "$c xview" -orient horizontal] -side bottom -fill x -before $c - set xw $win.xscroll; set yw $win.yscroll - $c configure -yscrollcommand "$self scroll_set $yw" -xscrollcommand "$self scroll_set $xw" - after 0 [list $self adjust_scrollbars] -} - -def Canvas remove_scrollbars {} { - set win .$self - set c [$self widget] - if {![winfo exists $win.yscroll]} {return} - #use destroy instead of pack forget so that it can be tested with winfo exists - destroy $win.yscroll - destroy $win.xscroll - $c configure -yscrollcommand "" -xscrollcommand "" -scrollregion "" -} - -def Canvas adjust_scrollbars {} { - set c [$self widget] - set size [$c bbox foo] - if {[$self look scrollbar]} {$self auto_scrollbars} - if {$size != ""} { - mset {xmin ymin xmax ymax} {0 0 100 100} - mset {x1 y1 x2 y2} $size - if {$x2 > 100} {set xmax $x2} - if {$y2 > 100} {set ymax $y2} - set bbox [list $xmin $ymin $xmax $ymax] - set oldbbox [$c cget -scrollregion] - # it is very inefficient to call "configure" here - if {"$oldbbox" != "$bbox"} {$c configure -scrollregion $bbox} - set @bbox $bbox - } -} - -def Canvas auto_scrollbars {} { - set c [$self widget] - if {[$c bbox foo] != ""} { - mset {cx1 cy1 cx2 cy2} [$c bbox foo] - } else { - set cx2 [lindex $@canvas_size 0]; set cy2 [lindex $@canvas_size 1] - } - set x2 [$c canvasx [winfo width $c]] - set y2 [$c canvasy [winfo height $c]] - if {$x2 == 1} {set x2 $cx2; set y2 $cy2} - if {$cx2 <= $x2 && $cy2 <= $y2} {$self remove_scrollbars} {$self init_scrollbars} -} - -def Canvas delete_window {} { - set wl {} - foreach w $::window_list {if {$w != $self} {lappend wl $w}} - set ::window_list $wl - destroy .$self -} - -def Canvas delete {} { - $self delete_window - super -} - -def Canvas focus {} {return $@focus} -def Canvas focus= {o} {set @focus $o} -def Canvas history {} {return $@history} - -#-----------------------------------------------------------------------------------# -def Canvas find {} { - if {[info exists ::_(findmodel:_class)]} { - focus .$self.find.find - findmodel reinit - } else { - FindModel new_as findmodel $self - FindView new $self - focus .$self.find.find - } -} -def Canvas find_again {} { - if {[info exists ::_(findmodel:_class)]} {findmodel remove_info;findmodel search_recursive} -} - -def Canvas find_last_error {} {netsend [list pd finderror]} - -def Canvas bind {eventtype selector args} { - set c [$self widget] - #bind $c $eventtype [concat [list $self $selector] $args \; $self statusbar_draw %x %y] - #bind $c $eventtype "puts \[time {[concat [list $self $selector] $args \; $self statusbar_draw %x %y]}\]" - #bind $c $eventtype "puts \[time {[concat [list $self $selector] $args]}\]" - if {[$self look statusbar]} { - bind $c $eventtype [concat [list $self $selector] $args \; $self statusbar_draw %x %y] - } else { - bind $c $eventtype [concat [list $self $selector] $args] - } -} - -def Canvas new_binds {} { - # mouse buttons - $self bind <Button> click_wrap %x %y %b 0 - $self bind <Shift-Button> click_wrap %x %y %b 1 - $self bind <Control-Button> click_wrap %x %y %b 2 - $self bind <Control-Shift-Button> click_wrap %x %y %b 3 - $self bind <Alt-Button> click_wrap %x %y %b 4 - $self bind <Alt-Shift-Button> click_wrap %x %y %b 5 - $self bind <Alt-Control-Button> click_wrap %x %y %b 6 - $self bind <Alt-Control-Shift-Button> click_wrap %x %y %b 7 - switch $::OS { - osx { - $self bind <Button-2> click_wrap %x %y %b 8 - $self bind <Control-Button> click_wrap %x %y 3 8 - } - default { - $self bind <Button-3> click_wrap %x %y %b 8 - } - } - switch $::OS { unix { - $self bind <Button-4> scroll y -1 - $self bind <Button-5> scroll y +1 - $self bind <Shift-Button-4> scroll x -1 - $self bind <Shift-Button-5> scroll x +1 - } default { - $self bind <MouseWheel> scroll y %D - $self bind <Shift-MouseWheel> scroll x %D - }} - $self bind <ButtonRelease> unclick_wrap %x %y %b 0 - $self bind <Shift-ButtonRelease> unclick_wrap %x %y %b 1 - - # keyboard - $self bind <Control-Key> ctrlkey %x %y %K %A 0 - $self bind <Control-Shift-Key> ctrlkey %x %y %K %A 1 - $self bind <Alt-Key> altkey %x %y %K %A 0 - $self bind <Alt-Shift-Key> altkey %x %y %K %A 1 - switch $::OS { - unix { - $self bind <Mod1-Key> altkey %x %y %K %A 0 - $self bind <Mod1-Shift-Key> altkey %x %y %K %A 1 - $self bind <Mod4-Key> altkey %x %y %K %A 0 - $self bind <Mod4-Shift-Key> altkey %x %y %K %A 1 - } - osx { - $self bind <Mod1-Key> ctrlkey %x %y %K %A 0 - $self bind <Mod1-Shift-Key> ctrlkey %x %y %K %A 1 - } - } - $self bind <Key> key_wrap %x %y %K %A 0 - $self bind <Shift-Key> key_wrap %x %y %K %A 1 - $self bind <KeyRelease> keyup_wrap %x %y %K %A 0 - $self bind <Shift-KeyRelease> keyup_wrap %x %y %K %A 1 - $self bind <Control-KeyRelease> keyup_wrap %x %y %K %A 0 - $self bind <Motion> motion_wrap %x %y 0 - $self bind <Alt-Motion> motion_wrap %x %y 4 - $self bind <Control-Motion> motion_wrap %x %y 9 - #$self bind <Map> map - #$self bind <Unmap> unmap - $self bind <Leave> leave - $self bind <Configure> configure %h %w -} - -def Canvas configure {h w} { - if {[$self look gridstate]} { - $@grid update $h $w - if {[winfo exists .$self.yscroll]} {return}; # scrollbar will update grid already - $@grid draw - } -} - -#def Canvas map {} {} -#def Canvas unmap {} {} -def Canvas leave {} {$@crosshair erase} - -def Canvas scroll {axis diff} { - set c [$self widget] - $c [list $axis]view scroll $diff units - if {[$self look hairstate] && $@editmode} { - # this should be changed so that we don't need to recompute x,y here. - set x [expr [$c canvasx [expr [winfo pointerx $c] - [winfo rootx $c]]]/$@zoom] - set y [expr [$c canvasy [expr [winfo pointery $c] - [winfo rooty $c]]]/$@zoom] - set target [$self identify_target $x $y 0] - $@crosshair data= $x $y $target - $@crosshair draw - } else { - $@crosshair erase - } -} - -# this allows the grid to update when scroll -def Canvas scroll_set {w v1 v2} {if {[$self look gridstate] && $@editmode} {$@grid draw}; $w set $v1 $v2} - -def Canvas reload {} {netsend [list .$self reupload]} -def Canvas redraw {} { - $self changed - foreach x [$@objects values] {$x changed} - foreach x [ $@wires values] {$x changed} -} - -#patch editing commandline shortcuts -def Canvas o {x y {name ""}} { - set c [$self widget] - if {[$self snap_grid]} {set off [expr [$self look grid_size]/2]} {set off 0} - set @curpos [list [expr [$c canvasx $x]+$off] [expr [$c canvasy $y]+$off]] - $self new_object obj $name -} - -def Canvas c {from outlet to inlet} { - set out_objs [$self parse_idx $from] - set in_objs [$self parse_idx $to] - foreach out $out_objs { - foreach in $in_objs { - $self connect [list $out $outlet $in $inlet] - } - } -} - -def Canvas pc {from outlet to inlet} { - set out_objs [$self parse_idx $from] - set in_objs [$self parse_idx $to] - if {[llength $out_objs] != [llength $in_objs]} {return "No can do :("} - for {set i 0} {$i < [llength $out_objs]} {incr i} { - $self connect [list [lindex $out_objs $i] $outlet [lindex $in_objs $i] $inlet] - } -} - -def Canvas s {selection} { - set objs [$self parse_idx $selection] - foreach obj $objs {$self selection+= [$@objects get $obj]} -} - -def Canvas s+ {selection} { - set objs [$self parse_idx $selection]; set ids {} - foreach obj $objs { - set v [$@objects get $obj]; lappend ids $v - $self selection+= $v - } - $self selection_wire= [$self implicit_wires $ids] -} - -def Canvas sw {from outlet to inlet} { - set out_objs [$self parse_idx $from] - set in_objs [$self parse_idx $to] - foreach out $out_objs { - foreach in $in_objs { - set id [$self wire_idx [list $out $outlet $in $inlet]] - if {$id>=0} {$self selection_wire+= [$@wires get $id]} - } - } -} - -def Canvas parse_idx {val} { - set objs {} - foreach obj [split $val ","] { - if {[regexp {\d+-\d+} $obj range]} { - set l [split $range "-"] - set objs [concat $objs [lmake [lindex $l 0] [lindex $l 1]]] - continue - } - lappend objs $obj - } - return $objs -} - -def Canvas xy_snap {x y} { - if {[$self look snap_grid]} { - set grid [$self look grid_size] - set x [expr floor($x/$grid)*$grid] - set y [expr floor($y/$grid)*$grid] - } - return [list $x $y] - -} - -def Canvas new_object {sel args} { - $self editmode= 1 - $self deselect_all - mset {x y} $@curpos - if {[$self look snap_grid]} { - set grid [$self look grid_size] - set x [expr floor($x/$grid)*$grid] - set y [expr floor($y/$grid)*$grid] - } - switch -- $sel { - obj { set goto [list $self new_object_edit]} - msg { set goto [list $self new_object_edit]} - text { set goto [list $self new_object_edit]} - default {set goto [list $self new_object_callback]} - } - netsend [concat [list .$self $sel $x $y] $args] $goto -} - -def Canvas new_wire_callback {wire} {} - -def Canvas new_object_callback {obj} { - $self add_to_obj_history $obj - set @keynav_last_obj $obj - $self selection+= $obj - if {$@keynav} {$self update_Active $obj} -} - -def Canvas new_object_copyselect {obj} { - $self selection+= $obj - #set @action "move" - #$self click_on_object $obj 0 -} - -def Canvas new_wire_select {wire} {$self selection_wire+= $wire} - -def Canvas new_object_edit {obj} { - if {[$obj class] == "NumBox"} {return} - $obj edit -} - -def Canvas add_to_obj_history {obj} { - if {![[$obj class] <= ObjectBox]} {return} - obj_hist prepend [$obj text] -} - - -def Canvas insertxy {} {return [list $@insert_x $@insert_y]} - -def Canvas insert_object {} {$self do_insert_obj "none" "none"} - -def Canvas get_canvas {} { - if {![info exists @gop]} { - if {[info exists @subpatch]} {if {$@subpatch} {return [$self canvas]}} - if {[info exists @abs]} {if {$@abs} {return [$self canvas]}} - if {[winfo exists .$self.c]} {return $self} - } - #if {[info exists @subpatch]} {if {$@subpatch} {return [$self canvas]}} - return [super] -} - -def Canvas get_topcanvas {} { - set canvas $@canvas - if {$@canvas == ""} {return $self} - while {[$canvas canvas] != ""} {set canvas [$canvas canvas]} - return $canvas -} - -def Canvas do_insert_obj {x y} { - if {$x == "none" && $y == "none"} { - if {[$@wiresel size] != 1} {return} - set wire [$@wiresel values] - puts "insert object for wire $wire" - mset {from outlet to inlet} [$wire report] - set c [$self widget] - set iowidth [$self look iowidth] - mset {ox1 oy1 ox2 oy2} [lmap / [$c bbox ${from}o${outlet}] [$self zoom]] - mset {ix1 iy1 ix2 iy2} [lmap / [$c bbox ${to}i${inlet} ] [$self zoom]] - set x1 [expr $ox1 + $iowidth/2]; set y1 [expr ($oy1+$oy2)/2] - set x2 [expr $ix1 + $iowidth/2]; set y2 [expr ($iy1+$iy2)/2] - set x [expr $x1 + ($x2-$x1)/2] - set y [expr $y1 + ($y2-$y1)/2] - } - netsend [list .$self obj $x $y] [list $self new_object_edit] - set @action insert -} - -def Canvas new_object_insert_wire {obj} { - set wire [$self selection_wire] - $self selection_wire-= $wire - mset {from outlet to inlet} [$wire report] - $self disconnect [$wire connects] - set @keynav 0; $@active hide; set @keynav_tab_sel "object" - set from_idx [$@objects search $from] - set to_idx [$@objects search $to] - set obj3_idx [$@objects search $obj] - $self connect [list $from_idx $outlet $obj3_idx 0] [list $self keynav_current=] - $self connect [list $obj3_idx 0 $to_idx $inlet] - $self action= none -} - -def Canvas chain_object {} { - if {[$@objectsel size] != 1} {return} - set o [$@objectsel values] - mset {x1 y1 x2 y2} [$o bbox] - set grid [$self look grid_size] - if {[$self look snap_grid]} {set y [expr floor(($y2+$grid)/$grid)*$grid]} {set y [expr $y2+10]} - netsend [list .$self obj $x1 $y] [list $self new_object_edit] - set @action chain_obj -} -def Canvas new_object_chain_wire {obj} { - obj_hist prepend [$obj text] - set from_idx [$@objects search [lindex [$self selection] 0]] - $self deselect_all - set to_idx [$@objects search $obj] - $self connect [list $from_idx 0 $to_idx 0] - $self action= none - $self selection= $obj -} - -def Canvas objects {} {return $@objects} -#def Canvas wires {} {return $@wires} -def Canvas selection {} {$@objectsel values} -def Canvas selection= {objs} {$@objectsel clear; $self selection+= $objs} -def Canvas selection+= {objs} {foreach obj $objs {$@objectsel set [$obj index] $obj}} -def Canvas selection-= {objs} {foreach obj $objs {set k [$obj index]; if {[$@objectsel exists $k]} {$@objectsel unset $k}}} -def Canvas selection_wire {} {$@wiresel values} -def Canvas selection_wire= {objs} {$@wiresel clear; $self selection_wire+= $objs} -def Canvas selection_wire+= {objs} {foreach obj $objs {$@wiresel set [$obj index] $obj}} -def Canvas selection_wire-= {objs} {foreach obj $objs {set k [$obj index]; if {[ $@wiresel exists $k]} { $@wiresel unset $k}}} - -def Canvas Object {} {$self new_object obj} -def Canvas Message {} {$self new_object msg} -def Canvas Number {} {$self new_object floatatom} -def Canvas Symbol {} {$self new_object symbolatom} -def Canvas Comment {} {$self new_object text} - -#!@#$ these 9 should be harmonised with the class list instead of having special names -def Canvas bng {} {$self new_object obj bng} -def Canvas tgl {} {$self new_object obj tgl} -def Canvas nbx {} {$self new_object obj nbx} -def Canvas vsl {} {$self new_object obj vsl} -def Canvas hsl {} {$self new_object obj hsl} -def Canvas vradio {} {$self new_object obj vradio} -def Canvas hradio {} {$self new_object obj hradio} -def Canvas vu {} {$self new_object obj vu} -def Canvas cnv {} {$self new_object obj cnv} - -def Canvas Graph {} {$self editmode= 1; netsend [list .x$self graph ]} -def Canvas Array {} {$self editmode= 1; netsend [list .x$self menuarray]} - -def Canvas init_menus {} { - set name .$self - set m $name.m - menu $m - #removed Paths after send_message - foreach x {file edit find view put window help} {menu $m.$x -tearoff $::pd_tearoff} - $self populate_menu file {new_file open_file {} send_message {} close save save_as print {} abort_server quit} - $self populate_menu edit {undo redo {} cut copy paste duplicate select_all subpatcherize {} tidy_up {}} - $self populate_menu find {find find_again find_last_error} - #!@#$ those shortcuts should be looked up in the key table!!! - $m.view add checkbutton -label [say visual_diff] -selectcolor grey0 -command [list $self visual_diff] \ - -accelerator [accel_munge "Ctrl+E"] -indicatoron 1 - $self populate_menu view {get_elapsed {} reload redraw} - $self populate_menu put {Object Message Number Symbol Comment {} bng tgl nbx vsl hsl vradio hradio vu cnv {} Graph Array} - $self populate_menu window {{}} - $m.edit add checkbutton -label [say edit_mode] -selectcolor grey0 -command [list $self editmodeswitch] \ - -accelerator [accel_munge "Ctrl+e"] -indicatoron 1 - $m.edit configure -postcommand "$self fix_edit_menu" - $m.window configure -postcommand "$self fix_window_menu" - foreach x {file edit view find put window help} { - if {$x=="help"} { - # help menu is in the wrong place in patch windows because it's taken from .mbar ??? - $m add cascade -label [say $x] -menu .mbar.$x - } { - $m add cascade -label [say $x] -menu $m.$x - } - } -} - -# corrects edit menu, enabling or disabling undo/redo -# LATER also cut/copy/paste -def Canvas fix_edit_menu {} { - set e .$self.m.edit - switch $::OS {osx {set i 0} default {set i 1}} - set t [say undo] - if {[$@history can_undo?]} { - $e entryconfigure $i -state normal -label "$t [$@history next_undo_name]" - } else { - $e entryconfigure $i -state disabled -label "[say cannot] $t" - } - incr i - set t [say redo] - if {[$@history can_redo?]} { - $e entryconfigure $i -state normal -label "$t [$@history next_redo_name]" - } else { - $e entryconfigure $i -state disabled -label "[say cannot] $t" - } -} - -def Menuable fix_window_menu {} { - set menu $@menubar.window - $menu delete 0 end - foreach w $::window_list {$menu add command -label [wm title [$w window]] -command "$w raise"} -# {"parentwindow" {menu_windowparent} ""} -} - -#-----------------------------------------------------------------------------------# -#this just tells whether an object is part of the selection, that is, what usually makes objects turn blue. -def Canvas selection_include? {member} {expr [$@objectsel search $member]>=0} - -def Canvas type {} { - if {$@subpatch && !$@gop} {return "sub"} - if {$@subpatch && $@gop} {return "gopsub"} - if {$@abs && !$@gop} {return "abs"} - if {$@abs && $@gop} {return "gopabs"} - if {!$@subpatch && !$@abs && !$@gop} {return "toplevel"} -} - -def Canvas draw {} { - if {$@gop} { - if {[$self gop_check]} {$self all_changed} - #if the focus is not in the opened gop - if {[regexp {^.x[0-9a-f]{6,8}.c} [focus] f]} { - if {$@canvas != ""&& $f != [$self widget]} {super;return} - } elseif {$@canvas != "" && [focus] != [$self widget]} {super;return} - } elseif {$@subpatch || $@abs} {super} - if {!$@mapped} {return} else {if {![winfo exists [$self widget]]} {return}} - $self check_findbar - if {$@editmode} {set bg [$self look bgedit]} else {set bg [$self look bgrun]} - [$self widget] configure -background $bg - $self adjust_scrollbars - if {$@gop} {$self gop_rect} -} - -def Canvas popup_properties {} {CanvasPropertiesDialogue new $self} - -def Canvas gop_target {id} { - while {[$id canvas] != $self} {set id [$id canvas]}; return $id -} - -#-----------------------------------------------------------------------------------# -class_new MacroRect {View} - -def MacroRect init {} {super; $self data= 0 0 0 0 blue} - -def MacroRect data= {x1 y1 x2 y2 col} { - set @x1 $x1; set @y1 $y1 - set @x2 $x2; set @y2 $y2 - set @col $col -} - -def MacroRect flash {x1 y1 x2 y2 col} { - $self data= $x1 $y1 $x2 $y2 $col - $self draw - after 500 $self erase -} - -def MacroRect draw {} { - set @canvas [string range [focus] 1 [string first . [focus] 1]-1] - $self item MACRO rect [list $@x1 $@y1 $@x2 $@y2] -outline $@col -} - -class_new Macro {EventHistory} -def Macro init {} { - $::event_history subscribe $self - set @idx 0 - set @state 0 - set @list {} - set @ref_list {} - set @delay 200 - set @offset_x 0 - set @offset_y 0 - set @rect [MacroRect new] -} -def Macro state= {val} { - set @state $val - if {$val} { - set @ref_list {} - set @list {} - post %s "start recording macro..." - } else { - post %s "end..." - } -} -def Macro state {} {return $@state} -def Macro dump {} {set i 0; foreach step $@list {post %s "step $i -> $step"; incr i}} -def Macro idx= {val} {set @idx $val} -def Macro idx {} {return $@idx} -def Macro delay {} {return $@delay} -def Macro append_ref {mess} {lappend @ref_list $mess} -def Macro ref_list {} {puts "$@ref_list";return $@ref_list} -def Canvas ref_list {} {$::macro ref_list} - - -def Macro notice {args} { - if {$@state} { - set mess [lindex $args 2] - switch [lindex $args 1] { - add {$self add $mess} - default {} - } - } -} - -def Macro add {mess} { - mset {event widget x y mode k kval} $mess - if {[regexp {^Control_} $k]} {return} - if {[regexp {^Alt_} $k]} {return} - if {[regexp {^Shift_} $k]} {return} - if {$event == "KeyRelease"} {return} - if {$event == "ButtonRelease"} {lappend @list [lreplace $mess 0 0 "Motion"]} - if {$event == "KeyPress" } {lappend @list [lreplace $mess 0 0 "Motion"]} - if {$event == "ButtonPress" } {lappend @list [lreplace $mess 0 0 "Motion"]} - lappend @list $mess -} - -def Macro test_playable {x y} { - mset {macro_width macro_height} [$self calc_size] - set c [string range [focus] 0 [string first . [focus] 1]+1] - set cwidth [winfo width $c]; set cheight [winfo height $c] - set cx1 [$c canvasx 0]; set cy1 [$c canvasy 0] - set cx2 [$c canvasx $cwidth]; set cy2 [$c canvasy $cheight] - set new_x [expr $x+$macro_width]; set new_y [expr $y+$macro_height] - $@rect flash $x $y $new_x $new_y blue - if {$new_x > $cx2 || $new_x < $cx1 || $new_y > $cy2 || $new_y < $cy1} { - puts "Can't playback Macro:: outside of canvas area" - return - } else {$self idx= 0; $self offset $x $y; $self play [$self delay]} - -} - -def Macro offset {new_x new_y} { - mset {event widget x y mode k kval} [lindex $@list 0] - set @offset_x [expr $new_x-$x] - set @offset_y [expr $new_y-$y] -} - -def Macro play {delay} { - if {$@idx == [llength $@list]} {return} - #$self test_canvas_size - set i 0 - set focus [string range [focus] 1 [string first . [focus] 2]-1] - set step [lindex $@list $@idx] - #puts "\t $step" - mset {event widget x y mode k kval} $step - switch $event { - #KeyRelease {set name [modekey $k $mode]} - KeyPress {set name [modekey $k $mode]} - ButtonPress {set name $event-$k} - ButtonRelease {set name $event-$k} - Motion {set name $event} - default {puts "Error: event $event should not have been here.."} - } - if {$@idx < [llength $@list]} { - #after $delay [list $self run $event $name $k [expr $X+$@offset_x] [expr $Y+$@offset_y] \ - # [expr $x+$@offset_x] [expr $y+$@offset_y]] - after $delay [list $self run $event $name $k $x $y] - } -} - -#this don't make sense when multiple window, and should be re implemeneted somehow -def Macro calc_size {} { - set x1 66666; set x2 0 - set y1 66666; set y2 0 - foreach step $@list { - mset {event widget x y mode k kval} $step - set x1 [min $X $x1]; set x2 [max $x2 $X] - set y1 [min $Y $y1]; set y2 [max $y2 $Y] - - } - return [list [expr $x2-$x1] [expr $y2-$y1]] -} - -def Macro test_canvas_size {} { - set c [string range [focus] 0 [string first . [focus] 1]+1] - set cwidth [winfo width $c]; set cheight [winfo height $c] - set cx1 [$c canvasx 0]; set cy1 [$c canvasy 0] - set cx2 [$c canvasx $cwidth]; set cy2 [$c canvasy $cheight] - mset {x1 y1 x2 y2} [$self calc_size] -} - -def Macro run {event name k x y} { - set w [focus] - incr @idx - event generate $w <$name> -x $x -y $y - if {$event=="KeyPress"} {event generate $w <KeyRelease-$k> -x $x -y $y} - $self play $@delay -} - -def Macro copy {} { - clipboard clear - selection clear - set i 0 - foreach step $@list { - if {$i == [expr [llength $@list]-1]} {set comma ""} else {set comma ","} - mset {event widget x y mode k kval} $step - set mess [list $event $x $y $mode $k] - set t ${mess}$comma - switch $event { - KeyPress {clipboard append [lreplace $t 0 0 "key"]} - ButtonPress {clipboard append [lreplace $t 0 0 "click"]} - ButtonRelease {clipboard append [lreplace $t 0 0 "unclick"]} - } - incr i - } - selection handle -selection PRIMARY [focus] "$self getdata" - selection own -command lost -selection PRIMARY -} - -def Macro getdata {offset maxchar} { - puts "clipboard ::: [clipboard get]" - return [string range [format %s [clipboard get]] $offset [expr {$offset+$maxChars}]] -} - -def Macro reset {} {set @idx 0} - -set ::macro [Macro new] -set ::macro_state 0 - -def Canvas macro_toggle {} {if {![$::macro state]} {set ::macro_state 1} {$::macro state= 0; $::macro dump}} -#def Canvas macro_play {} {puts ">> $@click_at <<"; $::macro idx= 0; $::macro play [$::macro delay]} -def Canvas macro_play {} { - mset {x y} $@click_at - $::macro reset - $::macro play [$::macro delay] - #$::macro test_playable $x $y -} -def Canvas keyevent {} { - focus [$self widget] - event generate [$self widget] <Control-Key-1> -} - -def Canvas macro_copy {} {$::macro copy} - -#-----------------------------------------------------------------------------------# -class_new TextBox {Box} - -def TextBox init {mess} { - super $mess - set @edit 0 - set @x1 [lindex $mess 2] - set @y1 [lindex $mess 3] - set @text [$self remove_braces [join [lrange $mess 4 end]]] - set @multi 0 - set @max_width 40 - # @textoffset is for offseting the text item/widget, ie, ObjectBox vs NumBox - switch [$self class] { - NumBox {set @textoffset [list 10 2]} - default {set @textoffset [list 2 2]} - } -} - -def TextBox text= {text} {set @text [$self remove_braces [join $text]]} -def TextBox text {} {return $@text} -def TextBox filter_text {{for_edit 0}} {return $@text} - -def TextBox draw {} { - if {[$self class] == "Canvas"} {if {$@text == "graph"} {$self update_size; super; return}} - # "TEXT" is the text label while "text" is the the input text field tk widget. - # the text should be drawn before, so that update_size works at the right time. - mset {x1 y1} [$self xy] - set z [$@canvas zoom] - if {$@edit} { - $self draw_edit - } else { - set fw [font measure [$self look font] 0] - set text [$self filter_text] - if {$::leet} {set text [string map -nocase {a 4 e 3 t 7 s 5 i 1 o 0 g 9} $text]} - $self item TEXT text [l+ $@textoffset [$self xy]] \ - -font [$self look font] -text $text \ - -fill [$self look fg] -anchor nw -width [expr ($fw*$@max_width)-1] - # set width with -1 because text item seem to be inclusive at wrap point - # where as the text widget is exclusive - } - $self update_size - super -} - -def TextBox edit {} { - if {$@edit} {return}; set @edit 1; $self changed edit - if {[[$self class] <= AtomBox]} {set @clear 1} -} - -def TextBox new_bind {} { - set t [$self cwidget].${self}text - bind $t <Key> "$self key_input %W %x %y %K %A 0" - bind $t <Control-Return> "$self key_input %W %x %y 10 %A 0" - bind $t <Control-v> "$self paste_resize" - bind $t <Return> "$self unedit" - bind $t <Escape> "$self unedit 0" - bind $t <Up> "$self scroll_history +1" - bind $t <Down> "$self scroll_history -1" - bind $t <Control-p> "$self scroll_history +1" - bind $t <Control-n> "$self scroll_history -1" - bind $t <Alt-BackSpace> "$self clear" -} - -def TextBox draw_edit {} { - set c [$self cwidget] - switch $::tcl_platform(os) { - Linux {$c configure -cursor crosshair} - #need to find equivalent names for other os - } - if {[lsearch [$@canvas selection] $self] < 0} {$@canvas selection+= $self} - set t $c.${self}text - if {[winfo exists $t]} {return} - set @edit 1 - set @tab_repeats 0 - obj_hist histi= 0 - set @selected? 1 - set z [$@canvas zoom] - set font_height [font metrics [$self look font] -linespace] - if {[$c bbox ${self}TEXT] != ""} { - mset {ix1 iy1 ix2 iy2} [lmap / [$c bbox ${self}TEXT] $z] - if {($iy2-$iy1)/$z > $font_height} {set @multi 1} - } else { - set ix1 0; set iy1 0 - set ix2 [font measure [$self look font] 0] - set iy2 [font metrics [$self look font] -linespace] - } - $c delete ${self}TEXT - set font_str [$self look font] - set new_size [format %.0f [expr [lindex $font_str 1]*$z]] - set font_str [lreplace $font_str 1 1 $new_size] - foreach char [split $@text ""] {lappend l [scan $char %c]} - mset {width height} [$self get_size [expr $ix2-$ix1] [expr $iy2-$iy1]] - set insertbg [$self look fg]; set fg [$self look fg] - if {[[$self class] <= AtomBox]} {set fg "red"; set insertbg [$self look bgedit]} - text $t -width $width -height $height -relief flat -bg [$self look bgedit] -borderwidth 0 \ - -highlightthickness 0 -font $font_str -fg $fg -insertbackground $insertbg -wrap word - $self new_bind - $@canvas focus= $self - $self item text window [l+ [lmap / $@textoffset $z] [$self xy]] -window $t -anchor nw -tags "${self}text $self text" - $t insert 1.0 $@text - $t configure -pady 0 -padx 0 - # dnd bindtarget $c.${self}text text/uri-list <Drop> {} - # tkdnd::drop_target register $c.${self}text - #set w .[$self get_canvas] - #tkdnd::drop_target register $w * - #bind $w <<Drop>> {post %s "Drop %e %W %X %Y %ST %TT %a %A %CST %CTT %t %T %b %D"} - #bind $w <<Drop:DND_Files>> {post %s "Drop:DND_Files %e %W %X %Y %ST %TT %a %A %CST %CTT %t %T %b %D"} - #bind $w <<DropEnter>> {post %s "DropEnter %e %W %X %Y %ST %TT %a %A %CST %CTT %t %T %b %D"} - #bind $w <<DropPosition>> {post %s "DropPosition %e %W %X %Y %ST %TT %a %A %CST %CTT %t %T %b %D"} - #bind $w <<DropLeave>> {post %s "DropLeave %e %W %X %Y %ST %TT %a %A %CST %CTT %t %T %b %D"} - - # "pd \"x[list ${self}] symbol \[ enquote %D \] ;\"" - $self resize - focus $t -} - -def TextBox resize {} { - if {[[$self class] <= AtomBox]} {return} - set c [$self cwidget] - set t $c.${self}text - #set z [$@canvas zoom] - set pix_height [$t count -update -ypixels 1.0 end] - set pix_width [font measure [$self look font] [$t get 1.0 end]] - mset {width height} [$self get_size $pix_width $pix_height] - $t configure -width [min $width $@max_width] -height $height -wrap word -} - -def TextBox get_size {w h} { - set c [$self cwidget] - set t $c.${self}text - set pix_height $h - set pix_width $w - set char_width [font measure [$self look font] 0] - set line_height [font metrics [$self look font] -linespace] - set round_chars [expr int(ceil($pix_width/$char_width.0))] - if {$round_chars < $@max_width && !$@multi} { - set round_lines 1 - } else { - set @multi 1 - set round_chars $@max_width - set round_lines [expr int(ceil($pix_height/$line_height))] - } - return [list $round_chars $round_lines] -} - -def TextBox key_input {widget x y key iso shift} { - after 0 "$self after_key $widget" - set c [$@canvas widget] - set t $c.${self}text - if {[[$self class] <= AtomBox]} {if {$@clear} {$t delete 1.0 1.end; set @clear 0}} - switch -- $key { - Tab { - if {[$self class] == "ObjectBox"} { - $self propose_completions; $widget configure -state disabled - } - } - 10 {$t configure -height [expr [lindex [$t configure -height] 4] + 1]} - } -} - -def TextBox after_key {widget} { - $widget configure -state normal; # for in case there is completion box - $self resize - $self changed -} - -def TextBox paste_resize {} { - if {[[$self class] <= AtomBox]} {return} - set c [$self cwidget] - set t $c.${self}text - set fixed [font metrics [$self look font] -fixed] - set text [clipboard get] - if {$fixed} { - set width [string length $text] - } else { - set textpix [font measure [$self look font] $text] - set fwidth [font measure [$self look font] 0] - set width [expr (($textpix+$fwidth-1)/$fwidth)+1] - } - set maxwidth 40 - mset {y1 y2} [$t yview] - if {$width < $maxwidth} {set height 1} {set height [expr ceil($width/$maxwidth.0)]} - $t configure -width [min $width $maxwidth] -height $height -wrap word - after 0 [list $t mark set insert 1.end] - $t mark set insert 1.0 - $self update_size - $self changed -} - -def TextBox scroll_history {incr} { - if {[[$self class] <= MessageBox]} {return} - set c [$self cwidget] - set t $c.${self}text - if {![obj_hist histi]} {obj_hist set_hist 0 [$t get 1.0 1.end]} - $t delete 1.0 1.end - set text [obj_hist traverse $incr] - $t insert 1.0 $text - $t configure -width [string length $text] - $self update_size - after 0 $self changed - -} - -def TextBox clear {} { - set c [$self cwidget] - set t $c.${self}text - $t delete 1.0 1.end -} - -def TextBox text {} {return $@text} - -def TextBox update_size {} { - if {[info exists @gop]} {if {$@gop} {mset [list @xs @ys] $@pixsize; return}} - if {$@canvas == ""} {puts "update_size: this textbox has no canvas, try again later"; return} - set c [$self cwidget] - set t_widget $c.${self}text - set t_item $c.${self}TEXT - set w2 0; set h2 0 - set xpad 2; set ypad 3 - set z [$@canvas zoom] - if {[winfo exists $t_widget]} { - set textwidth [expr ([winfo reqwidth $t_widget]+$xpad)/$z] - set height [expr ([winfo reqheight $t_widget]+$ypad)/$z] - } else { - mset {x1 y1 x2 y2} [[[$self canvas] widget] bbox ${self}TEXT] - set textwidth [expr ($x2-$x1+$xpad)/$z] - set height [expr ($y2-$y1+$ypad)/$z] - } - set iowidth [$self look iowidth] - set topwidth [expr {(2* $@ninlets-1)*$iowidth}] - set bottomwidth [expr {(2*$@noutlets-1)*$iowidth}] - set @xs [max [$self look minobjwidth] [max $bottomwidth [max $topwidth $textwidth]]] - set @ys $height -} - -#----------------------------------------------------------------------------------- - -class_new ObjectBox {TextBox} - -def ObjectBox init {mess} { - super $mess - set @valid 0 ;# only ObjectBox needs a @valid. (removed all others) - set @ninlets 0 - set @noutlets 0 - set @pdclass "" -} - -def ObjectBox valid= {v} {set @valid $v} -def ObjectBox valid {} {return $@valid} -def Canvas objectsel {} {return $@objectsel} -def Canvas wiresel {} {return $@wiresel} - -def ObjectBox draw_box {} { - super - set xya [$self bbox] - mset {x1 y1 x2 y2} $xya - # the 3d look could be done quicker using incr on x1 y1 x2 y2 like BlueBox does. - #set xyb [l+ [list $x2 $y1 $x1 $y1 $x1 $y2] [list -1 +1 +1 +1 +1 -1]] - #set xyc [l+ [list $x2 $y1 $x2 $y2 $x1 $y2] [list -1 +1 -1 -1 +1 -1]] - if {[$self selected?]} {set fg [$self look selectframe]} {set fg [$self look frame3]} - if {$@valid} { - $self item BASE rectangle $xya -fill [$self look bg] -outline $fg -width 1 - } else { - $self item BASE rectangle $xya -fill [$self look bg] -outline $fg -width 1 -dash {3 3} - } - #$self item BASE1 line $xyb -fill [$self look frame1] -width 1 - #$self item BASE2 line $xyc -fill [$self look frame2] -width 1 - #[$@canvas widget] lower ${self}BASE ${self}TEXT - [[$self get_canvas] widget] lower ${self}BASE ${self}TEXT - #[[$self get_canvas] widget] lower ${self}BASE -} - -def ObjectBox draw {} {super; $self draw_io} - -# this is called from the GUI; text= is reserved for server. -def TextBox setto {text} { - [$@canvas history] add [list $self setto $@text] - [$@canvas widget] configure -cursor {} - set @text $text - set l {} - foreach char [split $@text ""] {lappend l [scan $char %c]} - $@canvas selection-= [list $self] - switch [$@canvas action] { - insert {set goto [list $@canvas new_object_insert_wire]} - chain_obj {set goto [list $@canvas new_object_chain_wire]} - subpatcherize {set goto [list $@canvas new_object_subpatcherize_redraw]} - default {set goto [list $@canvas new_object_callback]} - } - netsend [concat [list .$@canvas text_setto $self] $l] $goto -} - -def TextBox unedit {{accept 1}} { - if {!$@edit} {return} - set @edit 0 - $self changed edit - set c [[$self get_canvas] widget] - set t $c.${self}text - if {$accept} {$self setto [$t get 1.0 "end - 1 chars"]} - after 1 "destroy $t" - if {[winfo exists .completion]} {$@action cancel} - focus $c - $@canvas focus= "" -} - -#-----------------------------------------------------------------------------------# -def Canvas name {} {return $@name} -def Canvas folder {} {return $@folder} -def Canvas name= {name} {if {!$@mapped} {return}; set @name $name ; $self update_title} -def Canvas folder= {folder} {if {!$@mapped} {return}; set @folder $folder; $self update_title} - -def Canvas make_title {} { - if {!$@mapped} {return} - if {$@subpatch} { - if {$@canvas == "" || 0==[string compare $@canvas $self]} { - set t "(uh)" - } else { - set t [$@canvas make_title] - } - set t "subpatch '$@name' of $t" - } else { - #set t "$@name in $@folder" - set t "$@name" - } - if {[$self modified?]} {append t "(*)"} - return $t -} - -def Canvas update_title {} { - if {[winfo exists .$self]} {wm title .$self [$self make_title]} -} - -# UNIMPLEMENTED: this should indicate whether the patch in pd is different from the last saved patch -def Canvas modified? {} {return 1} - -def Canvas mapped {} {return $@mapped} -def Canvas mapped= {v} {set @mapped $v} - -def Canvas havewindow= {flag} { - set was [winfo exists .$self] - if {$flag && !$was} {$self init_window; $self redraw} - #if {$flag && $was && [$self gop]} {$self redraw} - if {$flag && $was} {$self raise} - if {!$flag && $was} {$self delete_window} -} - -def Canvas visibles+= {child} { - if {[lsearch $@visibles $child] < 0} {lappend @visibles $child; $self changed visibles} -} -def Canvas visibles-= {child} { - if {[lsearch $@visibles $child] >= 0} {set @visibles [lwithout $@visibles $child]; $self changed visibles} -} - -def Canvas visibles {} {return $@visibles} - -def Canvas all_changed {} { - foreach x $@visibles { - if {[$x class] == "Canvas"} {if {$@gop} {$x all_changed}} - $x changed - } -} - -# this is a shim between the client's new-style indices and the server's remaining old-style indices -proc dex {h k} {lsearch [lsort -integer [$h keys]] $k} - -# for undo; calls the server -def Canvas ins {i constructor} { - set parts [pd_mess_split $constructor] - set last [lindex $parts end] - set parts [lrange $parts 0 end-1] - foreach part $parts {netsend $part} - netsend [concat [list .$self object_insert $i] $last] - $@history add [list $self del $i] -} - -def Canvas del {i} { - set o [$@objects get $i] - #this keynav should be better sorted out - if {$o == $@keynav_current || $o == $@keynav_last_obj} { - set @keynav_current 0 - set @keynav_last_obj 0 - } - # this "if" might not be necessary... try deconstruct_to for everything. - if {[$o class] != "Canvas"} { - $@history add [list $self ins $i [$o deconstruct]] - } else { - set meuh [Clipboard2 new] - $o deconstruct_to $meuh - $@history add [list $self ins $i [$meuh value]] - $meuh delete - } - netsend [list .$self object_delete $o] -} - -def Canvas wires {} {return $@wires} - -def Canvas delete_selection {} { - $@history atomically [list delete_selection] { - if {![$@objectsel size] && ![$@wiresel size]} {return} - #this keynav should be better sorted out - if {$@keynav} { - set @keynav 0 - switch [$@keynav_current class] { - Wire {set @keynav_last_wire 0} - default {set @keynav_last_obj 0} - } - set @keynav_current 0 - $@active hide - } - set del_wire {} - foreach obj [$@objectsel values] { - foreach wire [$obj wires2] { - if {[$@wires search $wire] != -1 && [lsearch $del_wire $wire] < 0} { - $self disconnect [$wire connects] - lappend del_wire $wire - } - } - $self del [$@objects search $obj] - } - foreach x [$@wiresel values] { - if {[$@wires search $x] != -1 && [lsearch $del_wire $x] < 0} { - $self disconnect [$x connects] - } - } - $@objectsel clear - $@wiresel clear - } -} - -def View position= {xy1} {mset [list @x1 @y1] $xy1; $self changed x1 y1} -def View set_orig_xy {x y} {set @orig_x $x; set @orig_y $y} - -def Canvas motion_wrap {x y f} { - set c [$self widget] - set x [expr [$c canvasx $x]/$@zoom] - set y [expr [$c canvasy $y]/$@zoom] - lappend @motion_queue [list $x $y $f] - #$self motion $x $y $f [$self identify_target $x $y $f] -} - -def Canvas motion_update {} { - if {[llength $@motion_queue]} { - mset {x y f} [lindex $@motion_queue end]; set @motion_queue {} - $self motion $x $y $f [$self identify_target $x $y $f] - } - set @motion_after_id [after 50 "$self motion_update"] -} - -def Canvas click_wrap {x y b f} { - set c [$self widget] - set x [expr [$c canvasx $x]/$@zoom] - set y [expr [$c canvasy $y]/$@zoom] - set f [expr 1<<($b+7)|$f] - $self click $x $y $f [$self identify_target $x $y $f] -} -def Canvas unclick_wrap {x y b f} { - set c [$self widget] - set x [expr [$c canvasx $x]/$@zoom] - set y [expr [$c canvasy $y]/$@zoom] - set f [expr 1<<($b+7)|$f] - $self unclick $x $y $f [$self identify_target $x $y $f] -} -def Canvas key_wrap {x y key iso shift} { - set c [$self widget] - $self key [expr [$c canvasx $x]/$@zoom] [expr [$c canvasy $y]/$@zoom] $key $iso $shift -} -def Canvas keyup_wrap {x y key iso shift} { - set c [$self widget] - $self keyup [expr [$c canvasx $x]/$@zoom] [expr [$c canvasy $y]/$@zoom] $key $iso $shift -} - -proc lsearch_minimum {l} { - set i 0 - set j 0 - set min [lindex $l 0] - foreach o $l { - if {$o < $min} {set i $j; set min $o} - incr j - } - return $i -} - -def Canvas quadrant {du dv array} { - if {$@keynav_current == 0} {set @keynav_current [$@objects get [lindex [$@objects keys] 0]]} - set foo {} - set bar {} - set pos [$@keynav_current xy] - foreach o $array { - mset {x y} [l- $pos [$o xy]] - set u [expr $x+$y] - set v [expr $x-$y] - if {$u*$du>0 && $v*$dv>0} {lappend foo $o; lappend bar [distance $pos [$o xy]]} - } - if {![llength $bar]} {return $@keynav_current} - set best [lindex $foo [lsearch_minimum $bar]] - return $best -} - -def Canvas motion {x y f target} { - #modes_callback $self "motion" $x $y $f $target - set c [$self widget] - $self motion_checkhairtip $target $x $y - eval $@dehighlight - set @dehighlight {} - set oldpos $@curpos - set @curpos [list $x $y] - # detects if the focus is not on the canvas itself in run mode, ie. numbox - if {!$@editmode & [$self focus] != $self & [$self focus] != ""} { - [$self focus] motion $x $y $f $target - } - mset {type id detail} $target - switch $@action { - edit {$self motion_edit $x $y $f} - insert {} - chain_obj {} - imove {$self motion_imove $oldpos $x $y; return} - mouse_copy {$self motion_move $oldpos $x $y; return} - move {$self motion_move $oldpos $x $y; return} - none {} - default {$@action motion $x $y $f $target} - } - if {$@editmode} {$self motion_iohilite2 $x $y $f} - if {$id == ""} {return} -} - -proc remainder {val val2} { - if {[expr {abs($val)}]} {return [expr {(abs($val)%$val2)*($val/abs($val))}]} else {return 0} -} - -def Canvas motion_move {oldpos x y} { - mset {ox oy} $oldpos - if {$@keynav} {$@active draw} - foreach obj [$@objectsel values] { - #if {[[$obj class] <= Box]} { - if {[$self look snap_grid]} { - set grid [$self look grid_size] - set ax [expr {(int($x)/$grid)*$grid}] - set ay [expr {(int($y)/$grid)*$grid}] - set oax [expr {(int($ox)/$grid)*$grid}] - set oay [expr {(int($oy)/$grid)*$grid}] - mset {x1 y1} [$obj xy] - if {![expr {($ax-$oax)%$grid}]} { - set xoff [remainder [expr {int($x1-$ax)}] $grid] - } else {set xoff 0} - if {![expr {($ay-$oay)%$grid}]} { - set yoff [remainder [expr {int($y1-$ay)}] $grid] - } else {set yoff 0} - $obj move [expr ($ax-$oax)-$xoff] [expr ($ay-$oay)-$yoff] - } else { - $obj move [expr {$x-$ox}] [expr {$y-$oy}] - } - #} else { - # puts "Canvas motion warning: trying to move non-Box explicitly" - #} - } -} - -def Canvas motion_imove {oldpos x y} { - mset {ox oy} $oldpos - if {$@keynav} {$@active draw} - if {[$@objectsel size] == 1} { - set obj [$@objectsel values] - set in_objs $obj - set out_objs $obj - } else { - if {![llength $@keynav_iosel_i] || ![llength $@keynav_iosel_o]} { - return - } else { - set obj [lindex $@keynav_iosel_i 0] - set in_objs $@keynav_iosel_i - set out_objs $@keynav_iosel_o - } - } - if {[[$obj class] <= Box]} { - if {[$obj class] == "Canvas"} { - if {[$obj gop]} {[$self widget] raise [list $obj [$obj visibles]]} - } else { - [$self widget] raise $obj - } - mset {type id detail} [$self identify_target $x $y 0] - if {$type == "wire"} { - mset {from outlet to inlet} [$id report] - $self disconnect [$id connects] - set from_idx [$@objects search $from] - set to_idx [$@objects search $to] - foreach obj $in_objs { - set obj3_idx [$@objects search $obj] - if {![llength [$obj ioselect]]} {set port 0} else {set port [lindex [$obj ioselect] 0]} - set w1 [list $from_idx $outlet $obj3_idx $port] - if {[$@wires search $w1]<0} {$self connect $w1} - } - foreach obj $out_objs { - set obj3_idx [$@objects search $obj] - if {![llength [$obj ioselect]]} {set port 0} else {set port [lindex [$obj ioselect] 0]} - set w2 [list $obj3_idx $port $to_idx $inlet] - if {[$@wires search $w2]<0} {$self connect $w2} - } - set @action move - } - foreach obj [$@objectsel values] {$obj move [expr $x-$ox] [expr $y-$oy]} - } else { - puts "Canvas motion warning: trying to move non-Box explicitly" - } -} - -def Canvas motion_edit {x y f} { - if {[distance [list $x $y] $@click_at] > 5} { - foreach obj [$@objectsel values] { - if {[[$obj class] <= Box]} { - $obj backupxy= [$obj xy] - } else { - puts "Canvas motion warning: trying to backup coordinates of non-Box" - } - } - if {$f == 9} {set @action imove} else {set @action move; $self motion_move $@click_at $x $y} - mset {ox oy} $@click_at - } -} - -def Canvas motion_checkhairtip {target x y} { - global tooltip - if {[$self look hairstate] && $@editmode} { - $@crosshair data= $x $y $target - $@crosshair draw - } else { - $@crosshair erase - } - if {[$self look tooltip]} { - if {$tooltip ne "" && ![$tooltip iserror] && [expr [distance [$tooltip curpos] [list $x $y]] > 10]} { - $tooltip delete - set tooltip "" - } - } -} - -def Canvas motion_iohilite2 {x y f} { - set c [$self widget] - set io [$self identify_closestio $x $y $f] - if {$io<0} {set @iohilite [list -1 0 0 0 0]; return} - foreach item {i o} { - set type_idx [string first $item $io] - set type [string index $io $type_idx] - set port [string range $io [expr $type_idx+1] end] - set object [string range $io 0 [expr $type_idx-1]] - if {$type_idx >= 0} {break} - } - mset {iox ioy} [lmap / [rect_centre [$c bbox $io]] $@zoom] - set @iohilite [list $object $iox $ioy $type $port] - $object hilite_io $type $iox $ioy - set @dehighlight [list $c delete ${io}b] -} - -def Canvas iohilite {} {return $@iohilite} - -def Canvas motion_iohilite {target x y} { - set c [$self widget] - mset {type id detail} $target - if {[llength $@keynav_iosel_i] || [llength $@keynav_iosel_o]} {return} - if {$@editmode && [$id canvas] == $self} { - switch $type { - inlet {set io i} - outlet {set io o} - default {return} - } - set port [$id hilite_io $io $x $y] - set @dehighlight [list $c delete ${id}$io${port}b] - } -} - -#-----------------------------------------------------------------------------------# -# returns one of those five things: -# object $id : the body of an object -# inlet $id $inlet : an inlet of an object -# outlet $id $outlet : an outlet of an object -# wire $id : a wire -# label $id : a label -# nothing : nothing -def Canvas identify_target {x y f} { - set c [$self widget] - set cx [expr $x*$@zoom] - set cy [expr $y*$@zoom] - set stack [$c find overlapping [expr $cx-2] [expr $cy-2] [expr $cx+2] [expr $cy+2]] - # reversing the stack is necessary for some things - # not reversing the stack is also necessary for some other things - # we have to figure out something. - set stack [lreverse $stack] - set target "" - foreach tag $stack {set target [$self target $x $y $f $tag]; if {[llength $target] > 1} {break}} - if {[llength $target] > 1} {return $target} {return [list "nothing"]} -} - -def Canvas target {x y f tag} { - set c [$self widget] - set cx [expr $x*$@zoom] - set cy [expr $y*$@zoom] - set tags [$c gettags $tag] - if {[regexp {^[xo][0-9a-f]{6,8}} $tags id]} { - # prior to Aug 15th, Wires had lower priority as all objects together - # now it's same priority, so just stacking order (and it's prolly wrong) - if {[$id classtags] == ""} {return [list "nothing"]} - set class [$id class] - if {[$self == $id]} {continue} - if {[$class <= Wire]} {if {$@action != "imove"} {return [list "wire" $id]}} - if {[$class <= Box]} { - if {$@action == "imove"} { - foreach tag [$self item_stack $x $y] { - set tags2 [$c gettags $tag] - if {[regexp {^[xo][0-9a-f]{6,8}} $tags2 id2]} { - set class [$id2 class] - if {[$class == Wire]} {return [list "wire" $id2]} - } - } - } - mset {x1 y1 x2 y2} [$id bbox] - if {[regexp {^x[0-9a-f]{6,8}LABEL} $tags label]} { - if {$x>$x1 && $x<$x2 && $y>$y1 && $y<$y2} { - return [list "object" $id] - } else { - return [list "label" $id] - } - } - set outs [$id noutlets] - set ins [$id ninlets] - if {$y>=$y2-6 && $outs} { - set val [expr int(($x-$x1)*$outs/($x2-$x1))] - if {$val==$outs} {incr val -1} - return [list "outlet" $id $val] - } - if {$y< $y1+2 && $ins} { - set val [expr int(($x-$x1)* $ins/($x2-$x1))] - if {$val== $ins} {incr val -1} - return [list "inlet" $id $val] - } - return [list "object" $id] - } - #puts "skipped a $class" - } -} - -def Canvas item_stack {x y} { - set c [$self widget] - set cx [expr {$x*$@zoom}] - set cy [expr {$y*$@zoom}] - set sense [$self pointer_sense] - set stack [$c find overlapping [expr {$cx-$sense}] [expr {$cy-$sense}]\ - [expr {$cx+$sense}] [expr {$cy+$sense}]] - set stack [lreverse $stack] - return $stack -} - -def Canvas identify_closestio {x y f} { - set c [$self widget] - set ios {} - set objs {} - foreach tag [$self item_stack $x $y] { - set tags [$c gettags $tag] - if {[regexp {^[x][0-9a-f]{6,8}[oi][0-9]{1,3}} $tags io]} { - foreach item {i o} { - set type_idx [string first $item $io] - set object [string range $io 0 [expr $type_idx-1]] - if {$type_idx >= 0} {break} - } - if {[$object canvas] == $self} {lappend ios $io} - } - } - if {![llength $ios]} {return -1} - set mindist 66666 - set idx 0; set i 0 - foreach io $ios { - set point2 [rect_centre [$c bbox $io]] - set point1 [list $x $y] - set dist [distance $point2 $point1] - if {$dist < $mindist} {set mindist $dist; set idx $i} - incr i - } - return [lindex $ios $idx] -} -def Canvas pointer_sense {} {return [$self look pointer_sense]} -def Canvas pointer_sense= {sense} { - set ::look(Canvas:pointer_sense) $sense - mset {x y} $@curpos - $@sense flash $x $y $sense "red" -} - -#-----------------------------------------------------------------------------------# -class_new StatusBar {View} ;# no, using View is wrong here. View is for tk canvas item collections. - -def StatusBar widget {} {return .$@canvas.stat} - -def StatusBar addw {a b text args} { - set f [$self widget] - if {$text!=""} { - eval [concat [list pack [label $f.${a}_l -text $text -font {helvetica -10} -pady 0] -side left] $args] - } - label $f.$a -width $b -font {helvetica -10} -background #cccccc -foreground black -anchor w -pady 0 - pack $f.$a -side left -} - -def StatusBar init {canvas} { - super - set @canvas $canvas - set f [$self widget] - frame $f -border 1 -relief ridge - $self addw px 4 "" - $self addw py 4 "" - $self addw what 28 " " -fill x -expand yes - $self addw action 12 " Action: " - $self addw sel 3 " Sel: " - $self addw focus 10 " Focus: " -} - -def Canvas statusbar_draw {x y} {$@statusbar draw $x $y} -def Canvas action {} {return $@action} -def Canvas action= {action} {set @action $action} -def Canvas zoom {} {return $@zoom} - -def StatusBar draw {x y} { - if {$x == "??"} {return} - set c [$@canvas widget] - set f [$self widget] - set zoom [$@canvas zoom] - set x [expr [$c canvasx $x]/$zoom] - set y [expr [$c canvasy $y]/$zoom] - set target [$@canvas identify_target $x $y -1] - mset {type id detail} $target - set t $target - switch -- $type { - object { - if {[info exists _($id:pdclass)]} {set class $_($id:pdclass)} {set class unknown} - append t " \[$class\]" - } - } - set action [$@canvas action] - if {[regexp ^o $action]} {set action [$action class]} - if {[string length [$@canvas focus]]} {set t "focus: [$@canvas focus]"} - $f.px configure -text [format "%4d" [expr round($x)]] - $f.py configure -text [format "%4d" [expr round($y)]] - if {$::debug} { - $f.what configure -text [$c gettags [lindex [$c find overlapping [expr $x-2] [expr $y-2] [expr $x+2] [expr $y+2]] end]] - } { - $f.what configure -text $t - } - $f.action configure -text $action - $f.sel configure -text [llength [$@canvas selection]] - $f.focus configure -text [$@canvas focus] -} - -#-----------------------------------------------------------------------------------# -class_new FindModel {Thing} - -def FindModel init {canvas} { - set @orig_canvas $canvas - set @find_string "" - set @next_canvases $canvas - set @last_canvas 0 - set @result "" - set @results {} - set @views {} - set @recursive 1 - set @info "" -} - -def FindModel reinit {} { - set @next_canvases $@orig_canvas - set @last_canvas 0 - set @result "" - set @results {} - $self remove_info -} -def FindModel remove_info {} { - foreach view $@views { - set f [$view widget] - destroy $f.info_l; destroy $f.info - } -} -def FindModel delete {} {foreach view $@views {destroy [$view widget]}; super} - -def FindModel find_string= {s} {set @find_string $s} -def FindModel find_string {} {return $@find_string} -def FindModel result= {s} { - $@orig_canvas deselect_all - $@orig_canvas selection= $s - set @result $s -} -def FindModel result {} {return $@result} -def FindModel views+ {view} {lappend @views $view} -def FindModel views {} {return $@views} -def FindModel end? {} {return $@end} -def FindModel end= {v} {set @end 0} - -def FindModel search_recursive {} { - if {![llength $@next_canvases]} {$self end; return} - if {[llength $@results]} {$self result= [lindex $@results 0]; set @results [lreplace $@results 0 0];return} - while {$@last_canvas < [llength $@next_canvases]} { - set canvas [lindex $@next_canvases $@last_canvas] - if {[$self cache_results $canvas]} { - if {![winfo exists [$canvas widget]]} {$canvas popup_open} else {focus [$canvas widget]} - $self result= [lindex $@results 0] - set @results [lreplace $@results 0 0] - incr @last_canvas - } else { - incr @last_canvas - $self search_recursive - } - return - } - set old_canvases $@next_canvases - set @next_canvases {} - if {$@recursive} { - foreach canvas $old_canvases {foreach x [$canvas get_childcanvas] {lappend @next_canvases $x}} - } else { - set @next_canvases {} - } - set @last_canvas 0 - $self search_recursive -} - -def FindModel end {} { - $self reinit - $@orig_canvas deselect_all - set @info " \"$@find_string\" not found" - foreach view $@views { - $view addw label "info" "info" - } -} - -def FindModel cache_results {canvas} { - set @results {} - foreach child [$@objects values] { - if {[string first $@find_string [$child text] 0] >= 0} { - lappend @results $child - } - } - if {[llength $@results]} {return 1} else {return 0} -} - -class_new FindView {FindModel} ;# no, using View is wrong here. View is for tk canvas item collections. -def FindView widget {} {return .$@canvas.find} -def FindView init {canvas} { - findmodel views+ $self - set @canvas $canvas - set @break 0 - set f [$self widget] - frame $f -border 1 -relief ridge - $self addw button "close" "" - $self addw text "find" "find" - $self addw checkbutton "recursive" "recursive" - if {[winfo exists .$@canvas.yscroll]} {set w .$@canvas.yscroll} else {set w .$@canvas.c} - pack $f -side bottom -fill x -before $w - set string [findmodel find_string] - if {$string != ""} {$f.find insert 0 $string} -} - -def FindView addw {type name label} { - set f [$self widget] - if {$label!=""} { - eval [concat [list pack [label $f.${label}_l -text ${label}: -font {helvetica -10} -pady 0] -side left]] - } - switch $type { - text { - entry $f.$name -width 10 -relief flat -bg white -borderwidth 0 -highlightthickness 0 - bind $f.$name <Escape> "findmodel delete" - bind $f.$name <Return> "$self find" - } - checkbutton { - checkbutton $f.$name - if {$name == "recursive"} {$f.$name configure -variable _(findmodel:recursive)} - } - button { - button $f.$name -border 1 -command "findmodel delete" -image icon_close -width 9 -height 9 - if {$name == "close"} {bind $f.$name <Return> "findmodel delete"} - } - label {label $f.$name -textvariable _(findmodel:info) -font {helvetica -10} -pady 0} - } - pack $f.$name -side left - bind $f.$name <Tab> "$self traversal %K %W forward" -} - -def FindView find {} { - set f [$self widget] - findmodel find_string= [$f.find get] - findmodel search_recursive - focus .$@canvas.c -} - -def FindView traversal {k w direction} { - set f [$self widget] - if {$w == "$f.recursive"} {set next $f.close} else {set next [tk_focusNext $w]} - focus $next -} - -def Canvas check_findbar {} { - if {[info exists ::_(findmodel:_class)] && ![winfo exists .$self.find.find]} {FindView new $self} -} - -def Canvas get_childcanvas {} { - set canvases {} - foreach child [$@objects values] {if {[$child class] == "Canvas"} {lappend canvases $child}} - return $canvases -} - -def Canvas runcommand {} {$@runcommand pack_prompt} - -class_new Runcommand {Listener} -def Runcommand canvas {} {return $@canvas} - -def Runcommand init {serf name command} { - set @history [History new 20] - set @serf ${serf}.run - set @command $command - set @expanded 0 - set @canvas [string trimleft $serf "."] - set @defs {} - set @completions {} - set @comp_i 0 - set @comp_s "666" - set @show_id 0 - $self defs - set f $@serf - frame $f -border 1 -relief ridge - button $f.close -border 1 -command "$self unpack_prompt" -image icon_close -width 9 -height 9 - bind $f.close <Return> "$self unpack_prompt" - pack $f.close -side left - bind $f.close <Tab> "$self traversal %K %W forward" - label $f.cmd_l -text Command: -font {helvetica -10} -pady 0 - pack $f.cmd_l -side left - entry $f.entry -width 30 -relief flat -bg white -borderwidth 0 -highlightthickness 0 - bind $f.entry <Escape> "$self unpack_prompt" - bind $f.entry <Control-g> "$self unpack_prompt" - bind $f.entry <Return> "$self eval" - bind $f.entry <Up> "$self scroll_history +1" - bind $f.entry <Down> "$self scroll_history -1" - bind $f.entry <Control-p> "$self scroll_history +1" - bind $f.entry <Control-n> "$self scroll_history -1" - bind $f.entry <Tab> "$self completion +" - switch $::tcl_platform(os) { - Linux {bind $f.entry <ISO_Left_Tab> "$self completion -"} - default {bind $f.entry <Shift-Tab> "$self completion -"} - } - pack $f.entry -side left -fill x -expand yes - bind $f.entry <Control-Tab> "$self traversal %K %W forward" -} - -def Runcommand pack_prompt {} { - set f $@serf - set @show_id [$@canvas show_id] - if {!$@show_id} {$@canvas show_id= 1} - if {[winfo exists .$@canvas.yscroll]} {set w .$@canvas.yscroll} else {set w .$@canvas.c} - pack $f -side bottom -fill x -before $w - focus $f.entry -} - -def Runcommand unpack_prompt {} { - if {!$@show_id} {$@canvas show_id= 0} - pack forget $@serf - focus [$@canvas widget] -} - -def Runcommand traversal {k w direction} { - set f $@serf - if {$w == "$f.entry"} {set next $f.close} else {set next [tk_focusNext $w]} - focus $next -} - -def Runcommand eval {} { - set f $@serf - if {[winfo exists $f.completion]} { - set l [string range $@comp 0 [expr [string first ":" $@comp 0]-1]] - $self replace $l - destroy $f.completion - return - } - #$self unpack_prompt - super - $self unpack_prompt -} - -def Runcommand defs {} { - set name [$@canvas class] - set len [string length ${name}_] - foreach def [$name methods] {lappend @defs $def} -} - -def Runcommand completion {which} { - set f $@serf - set text [$f.entry get] - if {$text != $@comp_s} { - set @comp_s $text - set @completions {} - set @comp_i 0 - foreach def $@defs {if {[regexp ^$@comp_s $def]} {lappend @completions $def}} - } - if {![llength $@completions]} return - set def [lindex $@completions $@comp_i] - set args [$@canvas args $def] - if {[lindex $args 0] == "self"} { - set args2 [lreplace $args 0 0] - } else { - set args2 $args - } - if {![llength $args2]} {set args2 "none"} - set @comp [join [list $def ":" $args2]] - if {$which == "+"} { - set @comp_i [expr ($@comp_i+1)%[llength $@completions]] - } else { - set @comp_i [expr $@comp_i-1] - if {$@comp_i<0} {set @comp_i [expr [llength $@completions]-1]} - } - if {![winfo exists $f.completion]} { - label $f.completion -textvariable _($self:comp) -pady 0 - pack $f.completion -side right - } -} - -def Thing args {def} { - set class [$self class] - set ancestors [$class ancestors] - set name ${class}_$def - set n 0 - foreach class $ancestors { - set name ${class}_$def - if {[info exists ::__args($name)]} {break} - } - return $::__args($name) -} - -def Canvas visible_rect {} { - set c [$self widget] - set height [winfo height $c] - set width [winfo width $c] - if {$width == 1 && $height == 1} {set height 300; set width 450} - mset {l r} [$c xview] - mset {t b} [$c yview] - if {$l == $r} {set l 0; set r 1} - if {$t == $b} {set t 0; set b 1} - set w [expr $width / ($r - $l)] - set h [expr $height / ($b - $t)] - mset {l2 r2} [lmap * [list $l $r] $w] - mset {t2 b2} [lmap * [list $t $b] $h] - return [list $l2 $t2 $r2 $b2] -} - -def Canvas clipboard_coords {offset} { - set in 0 - foreach mess [pd_mess_split [$::clipboard value]] { - set type [lindex $mess 1] - switch $type { - canvas {set in 1} "" {} connect {} - default { - if {$type == "restore"} {set in 0} - mset {x y} [lmap + [lrange $mess 2 3] $offset] - if {!$in} {lappend xcoords $x; lappend ycoords $y} - } - } - } - return [list $xcoords $ycoords] -} - -def Canvas paste_visible? {x1 y1 x2 y2 offset} { - set in 0 - foreach mess [pd_mess_split [$::clipboard value]] { - set type [lindex $mess 1] - switch $type { - canvas {set in 1} "" {} connect {} - default { - if {$type == "restore"} {set in 0} - mset {x y} [lmap + [lrange $mess 2 3] $offset] - if {!$in} { - if {$x > $x2 || $x < $x1} {return 0} - if {$y > $y2 || $y < $y1} {return 0} - } - } - } - } - return 1 -} - -def Canvas copy_times= {c} {set @copy_count $c} -def Canvas copy_times {} {return $@copy_count} - -def Canvas copy {} { - if {![$@objectsel size]} {return} - $clipboard value= "" - $self copy_times= 1 - array unset ::obj_index_sel $self:* - set j 0 - foreach i [lsort -integer [$@objectsel keys]] { - set child [$@objectsel get $i] - #set ::obj_index_sel($self:$child) [$@objectsel search $child] - set ::obj_index_sel($self:$child) $j; incr j - $child deconstruct_to $::clipboard - } - foreach wire [$@wiresel values] { - if {[array names ::obj_index_sel $self:[$wire from]] == ""} {continue} - if {[array names ::obj_index_sel $self:[$wire to ]] == ""} {continue} - $wire deconstruct_to $::clipboard $self - } -} - -def Canvas paste {} { - if {[$self look snap_grid]} {set offset [$self look grid_size]} {set offset 15} - $self do_paste [expr [$self copy_times] * $offset] - $self copy_times= [expr [$self copy_times] + 1] -} - -def Canvas do_paste {offset} { - set in 0 - $self deselect_all - netsend [list .$self "push"] - foreach mess [pd_mess_split [$::clipboard value]] { - set type [lindex $mess 1] - if {$type == "restore"} {incr in -1} - if {!$in} {set with [list $self new_object_copyselect]} else {set with ""} - switch $type { - "" {} - canvas {incr in; netsend $mess} - connect { - if {$with != ""} {set with [list $self new_wire_select]} - netsend $mess $with} - default {netsend [$self paste_coords $mess $offset] $with} - } - } - netsend [list #X pop 1] -} - -def Canvas paste_coords {mess offset} { - set x [lindex $mess 2]; set y [lindex $mess 3] - mset {vx1 vy1 vx2 vy2} [$self visible_rect] - mset {xcoords ycoords} [$self clipboard_coords $offset] - set visible [$self paste_visible? $vx1 $vy1 $vx2 $vy2 $offset] - set ref [lsearch $ycoords [lindex [lsort -real -increasing $ycoords] 0]] - if {!$visible} { - set xoff [expr ($vx2 - $vx1) * 0.25] - set yoff [expr ($vy2 - $vy1) * 0.25] - set x2 [expr [lindex $mess 2] - [lindex $xcoords $ref] + $vx1 + $xoff] - set y2 [expr [lindex $mess 3] - [lindex $ycoords $ref] + $vy1 + $yoff] - return [lreplace $mess 2 3 $x2 $y2] - } else { - puts "\t \t [expr $x+$offset] [expr $y+$offset] <<<<<" - return [lreplace $mess 2 3 [expr $x+$offset] [expr $y+$offset]] - } -} - -def Canvas cut {} { - $@history atomically [list cut] { - $self copy - $self delete_selection - } -} - -def Canvas duplicate {} { - if {[$self look snap_grid]} {set off [$self look grid_size]} {set off 15} - $self do_duplicate $off -} - -def Canvas do_duplicate {offset} { - global clipboard - set backup $clipboard - set clipboard [Clipboard2 new] - $self copy - $self do_paste $offset - $clipboard delete - set clipboard $backup -} - -def Canvas mouse_copy {} { - $self do_duplicate 0 -} - -def Canvas select_all {} { - $self editmode= 1 - eval [concat [list $@objectsel reinit] [$@objects list]] - eval [concat [list $@wiresel reinit] [ $@wires list]] -} -def Canvas deselect_all {} { - #$self editmode= 1 - $@objectsel clear - $@wiresel clear -} - -def Canvas popup_help {} {$::main class_browser} - -def Canvas popup_open {} { - #$self init_window - #set @mapped 1 - if {[winfo exists [$self widget]]} {raise .$self; return} - netsend [list .$self vis 1] - #$self init_window - #$self redraw -} - -def Canvas popup {id x y} { - set p .$self.popup - catch {destroy $p} - menu $p -tearoff false - if {$id == $self} { - $self populate_menu $p {popup_properties popup_help} - } elseif {[$id class] == "Wire"} { - $id populate_menu $p {popup_insert} - } else { - $id populate_menu $p {popup_properties popup_open popup_help - popup_clear_wires popup_remove_from_path popup_delete_from_path popup_copy_id} - } - tk_popup $p [expr $x-5] [expr $y-5] -} - -def View popup_copy_id {} { - clipboard clear - clipboard append $self -} - -def Canvas disconnect {wire} { - set @keynav_tab_sel "wire" - set id [$@wires get [$self wire_idx $wire]] - if {$id == $@keynav_current || $id == $@keynav_last_wire} { - set @keynav_current 0 - set @keynav_last_wire 0 - } - mset {from outlet to inlet} $wire - netsend [list .$self disconnect $from $outlet $to $inlet] - $@history add [list $self connect $wire] -} -def Canvas connect {wire {callback ""}} { - mset {from outlet to inlet} $wire - netsend [list .$self connect $from $outlet $to $inlet] $callback - $@history add [list $self disconnect $wire] -} - -def Canvas clear_wires_of {obj} { - if {![llength [$obj ioselect]]} { - set port 0; set type "none" - } else { - set port [lindex [$obj ioselect] 0] - set type [lindex [$obj ioselect] 1] - } - foreach wire [$obj wires2] { - mset {from outlet to inlet} [$wire report] - switch $type { - i {if { $to==$obj && $inlet==$port} {$self disconnect [$wire connects]; if { !$inlet} {lappend @auto_wire_from $from}}} - o {if {$from==$obj && $outlet==$port} {$self disconnect [$wire connects]; if {!$outlet} {lappend @auto_wire_to $to }}} - none { - $self disconnect [$wire connects] - if {$from==$obj && !$outlet} {lappend @auto_wire_to $to } - if { $to==$obj && ! $inlet} {lappend @auto_wire_from $from} - } - } - } -} - -def Canvas clear_wires {} { - set @auto_wire_to {}; set @auto_wire_from {} - if {[$@objectsel size] == 1} { - set objs [$@objectsel values] - } else { - if {![llength $@keynav_iosel_i] && ![llength $@keynav_iosel_o]} {return} - set objs [list $@keynav_iosel_i $@keynav_iosel_o] - } - foreach obj $objs {$self clear_wires_of $obj} -} - -def Canvas reconnect {} { - foreach from $@auto_wire_from { - set idx1 [$@objects search $from] - foreach to $@auto_wire_to { - set idx2 [$@objects search $to] - set wire [list $idx1 0 $idx2 0] - if {[$self wire_idx $wire] < 0} {$self connect $wire} - } - } -} - -def Canvas delete_obj_from_path {} {$self clear_wires; $self reconnect; $self delete_selection} -def Canvas remove_obj_from_path {} {$self clear_wires; $self reconnect} - -def Canvas wire_idx {connects} { - foreach {idx x} [$@wires list] { - if {[string compare [join $connects] [join [$x connects]]] == 0} {return $idx} - } - return -1 -} - -def Canvas reconnect_brkwires {type brk_quads obj} { - set k [$@objects search $obj] - foreach quad $brk_quads { - mset {from outlet to inlet} $quad - set orig_outlet $outlet; set orig_inlet $inlet - switch $type { - i {set orig_obj $to; set to $k; set inlet 0} - o {set orig_obj $from; set from $k; set outlet 0} - } - netsend [list .$self connect $from $outlet $to $inlet] - } - if {$type == "i"} { - netsend [list .$self connect $k 0 $orig_obj $orig_inlet] - } else { - netsend [list .$self connect $orig_obj $orig_outlet $k 0] - } - $self new_object_callback $obj - -} - -def Canvas expand_port {type idx port} { - set obj [$@objects get $idx] - mset {bx1 by1 bx2 by2} [$obj io_bbox $type $port] - mset {ox1 oy1 ox2 oy2} [$obj bbox] - mset ys [expr $oy2-$oy1] - mset {brk_wires brk_quads} [$self broken_wires $type $idx $port $self] - switch $type { - i {mset {nx ny} [$self xy_snap $bx1 [expr $by1-25]]} - o {mset {nx ny} [$self xy_snap $bx1 [expr $by1+$ys+25]]} - } - foreach quad $brk_quads {$self disconnect $quad} - set reply [list $self reconnect_brkwires $type $brk_quads] - netsend [concat [list .$self obj $nx $ny] t a] $reply - -} - -def Canvas outlet_expand {k outlet} {set reconnect [$self broken_wires o $k $inlet]} - -def Canvas implicit_wires {objs} { - set l {}; set h $@objects - foreach obj $objs { - set k [$h search $obj] - for {set i 0} {$i < [$obj ninlets]} {incr i} { - set ws [$self com_wires i $k $i]; if {[llength $ws]} {foreach w $ws {lappend l $w}} - } - for {set o 0} {$o < [$obj noutlets]} {incr o} { - set ws [$self com_wires o $k $o]; if {[llength $ws]} {foreach w $ws {lappend l $w}} - } - } - #return [lsort -integer -unique $l] - return [lsort -unique $l] -} - -def Canvas com_wires {type k port} { - set h $@objectsel; set obj [$@objects get $k]; set wires [$obj wires2]; set l {} - foreach wire $wires { - mset {f2 o2 t2 i2} [$wire connects] - if {$t2==$k && $i2==$port && $type=="i" && [$h exists $f2]} {lappend l $wire} - if {$f2==$k && $o2==$port && $type=="o" && [$h exists $t2]} {lappend l $wire} - } - return $l -} - -def Canvas broken_wires {type k port canvas} { - set shash [$canvas objectsel] - set obj [[$canvas objects] get $k] - set wires [$obj wires2]; set brk_wires {}; set quads {} - foreach wire $wires { - mset {f2 o2 t2 i2} [$wire connects] - if {$t2==$k && $i2==$port && $type=="i" && ![$shash exists $f2]} { - lappend brk_wires $wire; lappend quads [$wire connects] - } - if {$f2==$k && $o2==$port && $type=="o" && ![$shash exists $t2]} { - lappend brk_wires $wire; lappend quads [$wire connects] - } - } - return [list $brk_wires $quads] -} - - -def Canvas selection_center {} { - set x 0; set y 0 - foreach obj [$@objectsel values] { - mset {x1 y1} [$obj xy] - incr x $x1 - incr y $y1 - } - set n [$@objectsel size] - set x [expr $x / $n] - set y [expr $y / $n] - return [list $x $y] -} - -# translate the key/idx in $@objects to key/idx in $@objectsel -def Canvas idx_map {idx} { - set i 0; set obj [$@objects get $idx] - foreach sobj [$@objectsel values] {if {$obj == $sobj} {return $i}; incr i} - return -1 -} - -def Canvas subpatcherize_mkio {center iolist offset} { - mset {x y} $center; set inx 0; set outx 0 - for {set i 0} {$i < [llength $iolist]} {incr i} { - mset {type io port dsp} [lindex $iolist $i] - if {$type == "i"} { - if {$dsp} {set inlet "inlet~"} {set inlet "inlet"} - netsend [list #X obj [expr ($inx+1)*100] 0 $inlet] - netsend [list #X connect $offset 0 $io $port] - incr inx - } else { - if {$dsp} {set outlet "outlet~"} {set outlet "outlet"} - netsend [list #X obj [expr ($outx+1)*100] [expr $y*2] $outlet] - netsend [list #X connect $io $port $offset 0] - incr outx - } - incr offset - } -} - -def Canvas subpatcherize_iopos {orig io} { - set tab {}; set result {} - for {set x 0} {$x < [llength $orig]} {incr x} { - mset {from k1 io1 dsp} [lindex $orig $x]; mset {k2 io2} [lindex $io $x] - set obj1 [$@objects get $k1] - mset {x1 y1 x2 y2} [$obj1 io_bbox $from $io1]; set x1 [expr int($x1)] - lappend pos $x1; lappend tab [list $k1 $x1 [list $k2 $io2 $dsp]] - #lappend pos $x1; lappend tab [list $k1 $x1 [list $k2 $io2]] - } - set tab [lsort -index 1 -real $tab]; set foo "" - foreach item $tab {mset {k1 val foo2} $item; if {$foo2 != $foo} {lappend result $foo2}; set foo $foo2} - return $result -} - -def Canvas subpatcherize {} { - set center [$self selection_center] - set rewire_off [llength [$@objectsel values]] - set ins {}; set outs {}; set toins {}; set fromouts {}; set broken {}; set iolist {} - foreach obj [$@objectsel values] { - for {set i 0} {$i < [$obj ninlets]} {incr i} { - mset {brk_wires brk_quads} [$self broken_wires i [$@objects search $obj] $i $self] - if {[llength $brk_wires]} { - foreach wire $brk_quads { - set out_obj_name [[$@objects get [lindex $wire 0]] text] - if {[regexp {~} $out_obj_name]} {set dsp 1} {set dsp 0} - lappend broken [concat i $wire $dsp] - } - } - } - for {set o 0} {$o < [$obj noutlets]} {incr o} { - mset {brk_wires brk_quads} [$self broken_wires o [$@objects search $obj] $o $self] - if {[llength $brk_wires]} { - foreach wire $brk_quads { - set out_obj_name [[$@objects get [lindex $wire 0]] text] - if {[regexp {~} $out_obj_name]} {set dsp 1} {set dsp 0} - lappend broken [concat o $wire $dsp] - } - } - } - } - # $broken stores total number of broken connections, i= need [inlet] o = need [outlet] - foreach c $broken { - mset {type f o t i dsp} $c - if {$type == "i"} { - lappend ins [list $t $i]; lappend toins [list o $f $o $dsp] - } else { - lappend outs [list $f $o]; lappend fromouts [list i $t $i $dsp] - } - } - # figures out the inlet/outlet positioning and num of in/outlet to create - set ins [$self subpatcherize_iopos $toins $ins] - set outs [$self subpatcherize_iopos $fromouts $outs] - # iolist stores in/outlets to be conected inside the subpatch - foreach in $ins {mset {idx p dsp} $in; lappend iolist [list i [$self idx_map $idx] $p $dsp]} - foreach out $outs {mset {idx p dsp} $out; lappend iolist [list o [$self idx_map $idx] $p $dsp]} - puts "\t \t Cutting..............." - $self cut - puts "\t \t Push.................." - netsend [list .$self "push"] - netsend [list #N canvas 0 0 450 300 sub 0] [list $self subpatcherize_id] - puts "\t \t Push clipboard........" - foreach mess [pd_mess_split [$::clipboard value]] {netsend $mess} - - #creating in/outlets - $self subpatcherize_mkio $center $iolist $rewire_off - #netsend [list [concat #X restore $center pd sub]] - netsend [concat #X restore $center pd sub] - puts "\t \t Pop..................." - netsend [list .$self "pop"] [list $self subpatcherize_rewire $broken $ins $outs] -} - -def Canvas subpatcherize_id {id} {set @subpatcherize_id $id} - -def Canvas subpatcherize_rewire {wires inlist outlist bogus} { - set obj $@subpatcherize_id - foreach wire $wires { - mset {type f o t i dsp} $wire - if {$type == "i"} { - set idx [lsearch $inlist [list $t $i $dsp]] - $self connect [list $f $o [$@objects search $obj] $idx] - } else { - set idx [lsearch $outlist [list $f $o $dsp]] - $self connect [list [$@objects search $obj] $idx $t $i] - } - } -} - -def Canvas end_action {} { - switch -- $@action { - none {post "ending action 'none' makes no sense"} - default {$@action delete; set @action "none"} - } -} - -proc shift? {f} {return [expr $f&1]} -proc ctrl? {f} {return [expr $f&2]} -proc alt? {f} {return [expr $f&4]} -proc button_of {f} { -# set f [expr $f>>8] -# set b 1 -# while {[expr $f&1==0} {set f [expr $f>>1]} -# return $f - return [expr $f>>8] -} - -class_new FutureWire {View} -def FutureWire init {canvas x y f target} { - super - set @canvas $canvas - mset {type from port} $target - switch $type { - outlet {set @from $from; set @outlet $port; set @to "" ; set @inlet "" ; set port_name ${from}o${port}} - inlet {set @from "" ; set @outlet "" ; set @to $from; set @inlet $port; set port_name ${from}i${port}} - } - mset {x y} [lmap / [rect_centre [[$@canvas widget] bbox $port_name]] [$@canvas zoom]] - set @x1 $x - set @y1 $y - $self motion $@x1 $@y1 $f $target -} -def FutureWire motion {x y f target} { - set @x2 $x - set @y2 $y - mset [list type foo bar] $target - $self draw -} -def FutureWire unclick {x y f target} { - mset [list type foo bar] $target - mset {obj iox ioy io idx} [$@canvas iohilite] - if {$obj != -1} { - switch $io {i {set type "inlet"} o {set type "outlet"}} - set target [list $type $obj $idx] - } - switch $type { - outlet {mset [list type @from @outlet] $target} - inlet {mset [list type @to @inlet] $target} - default {} - } - set from_idx [[$@canvas objects] search $@from] - set to_idx [[$@canvas objects] search $@to] - if {$from_idx >= 0 && $to_idx >= 0 && $@from != $@to} { - $@canvas connect [list $from_idx $@outlet $to_idx $@inlet] - } - if {![shift? $f]} {$@canvas end_action} -} -def FutureWire draw {} { - $self item WIRE line [xys $@x1 $@y1 $@x2 $@y2] -dash {4 4 4 4} -fill [$self look dash] -smooth yes -} - -class_new GopRect {View} - -def GopRect init {canvas rect} { - set @canvas $canvas - set @rect $rect -} - -def GopRect draw {} { - $self item GOPRECT rectangle $@rect -outline [$self look fg] -} - -class_new SelRect {View} -def SelRect init {canvas x y bf target} { - super - set @x1 $x - set @y1 $y - set @canvas $canvas - $self motion $x $y 0 $target -} -def SelRect motion {x y f target} { - set @x2 $x - set @y2 $y - $self draw -} -def SelRect unclick {x y f target} { - $self motion $x $y 0 $target - set sel {} - set c [$@canvas widget] - mset {x1 y1 x2 y2} [lmap * [list $@x1 $@y1 $@x2 $@y2] [$@canvas zoom]] - set sel [$c find overlapping $x1 $y1 $x2 $y2] - set selrect_index [lsearch $sel [$c find withtag selrect]] - set sel [lreplace $sel $selrect_index $selrect_index] - if {[llength $sel]} { - set objects {} - #set wires {} - foreach tag $sel { - if {[regexp {^[xo]?[0-9a-f]{6,8}} [$c gettags $tag] id]} { - if {[$@canvas == $id]} {continue} - if {[[$id class] <= Box]} {lappend objects $id} - #elseif {[[$id class] <= Wire]} {lappend wires $id} - } - } - set objects [lsort -unique $objects] - #set wires [lsort -unique $wires] - set objects2 {} - #so that objects in gop won't get selected... - foreach obj $objects {if {[$obj canvas] == $@canvas} {lappend objects2 $obj}} - $@canvas selection+= $objects2 - #$@canvas selection_wire+= $wires - } - $@canvas selection_wire+= [$@canvas implicit_wires $objects] - set _($@canvas:keynav_tab_sel) "wire" - $@canvas end_action - -} -def SelRect draw {} { - $self item RECT line [list $@x1 $@y1 $@x2 $@y1 $@x2 $@y2 $@x1 $@y2 $@x1 $@y1] \ - -fill [$self look rect] -dash {3 3 3 3} -dashoffset 3 -} - -def Canvas click {x y f target} { - if {[winfo exists .completion]} { - raise .completion - focus .completion.comp - return - } - mset {type id detail} $target - set c [$self widget] - focus $c - set @click_at [list $x $y] - if {$f&8} {if {$id == ""} {set id $self}; $self right_click $id $x $y; return} - if {!$@editmode} {$self click_runmode $id $x $y $f $target; return} - set in_selection [expr [$@objectsel search $id]>=0] - switch $@action { - mouse_copy {$self move_selection} - } - switch $type { - outlet {} - inlet {} - object {$self click_on_object $id $f} - wire {$self click_on_wire $id $f $x $y} - nothing { - #$self deselect_all - if {[lindex $@iohilite 0] == -1} {$self click_on_nothing $f $target $x $y; return} - } - label {$self click_on_object $id $f} - default {error "BORK: $type"} - } - if {$@iohilite != "" && $type != "wire"} { - mset {obj iox ioy io idx} $@iohilite - if {$obj < 0} {return} - switch $io { - i {set type "inlet"} - o {set type "outlet"} - } - if {$@action == "none" && [$obj canvas] == $self} { - set @action [FutureWire new $self $iox $ioy $f [list $type $obj $idx]] - } - return - } -} - -def Canvas click_runmode {id x y f target} { - foreach obj [$self selection] {if {[[$obj class] <= AtomBox]} {$obj unedit}} - $self deselect_all - #if {$@focus != ""} {if {[[$@focus class] <= TextBox]} {$self selection-= $@focus;$@focus unedit}} - if {[llength $id]} { - if {[$id class] != "Canvas"} { - $id click $x $y $f $target - } else { - if {[$id subpatch]} { - if {![$id mapped]} {$id popup_open} elseif {![$id gop]} {raise .$id} - } - } - } -} - -def Canvas click_on_object {id f} { - set c [$self widget]; set text $c.${id}text - # so that if one clicks on the objectbox when editing the objectname, the focus won't get lost - if {[winfo exists $text]} {focus $text; return} - switch [expr $f&255] { - 0 { - if {[$self action] == "mouse_copy"} {$self action= "none"; return} - # if $id is the content of GOP - if {[$id canvas] != $self} { - set obj [$id get_parent_gop $self] - } else {set obj $id} - if {[$@objectsel search $obj] < 0 || [$@objectsel size] == 0} { - $self deselect_all - $self selection+= $obj - set @action edit - } else {set @action edit} - } - 1 { - if {[$@objectsel search $id] < 0} { - $self selection+= $id - } else { - $self selection-= $id - } - } - 2 { - if {![llength [$id wires2]]} {return} - $self deselect_all - $self selection+= $id - $self remove_obj_from_path - } - 3 { - if {[$id canvas] != $self} { - set obj [$id get_parent_gop $self] - } else {set obj $id} - if {![$@objectsel size]} {$self selection+= $obj} - if {[$@objectsel search $obj] < 0} { - $self deselect_all - $self selection+= $obj - } - $self action= "mouse_copy" - } - } -} -def Canvas click_on_wire {id f x y} { - set obj_selection [$self selection] - if {[llength $obj_selection]} {$self selection-= $obj_selection} - set @keynav_tab_sel "object" - switch [expr $f&255] { - 0 {$self selection_wire= $id} - 1 {$self selection_wire+= $id} - 2 { - set c [$self widget] - set wire [$id connects] - $self disconnect $wire - set from [$@objects get [lindex $wire 0]]; set outlet [lindex $wire 1] - set to [$@objects get [lindex $wire 2]]; set inlet [lindex $wire 3] - set opos [lmap / [rect_centre [$c bbox ${from}o${outlet}]] [$self zoom]] - set ipos [lmap / [rect_centre [$c bbox ${to}i${inlet}]] [$self zoom]] - set pos [list $x $y] - if {[distance $pos $opos] > [distance $pos $ipos]} { - mset {x1 y1} $ipos - set target [list outlet $from $outlet] - } else { - mset {x1 y1} $opos - set target [list inlet $to $inlet] - } - set @action [FutureWire new $self $x1 $y1 $f $target] - } - } -} - -def Canvas click_on_nothing {f target x y} { - # this cget check actually saves a full tk redraw - if {[[$self widget] cget -cursor] != {}} {[$self widget] configure -cursor {}} - if {$@focus != ""} {if {[[$@focus class] <= TextBox]} {$@focus unedit}} - if {$@action == "insert"} {return} - if {![expr $f&255]} { - $self deselect_all - #$self click_deselect_io - } - switch $@action { - edit {} - move {} - none {} - insert {} - chain_obj {} - imove {} - mouse_copy {} - default {$@action unclick $x $y $f $target} - } - set @action [SelRect new $self $x $y $f $target] -} - -def Canvas right_click {id x y} { - set c [$self widget] - set @insert_x $x; set @insert_y $y - if {$id != $self} {set id [$self gop_target $id]} - $self popup $id [winfo pointerx $c] [winfo pointery $c] -} - -def Canvas unclick {x y f target} { - set c [$self widget] - mset {type id detail} $target - if {$@editmode} { - switch $@action { - edit { - if {[$id canvas] != $self} { - set obj [$id get_parent_gop $self] - } else {set obj $id} - if {[$id class] == "Canvas"} {if {[$id text] == "graph"} {set @action none; return}} - set focus [$self focus] - if {$focus != ""} {if {[[$focus class] <= TextBox]} {$focus unedit}} - $obj edit; set @action none; $obj changed action - } - move {$self unclick_move} - none {} - insert {} - chain_obj {} - mouse_copy {$self mouse_copy} - imove {$self unclick_move} - default {$@action unclick $x $y $f $target} - } - } else {$self unclick_runmode $target $f $x $y} - $self adjust_scrollbars - #$self checkgeometry -} - -def Canvas unclick_move {} { - $self move_selection - set @action none -} - -def Canvas move_selection {} { - foreach obj [$@objectsel values] { - if {![[$obj class] <= Box]} { - puts "Canvas unclick warning: trying to move non-Box explicitly" - continue - } - mset {x1 y1} [$obj xy] - switch $@action { - mouse_copy {} - default {$obj position= [$obj backupxy]} - } - $obj moveto $x1 $y1 - if {[$obj edit?]} {focus [[$obj canvas] widget].${obj}text} - } - set objs [$@objectsel values] -} - -def Canvas unclick_runmode {target f x y} { - if {[$self focus] != ""} {[$self focus] unclick $x $y $f $target} - mset {type id detail} $target - if {$id != ""} { - if {[$id class] == "Array"} {$id unclick $x $y $f $target; return} - } -} - -def Canvas get_bbox {} {return $@bbox} - -if {$have_expand} { - def Canvas notice {origin args} {$self child_changed $origin {expand}$args} -} else { - def Canvas notice {origin args} {eval [concat [list $self child_changed $origin] $args]} -} - -def Canvas tab_jump {} { - if {![$@objects size]} {return} - set @keynav 1 - set olength [$@objectsel size] - set wlength [ $@wiresel size] - if {$@keynav_tab_sel == "object"} { - if {[$@wires size]} {set @keynav_tab_sel "wire"} - } else { - set @keynav_tab_sel "object" - } - switch $@keynav_tab_sel { - object {$self tab_jump_object} - wire {$self tab_jump_wire} - } -} - -def Canvas tab_jump_wire {} { - # if no selection done by the mouse - if {![$@wiresel size]} { - # see if the selected object has wire, if yes, use it - # if keynav_current is already a wire, do nothing - if {[$@keynav_current class] != "Wire"} { - #use the last key selected wire as start if there is one - if {$@keynav_last_wire != 0} { - $self deselect_all - set @keynav_current $@keynav_last_wire - } else { - if {[llength [$@keynav_current wires2]]} { - $self deselect_all - set @keynav_current [lindex [$@keynav_current wires2] 0] - set @keynav_last_wire $@keynav_current - } else { - # check if the canvas has wires, if yes, use it - if {[$@wires size]} { - $self deselect_all - set @keynav_current [lindex [$@wires values] 0] - set @keynav_last_wire $@keynav_current - } else {return} - - } - } - } - } - $self selection_wire= $@keynav_current -} - -def Canvas tab_jump_object {} { - set olength [$@objectsel size] - # if there is no selection done by mouse - if {!$olength} { - # if keynav_current is 0, aka the start of key navigation - if {$@keynav_current == 0} { - if {[$@objects size]} {set @keynav_current [lindex [$@objects values] 0]} else {return} - } else { - # if the keynav_current is a wire, set keynav_current to a object - if {[$@keynav_current class] == "Wire"} { - set @keynav_last $@keynav_current - $self deselect_all - # use the last key selected obj as the start if there is one - if {$@keynav_last_obj != 0} { - set @keynav_current $@keynav_last_obj - } else { - set @keynav_current [lindex [$@keynav_current report] 0] - set @keynav_last_obj $@keynav_current - } - } - } - } elseif {$olength == 1} { - set @keynav_current [lindex [$@objectsel values] 0] - $self deselect_all - } else { - $self deselect_all - set @keynav_current [$@objects get 0] - set @keynav_last_obj $@keynav_current - } - $self selection= $@keynav_current -} - -def Canvas key_nav_up {} {$self key_nav +1 -1 0} -def Canvas key_nav_down {} {$self key_nav -1 +1 0} -def Canvas key_nav_right {} {$self key_nav -1 -1 0} -def Canvas key_nav_left {} {$self key_nav +1 +1 0} -def Canvas key_nav_up_shift {} {$self key_nav +1 -1 1} -def Canvas key_nav_down_shift {} {$self key_nav -1 +1 1} -def Canvas key_nav_right_shift {} {$self key_nav -1 -1 1} -def Canvas key_nav_left_shift {} {$self key_nav +1 +1 1} - -def Canvas key_nav {du dv shift} { - if {$@keynav_shift && !$shift} {} - set @keynav_shift $shift - if {[$@objectsel size] > 1} { - if {[llength $@keynav_iosel_i] > 0 || [llength $@keynav_iosel_o] > 0} { - #$self deselect_all - } - } - if {!$@keynav} {$self tab_jump} - switch $@keynav_tab_sel { - object { - set @keynav_next [$self quadrant $du $dv [$@objects values]] - if {!$shift} { - $self selection-= $@keynav_current - $@keynav_current selected?= 0 - set @keynav_last_obj $@keynav_next - } - if {[$@objectsel search $@keynav_next] < 0} {$self selection+= $@keynav_next} - } - wire { - #$@keynav_current selected?= 0 - set @keynav_next [$self quadrant $du $dv [$@wires values]] - if {!$shift} { - $self selection_wire-= $@keynav_current - $@keynav_current selected?= 0 - set @keynav_last_wire $@keynav_next - } - if {[$@wiresel search $@keynav_next] < 0} {$self selection_wire+= $@keynav_next} - } - } - #$self selection+= $@keynav_next - set @keynav_current $@keynav_next -} - -def Canvas victim {} { - if {[$@objectsel size]} {return [$@objectsel values]} - if {[string compare $@keynav_current 0]} {return {}} - return $@keynav_current -} - -def Canvas key_nav_ioselect {} { - if {![$@objectsel size]} {return} - set var [lindex [$@objectsel values] end] - if {$@keynav_iosel != $var} {set @keynav_iocount 0} - if {$@keynav_port != 0 && $@keynav_iosel == $var} { - #set hilitebox $@keynav_port - foreach io $@keynav_port2 {[$self widget] delete ${io}b} - } - set obj [lindex [$@objectsel values] 0] - set ins [$obj ninlets] - set outs [$obj noutlets] - set ports {}; set ports2 {}; set ports3 {} - for {set i 0} {$i < $ins} {incr i} {lappend ports ${obj}i${i}; lappend ports2 "i"; lappend ports3 $i} - for {set i 0} {$i < $outs} {incr i} {lappend ports ${obj}o${i}; lappend ports2 "o"; lappend ports3 $i} - #incr @keynav_iocount - if {$@keynav_iocount >= [llength $ports]} {set @keynav_iocount 0} - set port [lindex $ports3 $@keynav_iocount] - set type [lindex $ports2 $@keynav_iocount] - set @keynav_port ${obj}${type}${port} - set @keynav_port2 {} - # @keynav_port stores the current hilited in/outlets - # @keynav_ports stores the current hilited in/outlets if there are multiple objects - # @keynav_iosel_i stores the selected inlets - # @keynav_iosel_o stores the selected outlets - foreach object [$@objectsel values] { - if {$@keynav_iosel != $var} {set @keynav_iosel $var} - switch $type { - i { - if {[lsearch $@keynav_iosel_i $object] == -1} { - lappend @keynav_iosel_i $object - set find [lsearch $@keynav_iosel_o $object] - if {$find >= 0} {set @keynav_iosel_o [lreplace $@keynav_iosel_o $find $find]} - } - } - o { - if {[lsearch $@keynav_iosel_o $object] == -1} { - lappend @keynav_iosel_o $object - set find [lsearch $@keynav_iosel_i $object] - if {$find >= 0} {set @keynav_iosel_i [lreplace $@keynav_iosel_i $find $find]} - } - } - } - mset {x y x1 y1} [[$self widget] bbox ${object}${type}${port}] - lappend @keynav_port2 ${object}${type}${port} - set _($object:ioselect) [list [lindex $ports3 $@keynav_iocount] [lindex $ports2 $@keynav_iocount]] - #set _($object:ioselect) [lindex $ports3 $@keynav_iocount] - $object hilite_io [lindex $ports2 $@keynav_iocount] [expr $x/$@zoom] [expr $y/$@zoom] - } - incr @keynav_iocount - -} - -def Canvas keyboard_mode {} { - post "loading keyboard-mode...." - if {[file exists kb-mode.tcl]} { - package require kb-mode - $@runcommand defs - if {![info exists @kbcursor]} {set @kbcursor [kb-mode_init $self]} - puts "cursor::: $@kbcursor" - } -} - -def Canvas keyboard_mode_exit {} { - post "exiting keyboard-mode...." - package forget kb-mode - remove_callback kb-mode - $@runcommand defs - $@kbcursor delete - read_ddrc - remove_callback "kb-mode" - unset @kbcursor -} - -def Canvas keyprefix {} { - if {!$@keyprefix} {set @keyprefix 1} else {set @keyprefix 0} -} - -def Canvas click_deselect_io {} { - if {[llength $@keynav_iosel_i] || [llength $@keynav_iosel_o]} { - if {!$@iosel_deselect} {set @iosel_deselect 1} else {$self dehilite_io; set @iosel_deselect 0} - } else { - $self dehilite_io - } -} - -def Canvas dehilite_io {} { - foreach io [concat $@keynav_iosel_i $@keynav_iosel_o] { - puts "$io is a [$io class]" - set box $_($io:ioselect) - set type [lindex $_($io:ioselect) 1] - set port [lindex $_($io:ioselect) 0] - set tag ${io}${type}${port} - [$self widget] delete ${tag}b - set _($io:ioselect) {} - } - set @keynav_iosel_i {} - set @keynav_iosel_o {} - set @keynav_port 0 - set @keynav_iocount 0 -} - -def Canvas incr_scale {} {$self scale out} -def Canvas decr_scale {} {$self scale in} - -def Canvas scale {mode} { - set s $::scale_amount - switch $mode { in { set s [expr 1/$s] }} - set sel [$@objectsel values] - if {![llength $sel]} {set sel [$@objects values]} - foreach child $sel { - mset {x y} [$child xy] - set x1 [expr $x*$s] - set y1 [expr $y*$s] - $child position= [list $x1 $y1] - netsend [list .$self object_moveto $child $x1 $y1] - } - foreach child $sel {$child changed_wires} -} - -def Canvas incr_zoom {} {$self zooming in} -def Canvas decr_zoom {} {$self zooming out} -def Canvas zooming {mode} { - global zoom bar - set spinbox .$self.bbar.scale - set val [string trimright [$spinbox get] %] - set i [lsearch $zoom(canned) $val] - set end [expr [llength $zoom(canned)] - 1] - switch -regexp $mode { - in|up {if {$i<$end} {incr i +1}} - out|down {if {$i>0} {incr i -1}} - } - set per [lindex $zoom(canned) $i] - $spinbox set $per% - set @zoom [expr $per/100.0] ;# @zoom must be float, not int - #$self propagate_zoom $@zoom - $self redraw - if {[$self look gridstate]} {if {$@editmode} {$@grid erase}} - foreach child [$@objects values] {if {[$child class] == "Canvas" && [$child gop]} {$child all_changed}} -} - -def Canvas propagate_zoom {zoom} { - foreach child [$@objects values] { - if {[$child class] == "Canvas"} { - set @zoom $zoom - $child propagate_zoom $zoom - } - } -} - -#-----------------------------------------------------------------------------------# -set lastcanvasconfigured "" -set lastcanvasconfiguration "" - -def Canvas checkgeometry {} { - set topname .$self - set boo [winfo geometry $topname.c] - set boo2 [wm geometry $topname] - global lastcanvasconfigured lastcanvasconfiguration - if {$topname != $lastcanvasconfigured || $boo != $lastcanvasconfiguration} { - set lastcanvasconfigured $topname - set lastcanvasconfiguration $boo - } -} -#-----------------------------------------------------------------------------------# -def Canvas selection_move {dx dy} { - $@history atomically [list move] { - $self selection_move2 $dx $dy - } -} -def Canvas selection_move2 {dx dy} { - if {![$self editmode]} {return} - foreach o [$@objectsel values] { - mset {x1 y1} [$o xy] - if {[[$o class] <= Box]} { - $o moveto [expr $x1+$dx] [expr $y1+$dy] - } else { - puts "selection_move: $o is not a Box, it's a [$o class]" - } - } -} - -def Canvas key {x y key iso shift} { - global tooltip; if {$tooltip ne ""} {$tooltip delete; set tooltip ""} - #if {[modes_callback $self "key" $x $y $key $iso $shift]} {return} - #if {[$self focus] != ""} {[$self focus] key $key $shift} - #if {$iso != ""} {scan $iso %c key} - #set focus [$self focus] - if {!$@editmode && [llength [$self selection]] == 1} { - set obj [$self selection] - if {[[$obj class] <= AtomBox]} { - if {[regexp {^[a-zA-Z0-9~/\._]{1}$} $key]} {$obj text= $key} {return} - $obj edit - $obj clear 0 - return - } - } - if {$shift} { - if {[$self look snap_grid]} {set motion [expr [$self look grid_size]*2]} {set motion 10} - } else { - if {[$self look snap_grid]} {set motion [$self look grid_size]} {set motion 1} - } - set n [$@objectsel size] - switch -regexp -- $key { - BackSpace|Delete|KP_Delete {$self delete_selection} - Up {if {$n} {$self arrow_key 0 -$motion} else {$self scroll y -$motion}} - Down {if {$n} {$self arrow_key 0 +$motion} else {$self scroll y +$motion}} - Left {if {$n} {$self arrow_key -$motion 0} else {$self scroll x -$motion}} - Right {if {$n} {$self arrow_key +$motion 0} else {$self scroll x +$motion}} - Tab {$self tab_jump} - Return {$self return_key $x $y $key $iso $shift} - F1 {$self deselect_all} - F2 {set @keynav 0; $@active hide} - default {} - } -} - -def Canvas return_key {x y key iso f} { - mset {type id detail} [$self identify_target $x $y $f] - if {![llength $@keynav_iosel_i] && ![llength $@keynav_iosel_o]} { - if {[$@objectsel size] == 1} { - mset {bx1 by1 bx2 by2} [[$self selection] bbox] - set x1 [expr ($bx1+$bx2)/2]; set y1 [expr ($by1+$by2)/2] - $self click_wrap $x1 $y1 1 $f - $self unclick_wrap $x1 $y1 1 $f - } - } else { - foreach out_obj $@keynav_iosel_o { - set from [$@objects search $out_obj] - set outlet [lindex $_($out_obj:ioselect) 0] - foreach in_obj $@keynav_iosel_i { - set to [$@objects search $in_obj] - set inlet [lindex $_($in_obj:ioselect) 0] - $self connect [list $from $outlet $to $inlet] - } - } - $self dehilite_io - } - -} - -def Canvas arrow_key {val1 val2} { - if {![$self editmode]} { - if {[$@objectsel size] == 1} { - set o [$@selection values] - if {[[$o class] <= IEMGUI] || [[$o class] == FloatBox]} {$o key_incr $val1 $val2} - } - } else {$self selection_move $val1 $val2} -} - -def Canvas clear_selection {} { - if {[$@objectsel size] > 0 || [$@wiresel size] > 0} { - $self deselect_all - $self dehilite_io - } - if {$@keynav} { - set @keynav 0 - #bogus switch so that keynav remains the same next time.. - if {$@keynav_tab_sel == "object"} {set @keynav_tab_sel "wire"} {set @keynav_tab_sel "object"} - } -} - -#-----------------------------------------------------------------------------------# -def Canvas keynav_current {} {return $@keynav_current} -def Canvas keynav_current= {current} { - set @keynav_current $current - switch [$current class] { - Wire {set @keynav_last_wire $current} - default {set @keynav_last_obj $current} - } -} -def Canvas keynav {} {return $@keynav} -def Canvas keyup {x y key iso shift} { - if {$iso != ""} {scan $iso %c key} - if {$::macro_state} {$::macro state= 1; set ::macro_state 0 } - $@active draw -} - -class_new Active {View} -def Active init {canvas} { - super - set @canvas $canvas - set @length 3 - set @length2 10 -} -def Active draw {} { - set current [$@canvas keynav_current] - if {$current == ""} {return} - if {![string compare $current 0]} {return} - set col [$self look selectframe] - if {[$@canvas keynav]} { - if {[$current class] == "Wire"} { - $self item_delete - set i 0 - foreach side {1.6 -1.6} { - mset {ax1 ay1 ax2 ay2} [$current bbox] - set t [expr atan2($ay2-$ay1, $ax2-$ax1)] - set cx1 [expr $ax1 + (($ax2-$ax1)* 0.15)] - set cy1 [expr $ay1 + (($ay2-$ay1)* 0.15)] - set cx2 [expr ($@length * cos($t+$side)) + $cx1] - set cy2 [expr ($@length * sin($t+$side)) + $cy1] - - for {set n 0} {$n < 2} {incr n} { - set angle [lindex {45 90 -45 -90} [expr $n+$i]] - mset {ax1 ay1 ax2 ay2} [$current bbox] - set t [expr atan2($ay2-$ay1, $ax2-$ax1)] - set bx1 [expr $ax1 + (($ax2-$ax1)* 0.15)] - set by1 [expr $ay1 + (($ay2-$ay1)* 0.15)] - set bx2 [expr ($@length2 * cos($t+$angle)) + $bx1] - set by2 [expr ($@length2 * sin($t+$angle)) + $by1] - set line [list $cx2 $cy2 $bx2 $by2] - $self item LINE$angle line $line -fill $col -width 2 - } - set i [expr $i+2] - } - } else { - $self item_delete - mset {x y} [lmap - [$current xy] 5] - set line1 [list $x $y $x [expr $y + $@length2]] - set line2 [list $x $y [expr $x + $@length2] $y] - $self item LINE1 line $line1 -fill $col -width 2 - $self item LINE2 line $line2 -fill $col -width 2 - - } - } else {$self hide} -} -def Active hide {} {$self item_delete} -def Active bbox {} { - set current [$@canvas keynav_current] - set l [$current xy] - concat $l $l ;# happy now?? -} - -def Canvas update_Active {item} {$self keynav_current= $item} - -#-----------------------------------------------------------------------------------# -class_new Box {View} - -def Box init {{mess {}}} { - super - # @wires2 stores the connections to and from a object - set @wires2 {} - $self reinit $mess -} - -def Box delete {} {if {$@canvas != ""} {[$@canvas objects] unset $@index}; super} - -def Box remove_braces {str} { - # this hack is to remove the "\" in the text - regsub -all {\\} $str "" text - return $text -} - -def Box reinit {mess} { - global classinfo fields - if {[$::macro state] && [llength $mess] > 4} {$::macro append_ref $mess} - if {![llength $mess]} {return} ;# what? - if {[lindex $mess 1] == "obj"} {set i 4} else {set i 1} - set @pdclass [lindex $mess $i] - if {[info exists fields($@pdclass)]} { - set i 0 - foreach f $fields($@pdclass) {set _($self:$f) [lindex $mess $i]; incr i} - } else { - set @text [$self remove_braces [join [lrange $mess 4 end]]] - } - $self outside_of_the_box -} - -def Box update_size {} {} - -# will be so that @wires are updated correctly without breaking encapsulation -def Box connect_out {} {} -def Box connect_in {} {} - -def Box draw {} { - $self draw_box - if {[$@canvas show_id]} {$self draw_id} {$self item_delete ID} - [[$self get_canvas] widget] raise $self - $self update_hilite_io -# if {[$self class] == "Canvas"} {$self restack} - if {[info exists @elapsed]} { - mset {x1 y1 x2 y2} [$self bbox] - $self item ELAPSED text [l+ {10 1} [list $x1 $y2]] -anchor nw -fill "#008800" \ - -text $@elapsed -font {{DejaVu Sans Mono} -8} - } -} - -def Box elapsed {f} { - set @elapsed $f - $self changed -} - -def Canvas get_elapsed {} {netsend [list .$self get_elapsed]} - -def Canvas show_id {} {return $@show_id} -def Canvas show_id= {val} {set @show_id $val; $self redraw} -def Canvas id_toggle {} {if {$@show_id} {set @show_id 0} {set @show_id 1}; $self redraw} - -def Box draw_id {} { - set id [$self index]: - mset {x y} [$self xy] - set fw [font measure [$self look font] 0] - if {[$@canvas editmode]} { - set col [complement [$@canvas look bgedit]] - } else {set col [complement [$@canvas look bgrun]]} - $self item ID text [list [expr $x-([string length $id]*$fw)] [expr $y+2]] \ - -font [$self look font] -text $id \ - -fill $col -anchor nw -} - -def Box draw_box {} {} -def Box edit {} {} -def Box unedit {} {} - -def Box bbox {} { - mset {x y} [$self xy] - set xs $@xs - set ys $@ys - list $x $y [expr {$x+$xs}] [expr {$y+$ys}] -} - -def Box io_bbox {type port} { - mset {x1 y1 x2 y2} [$self bbox] - set xs [expr {$x2-$x1}] - # method calls aren't as fast as we'd want them to be. - #set iowidth [$self look iowidth] - #set fy [$self look iopos] - set iowidth 7 - set fy -1 - switch $type { - o {set n $@noutlets; set y [expr {$y2+$fy }]} - i {set n $@ninlets; set y [expr {$y1-$fy-1}]} - } - set nplus [expr {$n==1 ? 1 : $n-1}] - set onset [expr {$x1+($xs-$iowidth)*$port/$nplus}] - set points [list $onset $y [expr {$onset+$iowidth}] $y] - return $points -} - - -def Box ioselect= {type port} {set @ioselect [list $type $port]} -def Box ioselect {} {return $@ioselect} - -def Box wires2 {} {return $@wires2} -def Box wires2+= {val} {if {[lsearch $@wires2 $val] < 0} {lappend @wires2 $val}} - -def Box changed_wires {} {foreach wire $@wires2 {$wire changed}} - -def Box delete_wire {wire} { - set find [lsearch $@wires2 $wire] - if {$find != -1} {set @wires2 [lreplace $@wires2 $find $find]} -} - -def Box move {dx dy} { - set @x1 [expr {$@x1+$dx}]; set @y1 [expr {$@y1+$dy}] - set zoom [$@canvas zoom] - $self changed ;# until we find a way to avoid rounding errors on [$@canvas widget] move. - $self changed_wires -} - -# temporary hack... only used during the moving of objects. -def Box backupxy= {xy} {set @backupxy $xy} -def Box backupxy {} {return $@backupxy} - -# the only one sending to the server. -# View position= is when getting position from server. -# View xy is virtual (for GOP) -def Box moveto {x1 y1} { - netsend [list .$@canvas object_moveto $self $x1 $y1] - [$@canvas history] add [list $self moveto $@x1 $@y1] - if {[$self class] == "Canvas"} { - if {[$self gop] && ![winfo exists .$self.c]} {foreach x $@visibles {$x changed}} - } - set @x1 $x1 - set @y1 $y1 - $self changed - $self draw_wires -} - -def Box draw_io2 {which n color} { - for {set i 0} {$i<$n} {incr i} { - set points [$self io_bbox $which $i] - $self item [list $which$i $which] rectangle $points -outline $color -fill $color -width 1 - [[$self get_canvas] widget] raise $self$which$i - } -} - -def Box draw_io {} { - $self draw_io2 i $@ninlets [$self look inletfg] - $self draw_io2 o $@noutlets [$self look outletfg] -} - -def Box tips= {tips} {set @tips $tips} - -def Box tip {type port} { - if {[info exists @tips]} { - set tips $@tips - } else { - netsend [list .$@canvas object_get_tips $self] - #after 500 $self tip $type $port - set tips "" - } - switch $type { - i {return "inlet $port: [lindex $tips $port]"} - o {return "outlet $port"} - } -} - -# type is i or o -def Box hilite_io {type x y} { - mset {x1 y1 x2 y2} [$self bbox] - set xs [expr $x2-$x1] - set c [$@canvas widget] - switch $type {i {set ports $@ninlets} o {set ports $@noutlets}} - set port -1 - set iowidth [$self look iowidth] - - for {set n 0} {$n<$ports} {incr n} { - set tag $self$type$n - set area [lmap / [$c bbox $self$type$n] [$@canvas zoom]] - set center [expr ([lindex $area 2] + [lindex $area 0]) / 2 ] - set dist [expr abs($x - $center)] - if {$dist < [expr ($iowidth/2)+5] && $dist > 0} {set port $n} - } - - if {$ports==0 | $port==-1} return - if {$port >= $ports} {set port [expr $ports-1]} - $self hilite_io_2 $type $port - if {[$self look tooltip]} {$@canvas show_tooltip $x $y [$self tip $type $port] $type} - return $port -} - -def Box update_hilite_io {} { - if {![llength $@ioselect]} {return} - set type [lindex $@ioselect 1] - set zoom [$@canvas zoom] - set port [lindex $@ioselect 0] - set p $type$port - $self hilite_io_2 $type $port -} - -def Box hilite_io_2 {type port} { - set outline [switch $type {i {concat [$self look outletfg]} o {concat [$self look inletfg]}}] - set box [l+ [$self io_bbox $type $port] [list -3 -3 +3 +3]] - $self item $type${port}b rectangle $box -outline $outline -width 1 -} - -#def Box popup_help {} {netsend [list pd help $@pdclass]} -def Box popup_help {} {netsend [list .$@canvas object_help $self]} - -def Box show_error {text} { - regsub "\n" $text "" text - #mset {x1 y1 x2 y2} [$self bbox] - #[$self get_canvas] show_tooltip [expr $x2+4] [expr ($y1+$y2)/2] $text object 1 - mset {x1 y1 x2 y2} [$self bbox] - mset {x y} [rect_centre [$self io_bbox i 0]] - [$self get_canvas] show_tooltip $x $y $text i 1 -} - -def Canvas macro_event_append {e obj} { - if {![llength $@macro_q]} {after $@macro_delay [list $self macro_schedule $@macro_delay] $obj} - lappend @macro_q $e -} - -def Canvas get_clipboard {obj} { - puts "get clipboard" - set content [clipboard get] - set l {}; set s ""; set space " "; - set last_newline [string last ";" $content] - #foreach char [split $content ""] {lappend l [scan $char %c]} - set i 0 - foreach char [split $content ""] { - if {$i == $last_newline} {break} - #if {$char == ";"} {set s ${s}${space}list} {set s ${s}$char} - if {$char != ";"} { - if {$char == "\n"} { - set s ${s}${space}$char - } else { - set s ${s}$char - } - } - incr i - } - netsend [concat [list .$obj clipboard_set] $s] -} - - -def Canvas macro_schedule {delay obj} { - if {[llength $@macro_q]} { - set w [focus] - set m [lindex $@macro_q 0] - set fudge 0 - mset {event x y mode k} $m - switch $event { - key {set name [modekey $k $mode]; set fudge 1} - click {set name [modeclick $k $mode ButtonPress]; set fudge 1} - unclick {set name [modeclick $k $mode ButtonRelease]; set fudge 1} - bang { - after $delay [list $self macro_schedule $@macro_delay] $obj - netsend [list .$obj mbang] - set @macro_q [lreplace $@macro_q 0 0] - return - } - default {puts "Error: this event $event should not have been here.."} - } - if {$fudge} {event generate $w <Motion> -x $x -y $y} - event generate $w <$name> -x $x -y $y - #puts "event generate $w <$name> -x $x -y $y" - if {$event=="key"} {event generate $w <KeyRelease-$k> -x $x -y $y} - set @macro_q [lreplace $@macro_q 0 0] - after $delay [list $self macro_schedule $@macro_delay] $obj - } -} - -def Canvas foobar {} {$self macro_schedule 1000} - -def Canvas macro_q {} {puts "$@macro_q"} -#-----------------------------------------------------------------------------------# -class_new Wire {View} - -def Wire canvas= {c} { - super $c - mset {from outlet to inlet} $@connects - set children [$c objects] - set @from [$children get $from] - set @to [$children get $to] - $@from wires2+= $self; $@to wires2+= $self -} - -def Box index= {i} {super $i; if {$@canvas != ""} {[$@canvas objects] set $i $self}} -def Wire index= {i} {super $i; [$@canvas wires] set $i $self } - -def Wire init {mess} { - super - $self reinit $mess -} - -def Wire reinit {mess} { - if {[$::macro state]} {$::macro append_ref $mess} - mset {x msg from outlet to inlet canvas} $mess - set @connects [list $from $outlet $to $inlet] - set @outlet $outlet - set @inlet $inlet - $self outside_of_the_box -} - -def Wire from {} {return $@from} -def Wire outlet {} {return $@outlet} -def Wire to {} {return $@to} -def Wire inlet {} {return $@inlet} -def Wire move {dx dy} {$self changed} - -# DON'T do the former, it's so horribly slow -#def View draw_wires {} {foreach wire $_($@canvas:wires) {$wire changed}} -def View draw_wires {} {foreach wire $@wires2 {$wire changed}} - -def Wire bbox {} { - set from $@from; set outlet $@outlet - set to $@to; set inlet $@inlet - set zoom [$@canvas zoom] - set c [$@canvas widget] - mset {x1 y1} [lmap / [rect_centre [$c bbox ${from}o${outlet}]] $zoom] - mset {x2 y2} [lmap / [rect_centre [$c bbox ${to}i${inlet} ]] $zoom] - list $x1 $y1 $x2 $y2 -} - -def Wire xy {} { - mset {x1 y1 x2 y2} [$self bbox] - list [expr $x1 + (($x2-$x1)*0.05)] [expr $y1 + (($y2-$y1)*0.05)] -} - -def Wire report {} {list $@from $@outlet $@to $@inlet} -def Wire connects {} {return $@connects} -proc xys {x1 y1 x2 y2} { - return [list $x1 $y1 $x2 $y2] ;# just a straight line, no frills - set r {} - lappend r $x1 $y1 - set dx [expr $x2-$x1] - set dy [expr $y2-$y1] - set d [expr sqrt($dx*$dx+$dy*$dy)] - set n [expr 1+$d/10] - for {set i 1} {$i<$n} {incr i} { - set w $i*($n-$i)/(0.0+$n*$n) - lappend r [expr $x1 + $dx*$i/$n + $dy*(rand()-0.5)*$w] - lappend r [expr $y1 + $dy*$i/$n - $dx*(rand()-0.5)*$w] - } - lappend r $x2 $y2 - return $r -} - -def Wire draw {} { - set zoom [$@canvas zoom] - set c [$@canvas widget] - set iowidth [$@from look iowidth] - mset {ox1 oy1 ox2 oy2} [$@from io_bbox o $@outlet] - mset {ix1 iy1 ix2 iy2} [ $@to io_bbox i $@inlet] - set x1 [expr ($ox1+$ox2)/2.0]; set y1 $oy2 - set x2 [expr ($ix1+$ix2)/2.0]; set y2 $iy1 - set xys [xys $x1 $y1 $x2 $y2] - set length [expr sqrt(pow($x2-$x1,2)+pow($y2-$y1,2))] - # how to customise the arrow size/shape? - set arrowsize [expr $length<100 ? $length/10 : 10] - if {$arrowsize < 5} {set arrow none} {set arrow last} - set arrowshape [list $arrowsize [expr $arrowsize*4/5] [expr $arrowsize/3]] - set wire_width [$self look thick] - set wire_color [$self look fg] - if {[$self selected?]} { - set wire_color [$self look fg2] ;# fg2 should be renamed - } else { - if {[info exists _($@from:text)] && [info exists _($@to:text)]} { - if {[regexp -nocase {~$} [lindex $_($@from:text) 0]] && \ - [regexp -nocase {~$} [lindex $_($@to:text) 0]]} { - set wire_width [expr $wire_width*2] - } - } - } - set options {} - if {[$self look wirearrow]} {lappend options -arrow $arrow -arrowshape $arrowshape} - eval [concat [list $self item WIRE line $xys -width $wire_width -smooth yes -fill $wire_color] $options] -} - -def Wire delete {} { - $self unsubscribe $@canvas - $@from delete_wire $self - $@to delete_wire $self - [$@canvas wires] unset $@index - super -} - -def Wire popup_insert {} { - if {![llength [$@canvas selection_wire]]} {$@canvas selection_wire= $self} - mset {x y} [$@canvas insertxy] - $@canvas do_insert_obj $x $y -} - -#-----------------------------------------------------------------------------------# -############ colouring - -# equivalent to color* #c0c0c0 $c -proc darker {c} { - scan $c #%02x%02x%02x r g b - set r [expr $r*3/4] - set g [expr $g*3/4] - set b [expr $b*3/4] - return [format #%02x%02x%02x $r $g $b] -} - -proc brighter {c} { - scan $c #%02x%02x%02x r g b - set r [min 255 [expr $r*4/3]] - set g [min 255 [expr $g*4/3]] - set b [min 255 [expr $b*4/3]] - return [format #%02x%02x%02x $r $g $b] -} - -proc randomise_color {c} { - scan $c #%02x%02x%02x r g b - set r [clip [expr $r+int(rand()*65)-32] 0 255] - set g [clip [expr $g+int(rand()*65)-32] 0 255] - set b [clip [expr $b+int(rand()*65)-32] 0 255] - return [format #%02x%02x%02x $r $g $b] -} - -proc parse_color {c} { - regsub {;$} $c {} c - if {$c<0} { - set c [expr ~$c] - set r [expr round((($c>>12)&63)*255/63)] - set g [expr round((($c>> 6)&63)*255/63)] - set b [expr round((($c>> 0)&63)*255/63)] - return [format #%02x%02x%02x $r $g $b] - } {return #[lindex $::preset_colours2 $c]} -} - -proc unparse_color {c} { - if {[string index $c 0]=="#"} {set c [string replace $c 0 0 0x]} - set r [expr round((($c>>16)&255)*63/255)] - set g [expr round((($c>> 8)&255)*63/255)] - set b [expr round((($c>> 0)&255)*63/255)] - return [expr ~0[format %02o%02o%02o $r $g $b]] -} - -############ data transfer -# note: @pdclass is the server-side class name -# and @_class is the client-side class name - -# abstract classes -set fields1 {foo bar x1 y1 class} -set fields2 {snd rcv lab ldx ldy fstyle fs bcol fcol lcol} - -# real classes -set fields(tgl) [eval list $fields1 w isa $fields2 on nonzero] -set fields(bng) [eval list $fields1 w hold break isa $fields2] -set fields(nbx) [eval list $fields1 w h min max is_log isa $fields2 val log_height] -set fields(hsl) [eval list $fields1 w h min max is_log isa $fields2 val steady] -set fields(hradio) [eval list $fields1 w change isa n $fields2 on] -set fields(vu) [eval list $fields1 w h rcv lab ldx ldy fstyle fs bcol lcol scale isa] -set fields(cnv) [eval list $fields1 hh w h snd rcv lab ldx ldy fstyle fs bcol lcol isa] -set fields(vsl) $fields(hsl) -set fields(vradio) $fields(hradio) -set fields(hdl) $fields(hradio) -set fields(vdl) $fields(hradio) -set fields(coords) {foo bar xfrom yfrom xto yto w h gop x1 y1} ;# goes with #N canvas -set fields(floatatom) {foo bar x1 y1 w min max pos lab rcv snd} -set fields(symbolatom) {foo bar x1 y1 w min max pos lab rcv snd} -set fields(array) {name n elemtype flags} - -proc classinfo {pdclass _class} { - global classinfo classinfo2 - set classinfo($pdclass) $_class - set classinfo2($_class) $pdclass -} - -# basic patchables -classinfo obj ObjectBox -classinfo message MessageBox -classinfo floatatom FloatBox -classinfo symbolatom SymbolBox -classinfo text Comment - -# non-patchables (scalars, arrays, ...) -classinfo array Array - -# GUI patchables -classinfo bng Bang -classinfo tgl Toggle -classinfo nbx NumBox -classinfo hsl Slider -classinfo vsl Slider -classinfo vu Vu -classinfo hradio Radio -classinfo vradio Radio -classinfo hdl Radio -classinfo vdl Radio -classinfo canvas Canvas -classinfo cnv Cnv -classinfo display Display - -# remember, _($foo:$bar) notation should die -# because objects ought to be autonomous. - -# in array objects, number of inlets is bogus? -#X array array1 1 float 3; -#A 0 0; - -def View index= {i} {set @index $i} -def View index {} {return $@index} - -proc change {self canvas index e {ninlets 0} {noutlets 0} {valid 1}} { - foreach mess [pd_mess_split $e] {change_2 $self $mess} - #the server ought to take care of this: - #if {[lindex $e 1] == "array"} {set ninlets 0; set noutlets 0} - if {$canvas != "x0"} {$self canvas= $canvas} - $self index= $index - $self ninlets= $ninlets - $self noutlets= $noutlets - if {[$self class] == "ObjectBox"} {$self valid= $valid} - if {[$self class] == "Canvas"} { - if {[$self subpatch]} {$self valid= $valid} - if {[$self gop]} {$self valid= $valid} - if {[$self abs]} {$self valid= $valid} - } - $self changed -} - -proc change_2 {self mess} { - set isnew [expr ![info exists ::_($self:_class)]] - switch -- [lindex $mess 0] { - "#N" {if {$isnew} {Canvas new_as $self $mess} else {$self reinit $mess}} - "#X" { - set i 1 - # would it be possible to merge floatatom,symbolatom as gatom ? - switch -- [lindex $mess 1] { - obj {set class [lindex $mess 4]} - msg {set class message} - default {set class [lindex $mess 1]}} - if {[info exists ::classinfo($class)]} { - set _class [lindex $::classinfo($class) 0] - } else { - if {[lindex $mess 1] == "connect"} { - set _class Wire - } else { - set _class ObjectBox - } - } - if {$isnew} {$_class new_as $self $mess} else {$self reinit $mess} - switch -- $class { - floatatom {set class gatom} - symbolatom {set class gatom} - array {$self length= [lindex $mess 3]; $self name= [lindex $mess 2]} - default {$self position= [lrange $mess 2 3]}} - $self pdclass= $class - } - "#A" { - #post "#A: $mess" - $self array_set [lrange $mess 2 end] - } - "#V" { - #post "#V: $mess" - } - default {if {$mess != ""} {error "what you say? «[lindex $mess 0]» in «$mess»"}} - } -} - -#proc pasting_count {self} { -# global paste _ -# if {$paste(count2) != $paste(count)} {incr paste(count2)} -#} - -# split at message boundaries and atom boundaries, returning a list of lists of atoms. -# spaces get temporary value \x01 -# A_SEMI gets temporary value \x02 -# backslash gets temporary value \x03 -# A_COMMA is not handled yet -proc pd_mess_split {s} { - set s [regsub -all {\\\\} $s "\x03"] - set s [regsub -all {(^|[^\\]);} $s "\\1\x02"] - set s [regsub -all {(^|[^\\])[\s\n]+} $s "\\1\x01"] - set s [regsub -all {^\n} $s "\x01"] ;# oops - set s [regsub -all {\\([\\; \{\}])} $s "\\1\\2"] - set s [regsub -all \x03 $s \\] - set r {} - foreach m [split $s \x02] { - set m [regsub -all "\x01+" $m "\x01"] - set m [regsub -all "^\x01" $m ""] - set t [split $m \x01] - lappend r $t - } - return $r -} - -proc canonical_list {list} { - set r {} - foreach e $list {lappend r $e} - return $r -} - -proc pd_mess_split_want== {a b} { - set b [canonical_list $b] - set c [pd_mess_split $a] - if {[string compare $c $b]} { - puts "[VTred]string «$a»\nparses to «$c»\ninstead of «$b»[VTgrey]" - } else { - puts "[VTgreen]string «$a» OK[VTgrey]" - } -} - -if 0 { - pd_mess_split_want== {foo;bar;baz;a\;;b\\;c\\\;;d\\\\;e} {foo bar baz {{a;}} {b\\} {{c\;}} {{d\\}} e} - pd_mess_split_want== {foo\ bar} {{{foo bar}}} - pd_mess_split_want== {foo \ bar\ foo\ bar foo} {{foo { } {bar foo bar} foo}} - pd_mess_split_want== {\\ \\\\ \\\\\\ \ \\\ \\\\\ one} [list [list "\\" "\\\\" "\\\\\\" "\ \\\ \\\\\ one"]] - pd_mess_split_want== "\n \n \n foo" foo - pd_mess_split_want== "\\\x7b\\\x7b\\\x7b\\\x7b" [list [list "\x7b\x7b\x7b\x7b"]] - pd_mess_split_want== "\\\x7d\\\x7d\\\x7d\\\x7d" [list [list "\x7d\x7d\x7d\x7d"]] - exit -} - -############ rendering - -class_new MessageBox {TextBox} - -def MessageBox init {mess} { - super $mess - set @w 15 ;# this is useless? - set @xs $@w - set @ys $@w ;# this is a bug -} - -def MessageBox draw_box {} { - mset {x1 y1} [$self xy] - set x2 [expr $x1+$@xs] - set y2 [expr $y1+$@ys] - set points [list $x1 $y1 [expr $x2+4] $y1 $x2 [expr $y1+4] $x2 [expr $y2-4] [expr $x2+4] $y2 $x1 $y2 $x2 $y2 $x1 $y2] - if {[$self selected?]} {set frcol [$self look selectframe]} {set frcol [$self look frame3]} - $self item BASE polygon $points -fill [$self look bg] -outline $frcol -width 1 - [$@canvas widget] lower ${self}BASE ${self}TEXT - [$@canvas widget] raise $self -} - -def MessageBox draw {} { - super - $self draw_io -} - -def MessageBox click {x y f target} { - $self bang 1 - netsend [list .$self bang] - after 150 $self bang 0 -} - -def MessageBox bang {flag} { - if {$flag} {set color #ffff00} {set color [$self look bg]} - [$@canvas widget] itemconfigure ${self}BASE -fill $color -} - -# it was class_new AtomBox {View Box}, which is wrong because already Box<View -# it shouldn't have mattered, but super doesn't support proper pruning yet -#class_new AtomBox {Box} -class_new AtomBox {Labelled TextBox} -def AtomBox label_xy {} { - mset {x1 y1} [$self xy] - switch -- $@pos { - 0 {list [expr {$x1-3}] [expr {$y1+2}]} - 1 {list [expr {$x1+2}] [expr {$y1+2}]} - 2 {list [expr {$x1-1}] [expr {$y1-1}]} - 3 {list [expr {$x1-1}] [expr {$y1+3}]} - } -} -def AtomBox label_anchor {} { - switch -- $@pos { - 0 {return ne} - 1 {return nw} - 2 {return sw} - 3 {return nw} - } -} -def AtomBox label_font {} {list Courier 10 bold} -def AtomBox label_color {} {return -1} - -def AtomBox draw_box {} { - $self update_size - mset {x1 y1 x2 y2} [$self bbox] - set points [list $x1 $y1 [expr $x2-4] $y1 $x2 [expr $y1+4] $x2 $y2 $x1 $y2] - if {[$self selected?]} {set frcol [$self look selectframe]} {set frcol [$self look frame3]} - $self item BASE polygon $points -fill [$self look bg] -outline $frcol - [[$self get_canvas] widget] lower ${self}BASE ${self}TEXT - $self draw_io -} - -def AtomBox clear {var} {set @clear $var} -def AtomBox clear= {} {return $@clear} - -def AtomBox filter_text {{for_edit 0}} { - if {$for_edit} {return ""} - if {[string length $@text] <= $@w} {return $@text} - return [string range $@text 0 [expr $@w-1]] -} - -def AtomBox update_size {} { - set width [font measure [$self look font] 0] - set ls [font metrics [$self look font] -linespace] - set @xs [expr ($width*$@w)+3] - set @ys [expr $ls+3] -} - -class_new Comment {TextBox} - -def Comment draw_box {} { - super - mset {x1 y1} [$self xy] - set x2 [expr $x1+$@xs] - set y2 [expr $y1+$@ys] - set xya [list $x1 $y1 $x2 $y2] - set xyb [l+ [list $x2 $y1 $x1 $y1 $x1 $y2] [list -1 +1 +1 +1 +1 -1]] - set xyc [l+ [list $x2 $y1 $x2 $y2 $x1 $y2] [list -1 +1 -1 -1 +1 -1]] - if {[$@canvas editmode]} { - if {[$self selected?]} {set frcol [$self look selectframe]} {set frcol [$self look frame3]} - $self item BASE rectangle $xya -fill [$self look bg] -outline $frcol - } else { - $self item_delete BASE - } - #$self item BASE1 line $xyb -fill [$self look frame1] - #$self item BASE2 line $xyc -fill [$self look frame2] - if {[$@canvas editmode]} { - [$@canvas widget] lower ${self}BASE ${self}TEXT - #[$@canvas widget] raise ${self}BASE1 ${self}BASE - #[$@canvas widget] raise ${self}BASE2 ${self}BASE - } -} - -class_new Display {Box} - -def Display height= {val} {set @height $val} - -def Display init {{mess {}}} { - set font [$self look font] - set fw [font measure $font 0] - set @max_width 40; #in chars - set @wrap [expr $fw*$@max_width]; #in pixels - set @content {display} - set @height 1 - set @xs [expr [font measure [$self look font] 0]+3] - set @ys [font metrics [$self look font] -linespace] - set @textoffset [list 2 2] - netsend [list .$self height] - super $mess -} - -def Display draw {} { - super - set font [$self look font] - mset {x y} [$self xy] - mset {xf yf} $@textoffset - set fh [font metrics [$self look font] -linespace] - set text [lindex $@content 0]; - for {set i 1} {$i < $@height} {incr i} {set text ${text}\n[lindex $@content $i]} - set h 0; set w 0 - foreach line $@content { - set tw [font measure $font $line] - set h [expr int(ceil($tw/$@wrap.0)+$h)] - set w [min [max $w $tw] $@wrap] - } - set h [max $h 1] - $self item BASE rect [list $x $y [expr $x+$w+$xf+2] [expr $y+($@ys*$h)+$yf+1]] -fill [$self look bg] - $self item TEXT text [l+ $@textoffset [$self xy]] -font $font -text $text -fill [$self look fg] -anchor nw -width $@wrap - $self draw_io -} - -def Display dis {text} { - lappend @content $text - if {[llength $@content] > $@height} {set @content [lrange $@content 1 end]} - $self changed -} - -class_new IEMGUI {} -def IEMGUI text {} { - return [$self class] -} -class_new BlueBox {Labelled IEMGUI Box} -#class_new BlueBox {Box Labelled} - -def BlueBox draw_box {} { - super - set xya [$self bbox] - mset {x1 y1 x2 y2} $xya - set color [parse_color $@bcol] - if {[$self selected?]} {set frcol [$self look selectframe]} {set frcol [$self look frame3]} - $self item BASE rectangle $xya -fill $color -outline $frcol - #below lines draws the 3d box edge - #incr x1 +1; incr y1 +1; incr x2 -1; incr y2 -1 - #$self item BASE2 line [list $x2 $y1 $x1 $y1 $x1 $y2] -fill #ffffff - #$self item BASE3 line [list $x2 $y1 $x2 $y2 $x1 $y2] -fill [darker $color] - $self draw_io -} - -def IEMGUI popup_properties {} {IEMPropertiesDialogue new $self} - -class_new PropertiesDialogue {Dialogue} - -def PropertiesDialogue init {of} { - super cancel apply ok - set @of $of - set f .$self - checkbutton $f.auto_apply -text [say auto_apply] -anchor w -variable @auto_apply - frame $f.buttonsep2 -height 2 -borderwidth 1 -relief sunken - pack $f.auto_apply $f.buttonsep2 -side bottom -fill x - bind $f <KeyPress-Return> "break";#so that Return don't call do_auto_apply after Dialogue ok - #bind $f <KeyPress> [list $self do_auto_apply] ;# too wide: may cause Ok/Cancel to spit errors - #bind $f <ButtonRelease> [list $self do_auto_apply] ;# too wide: may cause Ok/Cancel to spit errors - $self non_resizable -} -class_new IEMPropertiesDialogue {PropertiesDialogue} - -def IEMGUI properties_apply {list {orient -1}} { - set orig [list $self properties_apply] - foreach var [lrange $::fields($@class) 5 end] {lappend orig $@$var} - [$@canvas history] add $orig - foreach v $list {switch -- $v {{} {set v "empty"}}; lappend props $v} - netsend [concat [list .$self reload] $props] - if {$orient >= 0} { - netsend [list .$self orient $orient] - } -} - -def IEMPropertiesDialogue apply {} { - set class $_($@of:class) - set props {} - foreach var [lrange $::fields($class) 5 end] { - set v $@$var - if {[regexp -nocase {^[bfl]col$} $var]} {set v [unparse_color $v]} - lappend props $v - } - if {[[$@of class] <= Slider] || [[$@of class] <= Radio]} { - $@of properties_apply $props $@orient - } else { - $@of properties_apply $props - } -} - -def IEMPropertiesDialogue init {of} { - super $of - set @class $_($of:class) - wm title .$self "\[$@class\] [say popup_properties]" - if {![info exists ::fields($@class)]} {set class obj} - foreach var $::fields($@class) { - set val $_($of:$var) - switch -- $val { empty {set val ""}} - if {[regexp -nocase {^([a-z])col$} $var]} {set val [parse_color $val]} - set @$var $val - } - if {[[$of class] <= Slider] || [[$of class] <= Radio]} { - set @orient $_($of:orient) - $self add .$self [list orient choice -choices {horizontal vertical}] - } - foreach prop [lrange $::fields($@class) 5 end] { - set d [concat [list $prop] [switch $prop { - w {list integer -width 7} - h {list integer -width 7} - hold {list float -width 9} - break {list float -width 9} - min {list float -width 9} - max {list float -width 9} - is_log {list choice -choices {linear logarithmic}} - isa {list choice -choices {no yes}} - n {list integer -width 4} - steady {list choice -choices {steady_no steady_yes}} - snd {list entry -width 20} - rcv {list entry -width 20} - lab {list entry -width 20} - ldx {list integer -width 5} - ldy {list integer -width 5} - fstyle {list choice -choices {Courier Helvetica Times}} - fs {list fontsize -width 5} - bcol {list color} - fcol {list color} - lcol {list color} - val {continue} - on {continue} - change {list choice -choices {no yes}} - nonzero {list float -width 9} - log_height {list float -width 9} - hh {continue} - scale {list toggle} - default {error "huh? ($prop)"} - }]] - $self add .$self $d - } -} - -def IEMPropertiesDialogue dropmenu_open {f name} {super $f} -def IEMPropertiesDialogue dropmenu_set {frame var part val} { - switch $var { - orient {if {[$@of class] == "Slider"} {set tmp $@h; set @h $@w; set @w $tmp}} - default {} - } - set tmp ${var}choices - set textvar ${var}2 - set @$textvar [say [lindex $@$tmp $val]] - super $frame $var $part $val - $self do_auto_apply -} - -class_new CanvasPropertiesDialogue {PropertiesDialogue} - -def CanvasPropertiesDialogue init {of} { - super $of - set @canvas $of - wm title .$self "[say canvas] [say popup_properties]" - set @gop [$of gop] - set @properties [list "gop" "xfrom" "xto" "yfrom" "yto" "width" "height" "xmargin" "ymargin"] - set mess [$of get_mess] - mset [list @xfrom @yfrom @xto @yto @width @height @xmargin @ymargin] $mess - if {!$@width} {set @width 85}; if {!$@height} {set @height 60} - $self add .$self [list gop toggle -command "$self gop_setting"] - for {set i 1} {$i<[llength $@properties]} {incr i} { - $self add .$self [list [lindex $@properties $i] integer -width 7] - } - $self gop_setting -} - -def CanvasPropertiesDialogue gop_setting {} { - set entries [lrange $@properties 1 end] - foreach entry $entries { - if {!$@gop} { - .$self.$entry.entry configure -state disable - } else { - .$self.$entry.entry configure -state normal - } - } -} - -def CanvasPropertiesDialogue apply {} { - if {![$@canvas editmode]} {$@canvas editmode= 1} - netsend [list .$@of coords $@xfrom $@yfrom $@xto $@yto $@width $@height $@gop $@xmargin $@ymargin] -} - -proc gatom_escape {sym} { - if {[string length $sym] == 0} {return "-"} - if {[string equal -length 1 $sym "-"]} {return [string replace $sym 0 0 "--"]} - return $sym -} - -proc gatom_unescape {sym} { - if {[string equal -length 1 $sym "-"]} {return [string replace $sym 0 0 ""]} - return $sym -} - -class_new BoxPropertiesDialogue {PropertiesDialogue} -def Box popup_properties {} {BoxPropertiesDialogue new $self} -def Box popup_clear_wires {} {[$self canvas] selection= $self; [$self canvas] clear_wires} -def Box popup_remove_from_path {} {[$self canvas] selection= $self; [$self canvas] remove_obj_from_path} -def Box popup_delete_from_path {} {[$self canvas] selection= $self; [$self canvas] delete_obj_from_path} -def BoxPropertiesDialogue init {of} { - super $of - wm title .$self "Box Properties" - pack [label .$self.huh -text "huh..."] - pack [label .$self.huh2 -text "this is where some #V properties should go"] -} - -class_new WirePropertiesDialogue {PropertiesDialogue} -def Wire popup_properties {} {WirePropertiesDialogue new $self} -def WirePropertiesDialogue init {of} { - super $of - wm title .$self "Wire Properties" - pack [label .$self.huh -text "huh..."] - pack [label .$self.huh2 -text "this is where some #V properties should go"] -} - -class_new GAtomPropertiesDialogue {PropertiesDialogue} - -def AtomBox popup_properties {} {GAtomPropertiesDialogue new $self} - -# this is buggy due to miller's escapes vs iem's escapes. -def GAtomPropertiesDialogue apply {} { - netsend [list .$@of reload $@w $@min $@max $@pos [gatom_escape $@lab] [gatom_escape $@rcv] [gatom_escape $@snd]] -} - -def GAtomPropertiesDialogue init {of} { - super $of - foreach var {w min max pos} {set @$var $_($of:$var)} - foreach var {lab rcv snd} {set @$var [gatom_unescape $_($of:$var)]} - wm title .$self "Atom" - global properties - $self add .$self \ - {w integer -width 4} \ - {min float -width 8} \ - {max float -width 8} \ - {lab symbol -width 20} \ - {pos side } \ - {snd symbol -width 20} \ - {rcv symbol -width 20} - #foreach name {w min max} {bind .$self.$name.entry <KeyPress-Return> "$self ok"} - .$self.w.entry select from 0 - .$self.w.entry select adjust end - focus .$self.w.entry -} - -class_new GraphPropertiesDialogue {Dialogue} - -def GraphPropertiesDialogue apply {} { - netsend [list .$@of dialog $@x1 $@y1 $@x2 $@y2 $@xpix $@ypix] -} - -def GraphPropertiesDialogue init {of} { - super $of - foreach var {x1 y1 x2 y2 xpix ypix} {set @$var $_($of:$var)} - wm title .$self "Graph" - pack [label .$self.label -text "GRAPH BOUNDS"] -side top - global properties - $self add .$self { - {x1 integer -width 7} \ - {x2 integer -width 7} \ - {xpix entry -width 7} \ - {y2 integer -width 7} \ - {y1 integer -width 7} \ - {ypix entry -width 7} - } - #.$self.xrangef.x2 select from 0 - #.$self.xrangef.x2 select adjust end - #focus .$self.xrangef.x2 -} - -class_new ArrayPropertiesDialogue {Dialogue} - -def ArrayPropertiesDialogue apply {} { - regsub {^\$} $@name "#" name - netsend [list .$@apply arraydialog $name $@n $@saveit $@otherflag] -} - -def ArrayPropertiesDialogue init {of} { - super $of - foreach var {name n saveit} {set @$var $_($of:$var)} - set @otherflag 0 - wm title $id "[say array] [say popup_properties]" - $self add .$self {name entry} {n entry} - pack [checkbutton .$self.saveme -text "save contents" -variable @saveit -anchor w] -side top - if {$newone} { - pack [frame .$self.radio] -side top - foreach {i label} {0 "in new graph" 1 "in last graph"} { - pack [radiobutton .$self.radio.radio$i -value $i -variable @otherflag -text $label] -side top -anchor w - } - } else { - pack [checkbutton .$self.deleteme -text "delete me" -variable @otherflag -anchor w] -side top - } - if {$newone} {.$self.buttonframe.apply configure -state disabled} - bind .$self.name.entry <KeyPress-Return> "$self ok" - bind .$self.n.entry <KeyPress-Return> "$self ok" - .$self.name.entry select from 0 - .$self.name.entry select adjust end - focus .$self.name.entry -} - -class_new FloatBox {AtomBox} -class_new SymbolBox {AtomBox} - -def AtomBox init {mess} { - super $mess - set @clickpos {} - set width [font measure [$self look font] W] - set height [font metrics [$self look font] -linespace] - set @xs [expr ($width*$@w)+3] - set @ys [expr $height+3] -} - -def FloatBox init {mess} {super $mess; set @text 0;} - -def FloatBox calc {x y x1 y1} { - #puts "$@min $@max" - if {!$@min && !$@max} { - set d [expr $@ovalue+($y1-$y)*$@rate] - } else { - set span [expr $@max-$@min] - set l [expr $@max-$@min] - set d [clip [expr $@ovalue+(($y1-$y)*$span/($l+0.0))*$@rate] $@min $@max] - } - return $d -} - -def SymbolBox init {mess} {super $mess; set @text "symbol"} - -def AtomBox set {val} {set @text [format "%g" $val]; $self changed} - -def AtomBox setto {text} { - [$@canvas widget] configure -cursor {} - if { [string is double $text]} { - set @text $text; #so that the text gets updated immediately - netsend [list .$self float $text] - #[$self get_canvas] selection-= $self - } -} -def SymbolBox set {text} {set @text $text} -def SymbolBox setto {text} { - [$@canvas widget] configure -cursor {} - if {![string is double $text]} {netsend [list .$self symbol $text]} -} - -def FloatBox ftoa {} { - set f $@val - set is_exp 0 - if {[string length $@buf]>0} {return $@buf} - set buf [format %g $f] - set bufsize [string length buf] - if {$bufsize >= 5} { - # exponential mode - set is_exp [regexp -nocase e] - } - if {$bufsize > $@w} { - # must shrink number - if {$is_exp} { - #... - } { - #... - } - } - return $buf -} - -def AtomBox click {x y f target} { - set @clickx $x; set @clicky $y - set canvas [$self get_canvas] - set t [$canvas widget].${self}text - set @ovalue [clip $@text $@min $@max] - set @clickpos [list $x $y] - set @mouse [list $x $y] - $canvas focus= $self - set @rate [expr $f&1 ? 0.01 : 1.00] -} - -def AtomBox unclick {x y f target} { - if {$x == $@clickx && $y == $@clicky} {$self edit} - [$self get_canvas] focus= "" -} - -def AtomBox motion {x y f target} { - if {$@edit} {return} - mset {clx cly} $@clickpos - set @text [$self calc $x $y $clx $cly] - netsend [list .$self float [expr {0+$@text}]] -} - -def AtomBox log_ratio {} { - set diff [expr $@is_log ? log($@max/$@min) : ($@max-$@min)] - return [expr $diff / $@max] -} - -def AtomBox key_incr {val1 val2} { - set @text [expr $@text - $val2] - netsend [list .$self float [expr {0+$@text}]] -} - -def SymbolBox motion {x y f target} {} -class_new NumBox {Labelled IEMGUI AtomBox} - -def NumBox init {mess} { - super $mess - set @clicking 0 - set changed 0 - set @buf "" - set @text [clip 0 $@min $@max] -} -def NumBox calc {x y x1 y1} { - set span [expr $@max-$@min] - set l [expr $@is_log ? $@log_height : ($@max-$@min)] - set d [expr {($y1-$y)*$span/($l+0.0)}] - set d [expr $@is_log ? $@ovalue*exp($d*$@rate*[$self log_ratio]) : $@ovalue+$d*$@rate] - set d [clip $d $@min $@max] - return $d -} -def NumBox reinit {mess} { - super $mess - set @text $@val -} -def NumBox draw {} { - super - mset {x1 y1} [$self xy] - set xs [expr 4+10*$@w] - set ys $@h - set x2 [expr $x1+$xs] - set y2 [expr $y1+$ys] - set c [[$self get_canvas] widget] - set points [list $x1 $y1 [expr $x2-4] $y1 $x2 [expr $y1+4] $x2 $y2 $x1 $y2] - set xt [expr $x1+$ys/2+2] - set yt [expr $y1+$ys/2+1+$xs/34] - set points2 [list $x1 $y1 [expr $x1+$ys/2] [expr $y1+$ys/2] $x1 $y2] - set focused [$self == [$@canvas focus]] - if {$focused} {set color4 #00ff00} {set color4 [$self look bg]} - $self item BASE4 polygon $points2 -outline [$self look frame3] -fill $color4 - $c raise ${self}BASE4 -} -def NumBox ftoa {} { - set f $@text - set is_exp 0 - if {[string length $@buf]>0} {return $@buf} - set buf [format %g $f] - set bufsize [string length buf] - if {$bufsize >= 5} { - # exponential mode - set is_exp [regexp -nocase e] - } - if {$bufsize > $@w} { - # must shrink number - if {$is_exp} { - #... - } { - #... - } - } - return $buf -} -def NumBox unfocus {} {set @buf ""; $self changed} - -class_new Radio {BlueBox} -def Radio reinit {mess} { - super $mess - switch [lindex $mess 4] { - hradio {set @orient 0} hdl {set @orient 0} - vradio {set @orient 1} vdl {set @orient 1} - default {set @orient 0} - } -} -def Radio bbox {} { - mset {x1 y1} [$self xy] - set x2 [expr {$x1+$@w*($@orient ?1:$@n)}] - set y2 [expr {$y1+$@w*($@orient ?$@n:1)}] - list $x1 $y1 $x2 $y2 -} -def Radio draw {} { - mset {x1 y1 x2 y2} [$self bbox] - super - $self item_delete BUT ;# would be cool if this didn't delete stuff that we're about to redraw. - for {set i 0} {$i<$@n} {incr i} { - #set coords [list [expr {$x1+3}] [expr {$y1+3}] [expr {$x1+$@w-3}] [expr {$y1+$@w-3}]] - set coords [list $x1 $y1 [expr {$x1+$@w}] [expr {$y1+$@w}]] - $self item [list BUT$i BUT] rectangle $coords -fill [parse_color $@bcol] -outline [parse_color $@fcol] - if {$@orient} {set y1 [expr {$y1+$@w}]} {set x1 [expr {$x1+$@w}]} - } - $self set $@on -} -def Radio set {value} { - set c [$self get_canvas] - mset {x1 y1} [$self xy] - set value [expr round($value)] - if {$@orient} {set y1 [expr $y1+$@w*$value]} {set x1 [expr $x1+$@w*$value]} - set coords [list [expr {$x1+3}] [expr {$y1+3}] [expr {$x1+$@w-2}] [expr {$y1+$@w-2}]] - puts "coords=$coords" - $self item [list CHECK BUT] rectangle $coords -fill [parse_color $@fcol] -width 0 -} -def Radio click {x y f target} { - mset {x1 y1} [$self xy] - set i [expr {int($@orient ?$y-$y1-2:$x-$x1-2)/$@w}] - netsend [list .$self fout $i] -} -def Radio key_incr {val1 val2} {netsend [list .$self fout [expr {$@on-$val2}]]} - -# in sliders, @value is the kind of value that goes thru inlets and outlets -# whereas @val is always measured in "centipixels" (unzoomed). -class_new Slider {BlueBox} -def Slider reinit {mess} { - super $mess - switch [lindex $mess 4] { - hsl {set @orient 0} - vsl {set @orient 1} - } - $self update_value -} -def Slider update_value {} { - set span [expr {$@max-$@min}] - set l [expr $@orient ?$@h:$@w] - set @value [expr $@val*$span/($l-1)/100] - #set t [expr $@val * [$self slider_ratio] * 0.01] - #set @value [expr $@min*exp($t)] -} -def Slider init {mess} { - super $mess - set @oposition $@min - $self update_value -} -def Slider bbox {} { - mset {x1 y1} [$self xy] - if {!$@orient} { - list [expr {$x1-3}] $y1 [expr {$x1+$@w+2}] [expr {$y1+$@h}] - } else { - list $x1 [expr {$y1-2}] [expr {$x1+$@w}] [expr {$y1+$@h+3}] - } -} -#the value/centipixel ratio -def Slider slider_ratio {} { - set diff [expr $@is_log ? log($@max/$@min) : ($@max-$@min)] - return [expr $diff / ($@orient ? ($@h-1) : ($@w-1))] -} -def Slider draw_knob {} { - mset {x1 y1} [$self xy] - set l [expr $@orient ?$@h:$@w] - set span [expr {$@max-$@min}] - set scaled [expr {$@value*($l-1)/$span}] - if {$@orient} { - set y1 [expr $y1+2] - set y [expr $y1+$@h-$scaled-2] - set coords [list [expr {$x1+2}] [expr {$y-1}] [expr {$x1+$@w-2}] [expr {$y+1}]] - } else { - set x1 [expr $x1-1] - set x [expr $x1+$scaled] - set coords [list $x [expr {$y1+2}] [expr {$x+2}] [expr {$y1+$@h-2}]] - } - $self item KNOB rectangle $coords -outline red -fill [darker [$self look bg]] -} -def Slider draw {} { - mset {x1 y1 x2 y2} [$self bbox] - #if {$@orient} {set y1 [expr $y1-2]} {set x1 [expr $x1-2]} - #if {$@orient} {set ys [expr $@h+5]} {set xs [expr $@w+5]} - super - $self draw_knob - $self update_value -} -# not used -def Slider draw_notches {} { - if {$@orient} { - set thick [clip [expr $xs/3] 1 5] - set x3 [expr $x1+$xs-$thick/2-2] - set eighth [expr round($ys/8-1)] - set coords [list $x3 $y1 $x3 [expr $y1+$ys]] - } else { - set thick [clip [expr $ys/3] 1 5] - set y3 [expr $y1+$ys-$thick/2-2] - set eighth [expr $xs/8] - set coords [list $x1 $y3 [expr $x1+$xs] $y3] - } - # there were supposed to be 7 notches... i don't remember what happened here. - $@canvas item NOTCH $coords -dash [list 1 $eighth 1 $eighth] -width $thick -fill [darker [$self look bg]] -} -def Slider click {x y f target} { - set canvas [$self get_canvas] - mset {type id detail} [$canvas identify_target $x $y $f] - if {$type == "label"} {return} - $canvas focus= $self - set @click_at [list $x $y] - set @rate [expr $f&1 ? 0.01 : 1.00] - if {!$@steady} { - mset {x1 y1 x2 y2} [$self bbox] - set t [expr [$self calc $x $y $x1 $y2]*$@rate] - set @value [expr $@is_log ? [expr $@min*exp($t*[$self slider_ratio])] : $t] - set @oposition $t - netsend [list .$self float $@value] - } else {set @oposition $@value} -} -def Slider unclick {x y f target} { - ### keep focus if only clicked. do we want that feature? - # if {[distance $@click_at [list $x $y]] == 0} {return} - set canvas [$self get_canvas] - $canvas focus= "" -} -def Slider motion {x y f target} { - set canvas [$self get_canvas] - set focused [$self == [$canvas focus]] - if {!$focused} {return} - mset {clx cly} $@click_at - set d [$self calc $x $y $clx $cly] - set t ($@oposition+$d*$@rate) - set value [expr $@is_log ? [expr $@min*exp($t*[$self slider_ratio])] : $t] - set out [clip $value $@min $@max] - netsend [list .$self float $out] -} -def Slider key_incr {val1 val2} { - set @value [expr {$@value-$val2}] - netsend [list .$self float $@value] -} -def Slider calc {x y x1 y1} { - set span [expr {$@max-$@min}] - set l [expr {$@orient ?$@h:$@w}] - set d [expr {($@orient ?$y1-$y:$x-$x1)*$span/($l+0.0)}] - return $d -} -def Slider unfocus {} {$self draw} - -class_new Labelled {} -def Labelled draw {} { - super - mset {lx ly} [$self label_xy] - set label $@lab; switch -- $label {empty {set label ""} - {set label ""}} - set lfont [$self label_font] - set lcolor [parse_color [$self label_color]] - if {$::leet} { - set text [string map -nocase {a 4 e 3 t 7 s 5 i 1 o 0 g 9} $label] - } else { - set text $label - } - $self item LABEL text [list $lx $ly] -text $text -anchor [$self label_anchor] -font $lfont -fill $lcolor -} -def Labelled label_xy {} {mset {x1 y1} [$self xy]; list [expr {$x1+$@ldx}] [expr {$y1+$@ldy}]} -def Labelled label_anchor {} {return w} -def Labelled label_font {} {list [lindex {courier helvetica times} $@fstyle] $@fs bold} -def Labelled label_color {} {return $@lcol} - -#-----------------------------------------------------------------------------------# -class_new Bang {BlueBox} -def Bang init {mess} { - super $mess - set @flash 0 - set @count 0 -} -def Bang bbox {} { - mset {x1 y1} [$self xy] - list $x1 $y1 [expr {$x1+$@w}] [expr {$y1+$@w}] -} -def Bang draw {} { - super - mset {x1 y1 x2 y2} [$self bbox] - set rect [list [expr {$x1+1}] [expr {$y1+1}] [expr {$x2-1}] [expr {$y2-1}]] - if {$@flash} { - #$self item BUT oval $rect -fill [parse_color $@fcol] - set fcol [] - set bcol [] - $self item BUT oval $rect -fill $fcol - after 100 [list $self item BUT oval $rect -fill $bcol] - set @flash 0 - } else { - set colour [parse_color $@bcol] - $self item BUT oval $rect -fill $colour -outline [$self look frame3] - } -} -def Bang unclick {x y f target} {} -def Bang click {x y f target} {netsend [list .$self bang]} -def Bang bang {count} {set @count $count; set @flash 1} -def Bang key_incr {val1 val2} {netsend [list .$self bang]} - -class_new Toggle {BlueBox} -def Toggle bbox {} { - mset {x1 y1} [$self xy] - list $x1 $y1 [expr $x1+$@w] [expr $y1+$@w] -} -def Toggle draw {} { - super - mset {x1 y1 x2 y2} [$self bbox] - set colour [parse_color $@bcol] - set t [expr {int(($@w+29)/30)}] - set fill $colour - set x3 [expr {$x1+$t+2}]; set y3 [expr {$y1+$t+2}] - set x4 [expr {$x2-$t-2}]; set y4 [expr {$y2-$t-2}] - if {$@on} { - set fill [parse_color $@fcol] - } { - set fill [parse_color $@bcol] - } - $self item X1 line [list $x3 $y3 [expr {$x4+1}] [expr {$y4+1}]] -width $t -fill $fill - $self item X2 line [list $x3 $y4 [expr {$x4+1}] [expr {$y3-1}]] -width $t -fill $fill -} -def Toggle unclick {x y f target} {} -def Toggle click {x y f target} { - if {!$@on} {set @on 1} {set @on 0} - netsend [list .$self float $@on] - $self changed -} - -class_new Vu {Labelled IEMGUI Box} -set vu_col { - 0 17 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 - 15 15 15 15 15 15 15 15 15 15 14 14 13 13 13 13 13 13 13 13 13 13 13 19 19 19 -} -def Vu init {mess} { - super $mess - set @value 0 - set @peak 0 -} -def Vu bbox {} { - mset {x1 y1} [$self xy] - list $x1 $y1 [expr $x1+$@w] [expr $y1+$@h] -} -def Vu led_size {} { - set n [expr $@h/40] - if {$n < 2} {set n 2} - return [expr $n-1] -} -def Vu draw {} { - global vu_col - mset {x1 y1 x2 y2} [$self bbox] - set colour [parse_color $@bcol] - super - $self draw_io - set led_size [$self led_size] - set x3 [expr $x1+$@w/4] - set x4 [expr $x2-$@w/4] - $self item BASE rectangle [list $x1 $y1 $x2 $y2] -width 0 -fill $colour - for {set i 1} {$i<=40} {incr i} { - set y [expr $y1 + ($led_size+1)*(41-$i) - ($led_size+1)/2] - $self item RMS${i} rectangle [list $x3 $y $x4 [expr $y+$led_size]] \ - -fill [parse_color [lindex $vu_col $i]] -width 0 - } - #if {!$@zoom} {return} - set lfont [list [lindex {courier helvetica times} $@fstyle] $@fs bold] - set lcolor [parse_color $@lcol] - set i 0 - foreach level { <-99 -50 -30 -20 -12 -6 -2 -0dB +2 +6 >+12 } { - set k1 [expr $led_size+1] - set k2 41 - set k3 [expr $k1/2] - set k4 [expr $y1-$k3] - set yyy [expr $k4 + $k1*($k2-4*$i)] - $self item SCALE{$level} text [list [expr $x2+4] [expr $yyy+$k3-3]] \ - -text $level -anchor w -font $lfont -fill $lcolor - incr i - } - set y [expr $y1 + ($led_size+1)*(41-$@value) - ($led_size+1)/2] - $self item MASK rectangle [list $x3 $y1 $x4 $y] -width 0 -fill $colour - set c [lindex $vu_col [expr int($@peak)]] - set y [expr $y1 + ($led_size+1)*(41-$@peak) - ($led_size+1)/2] - $self item PEAK rectangle [list $x1 $y $x2 [expr $y+$led_size]] -fill [parse_color $c] -width 0 -} -def Vu rms= {rms } {set @value $rms; $self changed rms} -def Vu peak= {peak} {set @peak $peak; $self changed peak} -def Vu set {i j} { - set @value $i - set @peak $j - $self changed -} - -if {![catch { - package require tkdnd - dnd bindtarget . text/uri-list <Drop> {open_file %D} -}]} { - puts "warning: tkdnd package not found" -} - -class_new Cnv {Labelled IEMGUI Box} -def Cnv draw {} { - mset {x1 y1} [$self xy] - $self item BASE rectangle [list $x1 $y1 [expr {$x1+$@w+1}] [expr {$y1+$@h+1}]] -fill [parse_color $@bcol] -width 0 - super -} -def Cnv bbox {} { - mset {x1 y1} [$self xy] - return [list $x1 $y1 [expr $x1+$@w] [expr $y1+$@h]] -} - -class_new Array {Box} -def Array init {mess} { - super $mess - set @name [lindex $mess 2] - set @length 0 - set @data {} - set @draw 0 -} -def Array bbox {} { - return {0 0 1 1} ;# huh? -} -def Array draw_name {} { - mset {x_off y_off} [$@canvas xy] - $self item TEXT text [lmap + [list $x_off $y_off] 2] \ - -font [View_look $self font] -text $@name \ - -fill [View_look $self fg] -anchor nw -} -def Array draw {} { - $self draw_name - mset {x_off y_off} [$@canvas xy] - set m [$@canvas get_mess] - mset {xfrom yto xto yfrom pixwidth pixheight} $m - if {[winfo exists [$@canvas widget]]} { - mset {c_width c_height} [$@canvas get_dimen] - set width [expr $c_width / $@length] - set i 0 - foreach val $@data { - if {!$val} {set val 0.0} - set y [expr $c_height - (((double($val)+abs($yfrom))/($yto-$yfrom) * $c_height))] - set x1 [expr $width * $i] - set x2 [expr $x1 + $width] - set line [list $x1 $y $x2 $y] - $self item elem${i} line $line -fill [$@canvas look compfg] -width 2 -tags "$self ${self}elem${i}" - #.$self.c raise ${self}elem${i} - incr i - } - } else { - set width [expr $pixwidth / $@length] - set canvas [$self get_canvas] - set i 0 - foreach val $@data { - if {!$val} {set val 0.0} - #set val2 [lindex $@data [expr $i+1]] - set y [expr ($pixheight - ((double($val)+abs($yfrom))/($yto-$yfrom) * $pixheight)) + $y_off] - #set y2 [expr ($pixheight - ((double($val2)+abs($yfrom))/($yto-$yfrom) * $pixheight)) + $y_off] - set x1 [expr ($width * $i) + $x_off] - set x2 [expr $x1 + $width] - set line [list $x1 $y $x2 $y] - $self item ${self}ELEM${i} line $line -fill [$self look fg] -width 2 - incr i - } - [$canvas widget] raise $self - #set width [expr $pixwidth / [expr $@length-1]] - #set canvas [$self get_canvas] - #set i 0 - #for {set i 0} {$i < [expr $@length-1]} {incr i} { - # #if {!$val} {set val 0.0} - # set val [lindex $@data [expr $i]] - # set val2 [lindex $@data [expr $i+1]] - # set y [expr ($pixheight - ((double($val)+abs($yfrom))/($yto-$yfrom) * $pixheight)) + $y_off] - # set y2 [expr ($pixheight - ((double($val2)+abs($yfrom))/($yto-$yfrom) * $pixheight)) + $y_off] - # set x1 [expr ($width * $i) + $x_off] - # set x2 [expr $x1 + $width] - # set line [list $x1 $y $x2 $y2] - # $self item ${self}ELEM${i} line $line -fill [$self look fg] -width 0 - #} - } -} -def Array click {x y f target} { - if {[winfo exists [$@canvas widget]]} {set canvas $@canvas} else {set canvas [$@canvas canvas]} - $canvas focus= $self - set @draw 1 -} -def Array unclick {x y f target} { - if {[winfo exists [$@canvas widget]]} {set canvas $@canvas} else {set canvas [$@canvas canvas]} - $canvas focus= "" - set @draw 0 -} -def Array motion {x y f target} { - if {!$@draw} return - if {[winfo exists [$@canvas widget]]} { - mset {c_width c_height} [$@canvas get_dimen] - mset {xfrom yto xto yfrom pixwidth pixheight} [$@canvas get_mess] - set width [expr $c_width / $@length] - set i [format %d [expr int($x/$width)]] - set x1 [expr $width * $i] - set x2 [expr $x1 + $width] - set line [list $x1 $y $x2 $y] - set val [expr (($c_height-$y)/$c_height) * ($yto-$yfrom) + $yfrom] - netsend [list .$self $i $val] - } else { - mset {xfrom yto xto yfrom pixwidth pixheight} [$@canvas get_mess] - mset {x_off y_off} [$@canvas xy] - set width [expr $pixwidth / $@length] - set i [format %d [expr int(($x-$x_off)/$width)]] - set val [expr (($pixheight-$y+$y_off)/$pixheight) * ($yto-$yfrom) + $yfrom] - netsend [list .$self $i $val] - } -} -def Array length= {val} {set @length [format %f $val]} -def Array name= {val} {set @name $val} -def Array array_set {data_list} { - if {[llength $data_list] == $@length} { - set @data {} - for {set i 0} {$i < $@length} {incr i} { - lappend @data [lindex $data_list $i] - } - } else { - puts "error..." - } -} - -############ evaluator - -class_new Listener {Thing} -def Listener init {serf name command} { - set @history [History new 20] - set @command $command - set @expanded 0 - set @serf $serf - set font $::look(View:font) - frame $serf - pack [frame $serf.1] -side left -fill y - pack [frame $serf.1.1] -side bottom - pack [button $serf.1.1.expander -image icon_plus -command "$self toggle_expand"] -side left - pack [label $serf.1.1.label -width 11 -font $font -text "$name: "] -side left - pack [entry $serf.entry -width 40 -font $font] -side left -fill x -expand yes - pack $serf -fill x -expand no - bind $serf.entry <Up> "$self scroll_history +1" - bind $serf.entry <Down> "$self scroll_history -1" - bind $serf.entry <Return> "$self eval" -} -def Listener toggle_expand {} { - set @expanded [expr 1-$@expanded] - if {$@expanded} {$self expand} {$self unexpand} -} -def Listener expand {} { - set e $@serf.entry - set text [$e get] - destroy $e - pack [text $e -width 40 -height 8] -side left -fill x -expand yes - $e insert 0.0 $text - $@serf.1.1.expander configure -image icon_minus - bind $e <Alt-Return> "$self eval" -} -def Listener unexpand {} { - set e $@serf.entry - set text [$e get 0.0 end] - regsub "\n$" $text "" text - destroy $e - pack [entry $e -width 40] -side left -fill x -expand yes - $e insert 0 $text - $@serf.1.1.expander configure -image icon_plus - bind $e <Up> "$self up" - bind $e <Down> "$self down" - bind $e <Return> "$self eval" -} -def Listener replace {stuff} { - $@serf.entry delete 0 end - $@serf.entry insert 0 $stuff - $@serf.entry icursor end -} -def Listener scroll_history {incr} { - if {![$@history histi]} {$@history set_hist 0 [$self get_command]} - $self replace [$@history traverse $incr] - -} -def Listener append {v} { - $@history prepend $v - lappend @hist $v; set @histi [llength $@hist] -} -def Listener get_command {} { - set e $@serf.entry - if {$@expanded} { - set l [$e get 0.0 end]; return $l - } else { - set l [$e get]; return $l - } - -} -def Listener eval {} { - set e $@serf.entry - $@history histi= 0 - set l [$self get_command] - $self append $l - if {$@expanded} {$e delete 0.0 end} {$e delete 0 end} - $@command $self $l -} - -proc tcl_eval {self l} {post %s "tcl: $l"; post %s "returns: [uplevel [info level] $l]"} -proc pd_eval {self l} {post %s "pd: $l"; netsend $l} -proc canvas_eval {self l} {post %s "tcl: $l"; post %s "returns: [uplevel [info level] [join [list [$self canvas] $l]]]"} -############ button bar - -set butt { - {ObjectBox Object {obj}} - {MessageBox Message {msg}} - {FloatBox Number {floatatom}} - {SymbolBox Symbol {symbolatom}} - {CommentBox Comment {text}} - {bng bng {obj bng}} - {tgl tgl {obj tgl}} - {nbx nbx {obj nbx}} - {vsl vsl {obj vsl}} - {hsl hsl {obj hsl}} - {vradio vradio {obj vradio}} - {hradio hradio {obj hradio}} - {vu vu {obj vu}} - {cnv cnv {obj cnv}} - {Graph graph {graph}} - {Array array {menuarray 0}} -} - -proc button_bar_add {x y} {lappend ::butt [list $x $y noload]} -if {$tk} { - set dir $cmdline(icons) - foreach icon {mode_edit mode_run pd_32} {image create photo icon_$icon -file $dir/$icon.gif} - foreach b $butt {mset {icon name cmd} $b; image create photo icon_$icon -file $dir/$icon.gif} -} -class_new ButtonBar {View} -def ButtonBar init {canvas} { - set @canvas $canvas - set bb .$@canvas.bbar - frame $bb - pack [button $bb.edit -image icon_mode_edit -border 1 -command [list $@canvas editmodeswitch]] -side left - foreach e $::butt { - mset {icon name cmd} $e - pack [button $bb._$name -image icon_$icon -border 1 -command "$@canvas new_object $cmd"] -side left - balloon $bb._$name [say $name] - } - pack [entry $bb.name -font {helvetica -12} -width 8 -border 0] -side right - pack [spinbox $bb.scale -width 5 -command "$canvas zooming %d" -state readonly] -side right - $bb.scale set [format %d%% [expr int(100*[$@canvas zoom])]] - $bb.name insert 0 $@canvas -} -def ButtonBar widget {} {return .$@canvas.bbar} -proc obj_create {c flag} {} - -############ crosshair - -class_new Crosshair {View} -def Crosshair classtags {} {return {}} -def Crosshair init {canvas} { - super - set @canvas $canvas - $self data= 0 0 {none} -} -def Crosshair data= {x y target} { - set @x $x - set @y $y - set @target $target -} -def Crosshair draw {} { - mset {type id detail} $@target - set x $@x; set y $@y - if {[$@canvas look hairsnap]} { - switch -regexp -- $type {^object|outlet|inlet$ {mset {x y x3 y3} [$id bbox]}} - } - mset {x1 y1 x2 y2} [$self display_area] - set h1 [list $x1 $y $x2 $y] - set v1 [list $x $y1 $x $y2] - $self item VHAIR1 line $v1 -fill [$@canvas look crosshair] -width 1 -dash {4 4 4 4} - $self item HHAIR1 line $h1 -fill [$@canvas look crosshair] -width 1 -dash {4 4 4 4} -} - -#def Crosshair erase {} {$self item_delete VHAIR1; $self item_delete HHAIR1} -class_new Sense {View} -def Sense init {canvas} { - super - set @canvas $canvas - $self data= 0 0 0 red -} -def Sense data= {x y range col} { - set @x $x - set @y $y - set @range $range - set @col $col -} -def Sense flash {x y sense col} { - $self data= $x $y $sense $col - $self draw - after 500 $self erase -} -def Sense draw {} { - set c [$@canvas widget] - set x1 [expr $@x-$@range]; set y1 [expr $@y-$@range] - set x2 [expr $@x+$@range]; set y2 [expr $@y+$@range] - $self item SENSE oval [list $x1 $y1 $x2 $y2] -fill $@col -outline yellow -} -def View display_area {} { - set c [$@canvas widget]; set z [$@canvas zoom] - set edge 10 - set x1 [expr {int([$c canvasx $edge]/$z)}] - set y1 [expr {int([$c canvasy $edge]/$z)}] - set x2 [expr {int(([$c canvasx [winfo width $c]]-$edge)/$z)}] - set y2 [expr {int(([$c canvasy [winfo height $c]]-$edge)/$z)}] - return [list $x1 $y1 $x2 $y2] -} - -class_new Grid {View} -def Grid init {canvas} { - super - set @canvas $canvas - set c [$@canvas widget] - set @width [winfo width $c] - set @height [winfo height $c] - set @size [$@canvas look grid_size] - set @col [$@canvas look grid] - set @gap 5 -} -def Grid classtags {} {return {}} -def Grid update {h w} {set @width $w; set @height $h} -def Grid size= {size} {set @size $size} -def Canvas snap_grid {} {return [$self look snap_grid]} -def Canvas snap_grid= {val} {set ::look(Canvas:snap_grid) $val} -def Canvas snap_objs2grid {} { - if {![$self editmode]} {return} - foreach obj [$@objects values] { - mset {x y} [$obj xy] - set grid [$self look grid_size] - set x [expr floor($x/$grid)*$grid] - set y [expr floor($y/$grid)*$grid] - $obj moveto $x $y - } -} -def Grid draw {} { - mset {x1 y1 x2 y2} [$self display_area] - set c [$@canvas widget] - set lowest [$@canvas lowest_item] - $self draw_lines $x1 $x2 $y1 $y2 VL - $self draw_lines $y1 $y2 $x1 $x2 HL - if {$lowest != -1} {$c lower $self $lowest} -} -def Grid draw_lines {v1 v2 v3 v4 tag} { - set s $@size; set g $@gap - for {set i $v1} {$i < $v2} {incr i} { - #if {$l%$g == 0} {set width 1;set dash [list 7 1]} {set width 1;set dash [list 1 4 1 4]} - if {![expr {$i % int($s*$g)}]} {set w 1;set d [list 7 1]} {set w 1;set d [list 1 4 1 4]} - if {![expr {$i % int($s)}]} { - switch $tag {VL {set line [list $i $v3 $i $v4]} HL {set line [list $v3 $i $v4 $i]}} - $self item ${tag}$i line $line -fill $@col -width $w -dash $d - } - } -} - -def Canvas lowest_item {} { - set c [$self widget] - set all [$c find withtag foo] - if {![llength $all]} {return -1} - set lowest [lindex [$c gettags [lindex $all 0]] 0] - return $lowest -} -#def Canvas grid_size {} {return [$self look grid_size]} -def Canvas grid_size= {size} { - set ::look(Canvas:grid_size) $size - if {[$self editmode]} {$@grid size= $size; $@grid erase; after 0 $@grid draw} -} -############ tooltips (only those that are drawn as canvas items) - -class_new Tooltip {View} -def Tooltip init {canvas pos curpos text type iserror} { - set @canvas $canvas - set @pos $pos - set @curpos $curpos - set @text $text - set @type $type - set @iserror $iserror -} -def Tooltip iserror {} {return $@iserror} -def Tooltip curpos {} {return $@curpos} -def Tooltip text {} {return $@text} -def Tooltip draw {} { - set c [$@canvas widget] - if {$@iserror} { - set fg "#ffffff"; set bg "#dd0000" - } else { - set fg "#000000"; set bg "#ffffcc" - } - mset {x y} $@pos - switch -- $@type { - o {set ny [expr {$y+24}]} - i {set ny [expr {$y-24}]} - } - $self item TEXT text [list [expr $x+12] $ny] -fill $fg -text $@text -anchor sw -width 300 - mset {x1 y1 x2 y2} [l+ [$c bbox ${self}TEXT] [list -4 -4 +4 +4]] - switch -- $@type { - o {set coords [list $x1 $y1 [expr $x1+8] $y1 $x $y [expr $x1+16] $y1 $x2 $y1 $x2 $y2 $x1 $y2 $x1 $y1]} - i {set coords [list $x1 $y1 $x2 $y1 $x2 $y2 [expr $x1+16] $y2 $x $y [expr $x1+8] $y2 $x1 $y2 $x1 $y1]} - } - $self item RECT polygon $coords -fill $bg -outline $fg - $c lower ${self}RECT ${self}TEXT -} -# $c delete tooltip_bg tooltip_fg -set tooltip "" -def Canvas show_tooltip {x y text type {iserror 0}} { - global tooltip - if {$tooltip ne "" && [$tooltip text] eq $text} {return} - if {$tooltip ne ""} {$tooltip delete} - set tooltip [Tooltip new $self [list $x $y] $@curpos $text $type $iserror] - $tooltip draw -} - -############ class browser - -# future use, maybe: -#class_new ServerClassDict {Observable Thing} -#def ServerClassDict init {} {} - -# Completion/Browser init can be cleaned up a bit more, do it later... -class_new ClassBrowser {Dialogue} -class_new Browser {ClassBrowser} -def Browser init {name x y textbox} {super $name $x $y $textbox} - -class_new Completion {ClassBrowser} -def Completion init {name x y textbox} {super $name $x $y $textbox} -def Completion cancel {} { - bind $@textbox <Key> "$@textself key_input %W %x %y %K %A 0" - bind $@textbox <Control-Return> "$@textself key_input %W %x %y 10 %A 0" - bind $@textbox <Return> "$@textself unedit" - bind $@textbox <Tab> "$@textself key_input %W %x %y %K %A 0" - focus $@textbox - $self delete -} -def ClassBrowser delete {} {set @exist 0; super} -def ClassBrowser init {name x y textbox} { - set @name $name - set @width 0 - set @height 0 - # so that in completion mode, it know which textbox to switch the focus to - set @textbox $textbox - netsend [list pd update-path] - netsend [list pd update-class-list $self list_callback] -} -def ClassBrowser fill_box {s} { - $@listbox delete 0 end - foreach class [lsort $::class_list] { - if {[string length $s]==0 || [string first $s $class]>=0} { - set t "\[$class\]" - if {[can_say $class]} {append t " [say $class]"} - $@listbox insert end $t - #if {[string length $t] > [string length $@width]} {set @width [string length $t]} - if {[string length $t] > $@width} {set @width [string length $t]} - } - } - set none [say no_matches] - if {![$@listbox size]} {$@listbox insert 0 $none; set @width [string length $none]} - $@listbox selection set 0 0 -} - -def Completion fill_box {s} { - super $s - wm maxsize .$self [winfo reqwidth .$self.comp] [winfo reqheight .$self.comp] -} - -def Browser fill_box {s} { - super $s - .$self.title configure -text [format [say how_many_object_classes] [$@listbox size] [llength $::class_list]] -} - -proc search_for_externs {} { - foreach dir $::pd_path { - catch { - #set xs [glob "$dir/*.pd*"] - set xs [glob "$dir/*.pd_*"] - foreach x $xs { - set fn [lindex [file split $x] end] - set fn [join [lrange [split $fn .] 0 end-1] .] - lappend ::class_list $fn - } - } - } -} - -def ClassBrowser info {listbox} { - set class [$self current_class] - if {$class != ""} {netsend [list pd update-class-info $class $self info_callback]} -} - -def Browser list_callback {} { - search_for_externs - set class_list [luniq [lsort $::class_list]] - - toplevel .$self - set f .$self.cl - pack [frame $f] -side top -fill both -expand yes - pack [label .$self.title -text ""] -side top - listbox $f.1 -width 50 -height 20 -yscrollcommand "$f.2 set" -activestyle none - scrollbar $f.2 -command "$f.1 yview" - text $f.3 -width 30 -height 20 -yscrollcommand "$f.4 set" - scrollbar $f.4 -command "$f.3 yview" - set @listbox $f.1 - - frame $f.5 - button $f.5.help -text [say help] -command [list $self help] - pack $f.5.help -side top - pack $f.5 -side left -fill y -expand no - pack $f.1 -side left -fill both -expand yes - pack $f.2 -side left -fill y -expand no - pack $f.3 -side left -fill both -expand yes - pack $f.4 -side left -fill y -expand no - - set b .$self.butt - frame $b - pack [label $b.1 -text [say filter]] -side left - pack [entry $b.2 -width 15] -side left - pack [button $b.close -text [say close] -command "destroy .$self"] -side right - pack $b -side bottom -fill x -expand no - set @textbox $b.2 - $self fill_box "" - #bind $f.1 <Button-1> "after 1 \"$self info $f.1 \"" - foreach w [list $f.1 $b.2] { - bind $w <KeyPress> "after 1 \"$self key %K 0\"" - bind $w <Shift-KeyPress> "after 1 \"$self key %K 1\"" - bind $w <Return> [list $self help] - } - focus $@textbox -} - -def Browser help {} { - set f .$self.cl - netsend [list pd help [$self current_class]] -} - -def Completion list_callback {} { - search_for_externs - set class_list [luniq [lsort $::class_list]] - toplevel .$self - wm protocol .$self WM_DELETE_WINDOW "$self cancel" - wm overrideredirect .$self 1 - set canvas $@name - set f .$self.comp - set @listbox $f - set @rootx [winfo rootx .$@name.c] - set @rooty [winfo rooty .$@name.c] - set @max [wm maxsize .$self] - if {[regexp {(x[0-9a-z]{6,8})text$} $@textbox dummy textself]} {set @textself $textself} - if {[$canvas look showcomp] <= 20} {set @height [$canvas look showcomp]} else {set @height 20} - listbox $f -width $@width -height $@height -relief flat -activestyle dotbox -font $::look(View:font) \ - -bg [$@textself look bg] -selectbackground [$@textself look fg] \ - -fg [$@textself look fg] -selectforeground [$@textself look bg] - $self adjust_box - bind $f <Button-1> "after 1 \"$self complete\"" - bind $f <Return> "after 1 \"$self complete\"" - bind $f <KeyPress> "$self key %K 0" - bind $f <Shift-KeyPress> "$self key %K 1" - bind $@textbox <Tab> "$self key %K; break" - bind $@textbox <KeyPress> "$self key %K " - focus .$self.comp -} - -def Completion adjust_box {} { - mset {x1 y1 x2 y2} [lmap * [$@textself bbox] [$@name zoom]] - set x1 [format %0.f $x1];set y1 [format %0.f $y1] - set x2 [format %0.f $x2];set y2 [format %0.f $y2] - $self fill_box [$@textbox get 1.0 1.end] - set f .$self.comp - $f configure -width $@width - set box_width [winfo reqwidth $f] - set box_height [winfo reqheight $f] - pack $f -side left -expand yes - - .$self configure -width $box_width - .$self configure -height $box_height - - #test the right edge of the screen, assuming the left edge has enough space - if {[expr $x1+$@rootx+$box_width] < [lindex $@max 0]} { - set box_x [expr $x1+$@rootx] - } else { - set box_x [expr $x2 - $box_width + $@rootx] - } - #test the lower edge of the screen, assuming the upper edge has enough space - if {[expr $y2+$@rooty+$box_height] < [lindex $@max 1]} { - set box_y [expr $y2 + 5 + $@rooty] - } else { - set box_y [expr $y1 - $box_height - 2 + $@rooty] - } - - wm geometry .$self [winfo reqwidth .$self]x[winfo reqheight .$self]+$box_x+$box_y - -} - -def ClassBrowser current_class {} { - set i [$@listbox curselection] - if {$i == ""} {return {}} - return [string range [lindex [$@listbox get $i] 0] 1 end-1] -} - -def ClassBrowser complete {} { - if {[regexp {x([0-9a-z]{6,8})text$} $@textbox obj]} { - set cut [string first "text" $obj] - set obj [string range $obj 0 [expr $cut -1]] - } - set class [$self current_class] - $@textbox delete 1.0 1.end - $@textbox insert 1.0 $class - $obj unedit - destroy .$self -} - -def ClassBrowser key {key {shift 0}} { - switch -regexp -- $key { - Up|Down { - if {[focus] != $@listbox} { - focus $@listbox - event generate $@listbox <KeyPress> -keysym $key - } else { - if {$self == "browser"} {$self info $@listbox} - } - } - Escape {after 1 "$self cancel"} ;# doesn't really work - Tab { - focus $@listbox - set next [$@listbox index active] - incr next - if {$next >= [$@listbox size]} {set next 0} - $@listbox activate $next - $@listbox selection clear 0 [expr [$@listbox size] - 1] - $@listbox selection set $next $next - #if {$next >= [expr $@height - 1]} {$@listbox yview scroll 1 units} - $@listbox see $next - if {$self == "browser"} {$self info $@listbox} - } - BackSpace { - if {[focus] == $@listbox} {focus $@textbox} - #classbrowser uses entry as input widget, where as completion is text widget... - switch $self { - browser {$self fill_box [$@textbox get]} - completion {$self adjust_box; $@textself resize; $@textself changed} - } - } - default { - $self key_default $key - } - } -} - -def Browser key_default {key} { - if {[focus] == $@listbox} { - if {[regexp {^[a-zA-Z0-9~/\._]{1}$} $key]} { - .$self.butt.2 insert end $key - $self fill_box [$@textbox get] - } - } else {$self fill_box [$@textbox get]} -} - -def Completion key_default {key} { - if {[focus] == $@listbox} { - if {[regexp {^[a-zA-Z0-9~/\._]{1}$} $key]} { - $@textbox insert 1.end $key - $@textself after_key $@textbox - $self adjust_box - focus $@textbox - } - } - if {[focus] == $@textbox & $key != "Tab"} { - $self adjust_box - $@textself resize - #hum, no idea why i need after 1 for it to work... - after 1 $@textself after_key $@textbox - } -} - -def ClassBrowser info_callback {class} { - global class_info - set f .browser.cl - set class [$self current_class] - $f.3 delete 0.0 end - $f.3 insert end "class $class\n" - foreach {k v} $class_info($class) {$f.3 insert end "$k=\"$v\"\n"} -} - -def TextBox propose_completions {} { - set c [$@canvas widget] - set widget $c.${self}text - set propose $c.${self}propose - #$propose configure -state normal - if {![info exists ::class_list]} { - netsend [list pd update-class-list $self propose_completions] - return - } - set r {} - set c {} - set n 0 - set prev "" - foreach class [luniq [lsort $::class_list]] { - if {[string length $@text]==0 || [string first $@text $class]>=0} { - if {[string compare [say $class] "{{$class}}"]} { - lappend r "$class : [say $class]" - } { - lappend r $class - } - lappend c $class - incr n - } - if {$n > 16} {lappend r ...; break} - } - set r [join $r "\n"] - mset {x1 y1 x2 y2} [$self bbox] - set @action [Completion new_as completion $@canvas $x1 $y1 $widget] -} - -############ properties_dialog ######### -proc change_entry {self val} { - set v [expr [$self get]+$val] - $self delete 0 end - $self insert 0 $v -} - -class_new Dialogue {View} -def Dialogue add_stuff {f name label} { - frame $f -# frame $f.label -width $@label_width -borderwidth 2 -# pack [button $f.label.0 -image "icon_empty" -width $@label_width] -side left -# place [message $f.label.1 -text $label -width $@label_width] -x 0 -y 0 -# puts [$f.label.1 cget -height] - pack [label $f.label -text $label -width [expr $@label_width/7] -wraplength $@label_width -anchor e] -side left - balloon $f.label $name -} -def Dialogue add_side {f name label} { - $self add_stuff $f $name $label - frame $f.side -relief ridge -borderwidth 2 - foreach {i side} {0 left 1 right 2 top 3 bottom} { - radiobutton $f.side.$side -value $i -variable @$name -text $side - } - pack $f.side.left -side left -fill y - pack $f.side.right -side right -fill y - pack $f.side.top -side top - pack $f.side.bottom -side bottom - pack $f.side -side left -} -def Dialogue add_color {f name label} { - $self add_stuff $f $name $label - set v $@$name - set text_color [complement $v] - button $f.color -text $v -font {Courier 10} -width 10 -pady 2 -fg $text_color \ - -command [list $self choose_col $f $name $v] -relief sunken -background $v -highlightbackground $v -activebackground $v - button $f.preset -text [say "preset"] -pady 2 -font {Helvetica 8} \ - -command [list $self color_popup $f $name 10] - bind $f.preset <Return> "$self color_popup $f $name 10" - pack $f.color $f.preset -side left -} -def Dialogue add_choice {f name label choices} { - $self add_stuff $f $name $label - menu $f.menu -tearoff 0 - set i 0 - foreach part $choices { - $f.menu add command -label [say $part] -command [list $self dropmenu_set $f $name $part $i] - incr i - } - set trim_name [string trimleft $name "-"] - set _($self:${name}choices) $choices - set choice $@$name - if {[string is integer $choice]} {set choice [lindex $choices $choice]} - label $f.butt -text [say $choice] -relief raised -width 20 - balloon $f.butt "click to change setting" - pack $f.label $f.butt -side left - bind $f.butt <1> [list $self dropmenu_open $f $name] -} -def Dialogue add_key {f name label} { - set text "" - set n 0 - foreach item $name { - if {$n != 0} {append text " & " [say $item]} else {set text [say $item]} - incr n - } - $self add_stuff $f $name $text - #balloon $f.label $name - foreach item $name { - set v $_($self:$item) ;# bug in objtcl - set item_lower [string tolower $item] - entry $f.$item_lower -width 15 -textvariable @$item - pack $f.$item_lower -side left - } -} -def Dialogue add_folders {f name label} { - $self add_stuff $f $name $label - set v $_($self:$name) ;# bug in poetcl - frame $f.a - listbox $f.a.list -width 40 -height 8 -yscrollcommand "$f.a.yscroll set" \ - -activestyle none -xscrollcommand "$f.a.xscroll set" - foreach line $v {$f.a.list insert end $line} - set @$name $f.a.list ;# save the listbox path at @$name instead - scrollbar $f.a.yscroll -command "$f.a.list yview" - scrollbar $f.a.xscroll -command "$f.a.list xview" -orient horizontal - pack $f.a.xscroll -side bottom -fill x - pack $f.a.list -side left -fill both -expand 1 - pack $f.a.yscroll -side left -fill y - pack $f.a -side left - frame $f.b -borderwidth 0 - foreach {cmd lab} {dir_add add listbox_remove remove listbox_up up listbox_down down} { - pack [button $f.b.$cmd -command "$self $cmd $f.a.list" -text [say $lab] -width 6] -side top - balloon $f.b.$cmd [say dir_$lab] - } - pack $f.b -side top -} -def Dialogue add_libraries {f name label} { - $self add_stuff $f $name $label - set v $_($self:$name) ;# bug in poetcl. is it still there? - frame $f.a - listbox $f.a.list -width 32 -height 16 -yscrollcommand "$f.a.yscroll set" \ - -activestyle none -xscrollcommand "$f.a.xscroll set" - #foreach line $@$name {$f.a.list insert end $line} - foreach line $v {$f.a.list insert end $line} - # save the listbox path at @$name instead - set @$name $f.a.list - pack [scrollbar $f.a.yscroll -command "$f.a.list yview"] -side right -fill y - pack $f.a.list -side top -fill both -expand 1 - pack [scrollbar $f.a.xscroll -command "$f.a.list xview" -orient horizontal] -side bottom -fill x - pack $f.a -side left - - frame $f.b -borderwidth 0 - pack [entry $f.b.entry -width 15 -borderwidth 5 -relief ridge] -side top - bind $f.b.entry <Return> "$self lib_add $f.a.list" - - foreach {cmd lab} {lib_add add listbox_remove remove listbox_up up listbox_down down} { - pack [button $f.b.$cmd -command "$self $cmd $f.a.list" -text [say $lab] -width 6] -side top - #balloon $f.b.$cmd [say dir_$lab] - } - pack $f.b -side top -} -def Dialogue dir_add {listbox} { - set dir [tk_chooseDirectory -initialdir ~ -title "Choose a folder" -parent .$self] - if {$dir == ""} {return} - $listbox insert end $dir - $listbox yview end - focus .$self -} -# doesn't work with toplevel widget -proc upwidget {levels name} { - set l [split $name .] - return [join [lrange $l 0 end-$levels] .] -} -def Dialogue lib_add {f} { - set f [upwidget 2 $f] - set listbox $f.a.list - set entry $f.b.entry - set var [$entry get] - if {$var != ""} {$listbox insert end $var} - $listbox yview end - $entry delete 0 end - focus $entry -} -def Dialogue listbox_remove {listbox} { - set sel [$listbox curselection] - if {$sel == ""} {return} - $listbox delete $sel - $listbox selection set $sel -} -def Dialogue listbox_swap {listbox dir} { - set sel [$listbox curselection] - if {$sel == ""} {return} - if {![inside [expr $sel+$dir] 0 [$listbox size]]} {return} - set line [$listbox get $sel] - $listbox delete $sel - incr sel $dir - $listbox insert $sel $line - $listbox selection set $sel - $listbox see $sel -} -def Dialogue add_devlist {f name label} { - $self add_stuff $f $name $label - menu $f.menu -tearoff 0 - set i 0 - set trim_name [string trimleft $name "-"] - set part none ;# in case there are none - foreach part $@$trim_name { - $f.menu add command -label $part -command [list $self dropmenu_set $f $name $part $i] - incr i - } - #label $f.butt -text [lindex $@$trim_name 0] -relief raised -width 20 - label $f.butt -textvariable _($self:${trim_name}0) -relief raised -width 20 - balloon $f.butt "click to change setting" - pack $f.label $f.butt -side left - bind $f.butt <1> [list $self dropmenu_open $f $name] -} -def Dialogue add_spins {f name label option} { - $self add_stuff $f $name $label - set i 0 - set trim_name [string trimleft $name "-"] - set n [llength $@$option] - foreach part $@$trim_name { - if {$i < $n} {set s "readonly"} else {set s "disabled"} - set v "::_($self:$trim_name${i})" - spinbox $f.$i -width 2 -command "$self spinning %d $v" -state $s -textvariable $v - pack $f.$i -side left - balloon $f.$i "Device [expr $i+1]" - incr i - } -} -def Dialogue spinning {mode v} { - switch $mode { - up {incr $v; puts " incr $v"} - down {incr $v -1} - } -} -def Dialogue listbox_up {listbox} {$self listbox_swap $listbox -1} -def Dialogue listbox_down {listbox} {$self listbox_swap $listbox +1} -def Dialogue add {w args} { - foreach row $args { - set name [lindex $row 0] - set type [lindex $row 1] - set options [lrange $row 2 end] - set f $w.$name - set label "[say $name]: " - set k [lsearch $options -choices] - if {$k>=0} { - set choices [lindex $options [expr $k+1]] - set options [lreplace $options $k [expr $k+1]] - } - #set v $@$name - #set v $_($self:$name) ;# bug in poetcl - switch -- $type { - side {$self add_side $f $name $label} - color {$self add_color $f $name $label} - font {$self add_font $f $name $label $options} - choice {$self add_choice $f $name $label $choices} - key {set f $w.[string tolower [lindex $name 0]] - $self add_key $f $name $label} - folders {$self add_folders $f $name $label} - libraries {$self add_libraries $f $name $label} - devlist {$self add_devlist $f $name $label} - spins {$self add_spins $f $name $label $options} - section {label $f -text $label -bg "#0000aa" -fg "#ffff55" -font {helvetica -10 bold}} - subsection {label $f -text $label -bg "#0000aa" -fg "#ffff55" -font {helvetica -10 bold}} - toggle { - $self add_stuff $f $name $label - eval [concat [list checkbutton $f.toggle -variable @$name] $options] - pack $f.toggle -side left - } - default { - $self add_stuff $f $name $label - set trim_name [string trimleft $name "-"] - eval [concat [list entry $f.entry -textvariable _($self:$trim_name)] $options] - pack $f.entry -side left - bind $f.entry <Return> "$self ok" - switch -regexp -- $type { - integer|float|fontsize { - frame $f.b -borderwidth 0 - button $f.b.1 -image icon_wedge_up -command "change_entry $f.entry +1" - button $f.b.2 -image icon_wedge_down -command "change_entry $f.entry -1" - pack $f.b.1 $f.b.2 -side top - pack $f.b -side left - bind $f.entry <Button-4> "change_entry $f.entry +1" - bind $f.entry <Button-5> "change_entry $f.entry -1" - } - entry {} - default { - label $f.type -text "($type)" -fg "#808080" - pack $f.type -side right -anchor e - } - } - } - } - pack $f -side top -fill x - } -} - -proc logvar {args} { - set r {} - foreach var $args { - regsub {^_\(.*:(.*)\)$} $var {@\1} var2 - lappend r "$var2=[uplevel 1 list \$$var]" - } - puts [join $r "; "] -} - -def Dialogue spinbox_update {mode} {puts " $mode"} -def Dialogue add_font {f name label class} { - $self add_stuff $f $name $label - set v $@$name - label $f.font -text $v -font [lreplace $v 1 1 -10] -width [string length $v] -height 1 -pady 3 -fg black \ - -relief sunken -bg white - button $f.preset -text [say "edit"] -pady 2 -font {Helvetica 8} \ - -command "FontDialogue new_as $name $class $f.font" - pack $f.font $f.preset -side left -} - -def Canvas fd {} {FontDialogue new_as view_font [$self look font] "View"} - -class_new FontDialogue {Dialogue} -def FontDialogue init {class orig} { - if {[winfo exists .$self]} {return} - super cancel ok - set f .$self - set @class $class - set @orig $orig - bind all <KeyPress-F1> help - set font $::look($@class:font) - set @family [lindex $font 0] - set @size [expr -[lindex $font 1]] - set @bold [expr [lsearch $font bold ]>=0] - set @italic [expr [lsearch $font italic]>=0] - set @str $font - pack [label $f.label -text [say font_family] -anchor w] -side top -fill x - - frame $f.list -bd 2 - pack [listbox $f.list.box -relief sunken -yscrollcommand "$f.list.scroll set" -width 30] -side left -expand yes -fill both - pack [scrollbar $f.list.scroll -relief sunken -command "$f.list.box yview" -takefocus 0] -side right -fill y - bind $f.list.box <<ListboxSelect>> "$self font_update $f" - foreach name [lsort [font families]] {$f.list.box insert end $name} - set fontlist [$f.list.box get 0 end] - set find [max 0 [lsearch $fontlist $@family]] - $f.list.box selection set $find $find - $f.list.box activate $find - $f.list.box see $find - bind $f.list.box <ButtonRelease-1> "$self font_update $f" - bind $f.list.box <ButtonPress-1> "focus $f.list.box" - pack $f.list -side left -expand yes -fill both - - #pack [ttk::separator $f.sep -orient vertical] -side left -fill y - #pack [ttk::sizegrip $f.sep] -side left -fill y - #ttk::panedwindow - - frame $f.var - frame $f.var.size - pack [label $f.var.size.label -text [say font_size]] -side left - pack [spinbox $f.var.size.entry -relief sunken -textvariable fontsize -width 4 \ - -command "$self font_changesize $f %d"] -side left - bind $f.var.size.entry <KeyPress-Return> "$self font_update_size $f" - $f.var.size.entry delete 0 end - $f.var.size.entry insert 0 $@size - - frame $f.var.style - pack [label $f.var.style.label -text [say font_style]] -side left - set cmd [list $self font_update $f] - pack [checkbutton $f.var.style.bold -text [say font_bold] -variable @bold -command $cmd] -side top - pack [checkbutton $f.var.style.italic -text [say font_italic] -variable @italic -command $cmd] -side top - - pack $f.var.size -side left - pack $f.var.style -side left -padx 20 - - frame $f.preview - pack [label $f.preview.label -text [say font_preview]] -side left - pack [canvas $f.preview.canvas -width 250 -height 50 -relief sunken -borderwidth 1] -side left -fill x - $f.preview.canvas create text 4 4 -tags ${self}TEXT -anchor nw -text [say font_preview_2] -font $font - - pack $f.var -side top -fill x - pack $f.preview -side top -pady 10 - focus $f.list.box - #$self non_resizable -} -def FontDialogue font_update {f} { - global font - set lb $f.list.box - set @family [$lb get [$lb curselection]] - set @str [list $@family [expr -$@size]] - if {$@bold } {lappend @str bold } - if {$@italic} {lappend @str italic} - # logvar @str - $f.preview.canvas itemconfigure ${self}TEXT -font $@str -} -def FontDialogue font_changesize {f mode} { - switch $mode { - up {set @size [expr $@size+1]} - down {set @size [expr $@size-1]} - } - $f.var.size.entry delete 0 end - $f.var.size.entry insert 0 $@size - $self font_update $f -} -def FontDialogue font_style {f bold} { - set @bold $bold - $self font_update $f -} -def FontDialogue font_update_size {f} { - set size [$f.var.size.entry get] - if [regexp {^[0-9]+$} $size] {set @size $size} - $self font_update $f -} -def FontDialogue apply {} { - set ::look($@class:font) $@str - $@orig configure -font [lreplace $@str 1 1 -10] -text $@str -width [string length $@str] -} - -############ .pdrc editor -#Turns #rgb into 3 elem list of decimal vals. -proc rgb2dec {c} { - set c [string tolower $c] - if {[regexp -nocase {^#([0-9a-f])([0-9a-f])([0-9a-f])$} $c x r g b]} { - # double'ing the value make #9fc == #99ffcc - scan "$r$r $g$g $b$b" "%x %x %x" r g b - } else { - if {![regexp {^#([0-9a-f]+)$} $c junk hex] || \ - [set len [string length $hex]]>12 || $len%3 != 0} { - if {[catch {winfo rgb . $c} rgb]} { - return -code error "bad color value \"$c\"" - } else { - return $rgb - } - } - set len [expr {$len/3}] - scan $hex "%${len}x%${len}x%${len}x" r g b - } - return [list $r $g $b] -} -#Returns a complementary color -proc complement {orig {grays 1}} { - foreach {r g b} [rgb2dec $orig] {break} - set R [expr {(~$r)%256}] - set G [expr {(~$g)%256}] - set B [expr {(~$b)%256}] - if {$grays && abs($R-$r) < 32 && abs($G-$g) < 32 && abs($B-$b) < 32} { - set R [expr {($r+128)%256}] - set G [expr {($g+128)%256}] - set B [expr {($b+128)%256}] - } - return [format "\#%02x%02x%02x" $R $G $B] -} - -# this makes the tooltip -proc balloon {w help} { - bind $w <Any-Enter> "after 500 [list balloon:show %W [list $help]]" - #bind $w <Any-Leave> "destroy %W.balloon; puts \"destroy balloon\" " - bind $w <Any-Leave> "destroy %W.balloon" -} - -proc balloon:show {w arg} { - if {[eval winfo containing [winfo pointerxy .]]!=$w} {return} - set top $w.balloon - catch {destroy $top} - toplevel $top -bd 1 -bg black - wm overrideredirect $top 1 - if {$::tcl_platform(platform) == "macintosh"} {unsupported1 style $top floating sideTitlebar} - pack [message $top.txt -aspect 10000 -bg lightyellow -font fixed -text $arg] - set wmx [expr [winfo rootx $w]+[winfo width $w]] - set wmy [winfo rooty $w] - wm geometry $top [winfo reqwidth $top.txt]x[winfo reqheight $top.txt]+$wmx+$wmy - raise $top -} - -def Dialogue ok {} {$self apply; $self cancel} -def Dialogue cancel {} {$self delete} -def Dialogue close {} {$self delete} -def Dialogue apply {} {} -def Dialogue delete {} {destroy .$self; super} -def Dialogue erase {} {}; # so that it doesn't call View erase -def Dialogue init {args} { - super - set f .$self - set @label_width 160 ;# 20 - toplevel $f - frame $f.buttonsep -height 2 -borderwidth 1 -relief sunken - frame $f.buttonframe - set i 0 - foreach a $args { - if {[llength $args]<=1 || $i>0} { - pack [label $f.buttonframe.$i -width 1] -side left -fill x -expand 1 - } - pack [button $f.buttonframe.$a -text [say $a] -command "$self $a"] -side left - bind $f.buttonframe.$a <Return> "$self $a" - incr i - } - pack $f.buttonframe -side bottom -fill x -pady 2m - pack $f.buttonsep -side bottom -fill x - wm protocol $f WM_DELETE_WINDOW "$self cancel" - bind .$self <Tab> "$self traversal %K %W forward" - bind .$self <Control-Tab> "$self traversal %K %W back" - set @auto_apply 0 -} -def Dialogue do_auto_apply {} {if {$@auto_apply} {$self apply}} -def Dialogue non_resizable {} {wm resizable .$self 0 0} -def Dialogue traversal {k w direction} { - switch $direction { - forward {focus [tk_focusNext $w]} - back {focus [tk_focusPrev $w]} - } -} -def Dialogue dropmenu_open {frame} { - set x [winfo rootx $frame.butt] - set y [expr [winfo height $frame.butt] + [winfo rooty $frame.butt]] - tk_popup $frame.menu $x $y -} -def Dialogue dropmenu_set {frame var part val} { - #if {$say} {set text [say $part]} else {set text $part} - set @$var $val - $frame.butt configure -text [say $part] -} -def Dialogue color_popup_select {frame var color} { - set @$var $color - set col [format #%6.6x $color] - if {$self == "ddrc"} {set @$var $col} ;#!@#$ fishy - $frame.color configure -background $col -activebackground $col -highlightbackground $col \ - -foreground [complement $col] -text $col - destroy $frame.color.popup - $self do_auto_apply -} -def Dialogue color_popup {frame var i} { - set w $frame.color.popup - if [winfo exists $w] {destroy $w} - #menu $w -tearoff false - toplevel $w -bg "#000000" - wm overrideredirect $w 1 - wm geometry $w +[expr [winfo rootx $frame.preset]]+[expr {[winfo rooty $frame.preset]+[winfo height $frame.preset]}] - for {set i 0} {$i<3} {incr i} { - pack [frame $w.$i -bd 0 -bg "#000000"] - for {set j 0} {$j<10} {incr j} { - set c [lindex $::preset_colors [expr {$i*10+$j}]] - pack [frame $w.$i.$j -width 24 -height 24 -background "#$c" -relief raised] -side left - bind $w.$i.$j <ButtonRelease> [list $self color_popup_select $frame $var [expr 0x$c]] - } - } -} -def Dialogue choose_col {frame var val} { - set c 0xFFFFFF - set color [tk_chooseColor -title $val -initialcolor $val] - if {$color != ""} { - $frame.color configure -text $color - $self color_popup_select $frame $var [expr [string replace $color 0 0 "0x"]&0xFFFFFF] - } -} - -class_new PagedDialogue {Dialogue} -def PagedDialogue init {args} { - eval [concat [list super] $args] - set @nb [ttk::notebook .$self.1] - set @nbs $@nb - pack $@nb -expand 1 -fill both - $self non_resizable -} - -# numbers in section are for the % of space taken by labels -set pdrc_options { - section {section_audio 50} - integer -r - devlist -audioindev|-soundindev - devlist -audiooutdev|-soundoutdev - spins {-inchannels audioindev} - spins {-outchannels audiooutdev} - integer -audiobuf|-soundbuf - integer -blocksize - integer -sleepgrain - void -nodac - void -noadc - choice {audio_api_choice} - void -32bit - - section {section_midi 50} - void -nomidiin - void -nomidiout - devlist -midiindev - devlist -midioutdev - - section {section_externals 20} - libraries -lib - - section {section_paths 20} - folders -path - folders -helppath - - section {section_other 50} - files -open - void -verbose - integer -d - void -noloadbang - string -send - void -listdev - void -realtime|-rt -} - -proc pdtk_audio_dialog {indevlist indevs inchans outdevlist outdevs outchans sr dspblock advance multi longform} { - pdrc audio_properties $indevlist $indevs $inchans $outdevlist $outdevs $outchans $sr $dspblock $advance $multi -} - -class_new ServerPrefsDialogue {PagedDialogue} -def ServerPrefsDialogue apply {} { - set audio_props [$self audio_properties=?] - #pd pd audio-dialog $audio_props - netsend [list "pd" "audio-dialog" $audio_props] - $self write -} -def ServerPrefsDialogue init_reverse_hash {} { - foreach {type names} $::pdrc_options { - set name [lindex $names 0] - if {[info exists @$name]} { - if {$name != "audio_api_choice"} {set @$name ""} - } else {set @$name ""} - foreach alias $names {set ::pdrc_options_h($alias) [list $type $name]} - if {$name == "audio_api_choice"} { - foreach alias [lrange $::pd_apilist2 1 end] {set ::pdrc_options_h($alias) [list $type $name]} - } - } -} -def ServerPrefsDialogue audio_properties {indevlist indevs inchans outdevlist outdevs outchans sr dspblock advance multi} { - set @audioindev $indevlist - set @audiooutdev $outdevlist - # the following @audioindev* is used as -textvariable for devlist - set @audioindev0 [lindex $@audioindev 0] - set @audiooutdev0 [lindex $@audiooutdev 0] - set @inchannels $inchans - set @outchannels $outchans - set @audiobuf $advance - set @blocksize $dspblock - set @usemulti $multi - set @r $sr - set @midiindev "midione" - set @midioutdev "miditwo" - # below are also used as -textvariable - mset [list @inchannels0 @inchannels1 @inchannels2 @inchannels3] $@inchannels - mset [list @outchannels0 @outchannels1 @outchannels2 @outchannels3] $@outchannels - set @audio_api_choice2 [say [lindex $::pd_apilist2 $@audio_api_choice]] - if {![winfo exists .$self.1.1]} {$self init_content} else {$self update_content} -} -def ServerPrefsDialogue audio_properties=? {} { - set indev0 [lsearch $@audioindev $@audioindev0] - set outdev0 [lsearch $@audiooutdev $@audiooutdev0] - return [list $indev0 0 0 0 $@inchannels0 $@inchannels1 $@inchannels2 $@inchannels3 \ - $outdev0 0 0 0 $@outchannels0 $@outchannels1 $@outchannels2 $@outchannels3 \ - $@r $@blocksize $@audiobuf] -} -def ServerPrefsDialogue read_one {type name contents i} { - switch -- $type { - folders {incr i; lappend @$name [lindex $contents $i]} - libraries {incr i; lappend @$name [lindex $contents $i]} - files {incr i; lappend @$name [lindex $contents $i]} - choice { - if {$name == "audio_api_choice"} { - if {$@$name == ""} {set @$name [lsearch $::pd_apilist2 [lindex $contents $i]]} - } else {set @$name [lindex $contents $i]} - } - void { set @$name 1} - default {incr i; set @$name [lindex $contents $i]} - } - incr i - return $i -} -def ServerPrefsDialogue read {} { - global pdrc_options pdrc_options_h cmdline - set fd [open $cmdline(rcfilename) "RDONLY CREAT"] - set contents {} - foreach line [split [read $fd] "\n"] { - if {[string index $line 0] != "#"} {lappend contents $line} - } - close $fd - set contents [concat [join $contents " "]] ;# concat casts to list type (faster) (?) - set i 0 - - # prevent Tk8.5 from showing grey checkmarks - foreach name {-nodac -noadc -32bit -nomidiin -nomidiout -verbose -noloadbang -listdev -realtime} {set _($self:$name) 0} - - while {$i < [llength $contents]} { - set op [lindex $contents $i] - if {[string length $op]==0} {break} - if {![info exists pdrc_options_h($op)]} {post "unknown option: %s" $op; incr i; continue} - mset {type name} $pdrc_options_h($op) - set name [lindex [split $name "|"] 0] - set i [$self read_one $type $name $contents $i] - } -} -def ServerPrefsDialogue write {} { - set fd [open $::cmdline(rcfilename) w] - #set fd stdout; puts "WOULD SAVE:" - foreach {type names} $::pdrc_options { - set name [lindex [split [lindex $names 0] "|"] 0] - if {[info exists _($self:$name)]} {set v $_($self:$name)} ;# bug in objective.tcl ? - switch $type { - folders {foreach item [$v get 0 end] {puts $fd "$name $item"}} - libraries {foreach item [$v get 0 end] {puts $fd "$name $item"}} - #files {foreach item $v {puts $fd "$name $item"}} - void {if {$v != ""} {if {$v} {puts $fd $name}}} - choice { - if {$name != "audio_api_choice"} {set vv [lindex $names [expr 1+$v]]} \ - else {set vv [lindex $::pd_apilist2 $v] } - if {$vv != "default"} {puts $fd $vv} - } - devlist {} - default {if {[string length $v]} {puts $fd "$name $v"}} - } - } - close $fd - #puts "THE END" -} -#def ServerPrefsDialogue reset {} {} -def ServerPrefsDialogue init_content {} { - set f .$self.1 - set section 0 - set @label_width 200 ;# 24 - foreach {type names} $::pdrc_options { - set name [lindex [split [lindex $names 0] "|"] 0] - switch $type { void { set type toggle }} - switch $type { - section { - set @label_width [expr 6*[lindex $names 1]] ;# % of 600 px - frame .$self.1.[incr section] - $@nb add .$self.1.$section -text [say $name] - } - choice { - if {$name == "audio_api_choice"} { - set ops $::pd_apilist2 - } else { - set ops [lrange $names 1 end] - } - $self add $f.$section [list $name choice -choices $ops] - } - devlist {$self add $f.$section [list $name devlist] } - spins {$self add $f.$section [list $name spins [lindex $names 1]] } - default {$self add $f.$section [list $name $type]} - } - } -} -def ServerPrefsDialogue update_content {} {$self update_channels} -def ServerPrefsDialogue update_channels {} { - set indev_len [llength $@audioindev] - set outdev_len [llength $@audiooutdev] - set i 0 - foreach chan $@inchannels { - if {$i< $indev_len} {set s "readonly"} else {set s "disabled"} - .$self.1.1.-inchannels.$i configure -state $s - incr i - } - set i 0 - foreach chan $@outchannels { - if {$i<$outdev_len} {set s "readonly"} else {set s "disabled"} - .$self.1.1.-outchannels.$i configure -state $s - incr i - } -} -def ServerPrefsDialogue init {} { - netsend [list pd audio-properties] - $self init_reverse_hash - $self read - super reset cancel apply ok - # pd pd midi-properties -} -def ServerPrefsDialogue dropmenu_set {frame var part val} { - set trim_part [string trimleft $part "-"] - set trim_var [string trimleft $var "-"] - if {$var == "audio_api_choice"} { - foreach api $::pd_apilist { - if {$trim_part == [string tolower [lindex $api 0]]} { - netsend [list pd audio-setapi [lindex $api 1]] - after 1 [netsend [list pd audio-properties]] - } - } - } else { - set ::_($self:${trim_var}0) $part - } - super $frame $var $part $val -} -#used by choice and devlist -def ServerPrefsDialogue dropmenu_open {f name} { - set trim_name [string trimleft $name "-"] - if {$trim_name != "audio_api_choice"} { - set i 0 - set m $f.menu - $m delete 0 end - foreach part $@$trim_name { - $m add command -label $part -command [list $self dropmenu_set $f $name $part $i] - incr i - } - } - super $f -} - -#################### ClientPrefsDialogue -set ddrc_options { -section Client section_color - subsection Client canvas_color - color Canvas bgedit - color Canvas bgrun - color Canvas grid - subsection Client object_color - color View bg - color View fg - color View frame1 - color View frame2 - color View frame3 - color Comment bg - color Comment fg - color Comment frame1 - color Comment frame2 - color Comment frame3 - color View selectframe - font View font - subsection Client wire_color - color Wire fg - color Wire dspfg - color Wire fg2 - color FutureWire dash - subsection Client others_color - color Box inletfg - color Box outletfg - color SelRect rect - font KeyboardDialogue font - font Console font -section Client keys - subsection Client put - key Canvas Object - key Canvas Message - key Canvas {Number nbx} - key Canvas Symbol - key Canvas Comment - key Canvas bng - key Canvas tgl - key Canvas {vsl hsl} - key Canvas {vradio hradio} - key Canvas vu - key Canvas cnv - key Canvas Graph - key Canvas Array - subsection Client edit - key Canvas {cut copy} - key Canvas {undo redo} - key Canvas {paste duplicate} - key Canvas select_all - key Canvas clear_selection - key Canvas {reload redraw} - key Canvas editmodeswitch - key Canvas {insert_object chain_object} - key Canvas {clear_wires auto_wire} - key Canvas subpatcherize - subsection Client general - key Canvas Pdwindow - key Canvas {new_file open_file} - key Canvas {save save_as} - key Client {server_prefs client_prefs} - key Canvas {close quit} - key Canvas {find find_again} - key Canvas {audio_on audio_off} - key Client {audio_settings midi_settings} - key Client test_audio_and_midi - key Canvas {load_meter latency_meter} - key Canvas about - subsection Canvas keynav - key Canvas {key_nav_up key_nav_up_shift} - key Canvas {key_nav_down key_nav_down_shift} - key Canvas {key_nav_right key_nav_right_shift} - key Canvas {key_nav_left key_nav_left_shift} - key Canvas key_nav_ioselect -section Client others - toggle Canvas hairstate - toggle Canvas hairsnap - toggle Canvas gridstate - integer Canvas grid_size - toggle Canvas snap_grid - toggle Canvas buttonbar - toggle Canvas statusbar - toggle Canvas menubar - toggle Canvas scrollbar - toggle View tooltip - toggle Wire wirearrow - integer Client console - language View language - language View language2 - integer Canvas pointer_sense -} - -class_new ClientPrefsDialogue {PagedDialogue} -def ClientPrefsDialogue apply {} {$self write; $self do_apply} -def ClientPrefsDialogue read {} {read_ddrc} -def ClientPrefsDialogue do_apply {} { - foreach canvas $::window_list { - if {[$canvas class] == "Canvas"} { - $canvas activate_menubar= [$canvas look menubar] - $canvas activate_buttonbar= [$canvas look buttonbar] - $canvas activate_statusbar= [$canvas look statusbar] - $canvas activate_scrollbars= [$canvas look scrollbar] - $canvas activate_grid= [$canvas look gridstate] - $canvas redraw - } - } -} -def ClientPrefsDialogue write {} { - global look key - $self get_val - set fd [open $::cmdline(ddrcfilename) w] - foreach category {look key} { - set class_list {} - puts $fd "$category \{" - foreach name [array names $category] { - mset {class var} [split $name ":"] - lappend class_list $class - } - set class_list [luniq [lsort $class_list]] - foreach class $class_list { - puts $fd " $class \{" - foreach name [lsort [array names $category -glob $class:*]] { - mset {class var} [split $name ":"] - # the eval here annoys me a bit because of possible special chars -- matju - puts $fd " $var [eval list \$${category}($class:$var)]" - #puts " $var $category $class $var" - } - puts $fd " \}" - } - puts $fd "\}" - } - close $fd -} -#this retrieves the values set in the editor -def ClientPrefsDialogue get_val {} { - global ddrc_options look key accels - set check_key {} - foreach {type class name} $ddrc_options { - switch -regexp -- $type { - color { - set str [string tolower $class$name] - set look($class:$name) $@$str - } - key { - foreach item $name { - set new_key $@$item - set old_key $key($class:$item) - if {$key($class:$item) != $new_key} { - if {[dict exists $accels $old_key]} { - set cmd [dict get $accels $old_key] - set accels [dict remove $accels $old_key] - dict set accels $new_key $cmd - } - } - if {[dict exists $check_key $new_key] && $new_key != ""} { - error "$new_key already assigned" - } else {dict set check_key $new_key key($item)} - set key($class:$item) $new_key - } - } - toggle {set look($class:$name) $@$name} - integer {set look($class:$name) $@$name} - choice|language { - if {$@$name == "autolanguage"} {set l auto} {set l $@$name} - set look($class:$name) $l - } - #font {set look(View:font) $@str} - } - } -} -def ClientPrefsDialogue reset {} { - # this should reload defaults.ddrc ? -} -def ClientPrefsDialogue revert {} { - # this should reload currently used settings ? -} -def ClientPrefsDialogue init {} { - global look key - super cancel apply ok - #super cancel reset revert apply ok - set f .$self.1 - set section 0 - set subsection 0 - set @label_width 200 ;# 24 - foreach {type class names} $::ddrc_options { - set name [lindex [split $names |] 0] - switch $type { void { set type toggle }} - switch $type { - section { - incr section - $@nb add [ttk::notebook $@nb.$section] -text [say $name] - set which_section $f.$section - set which_self $self - set subsection 0 - } - subsection { - set subself $self.1.$section - .$subself add [frame .$subself.[incr subsection]] -text [say $name] - set which_section .$subself.$subsection - set which_self $subself - } - language { - set @$name $look(View:$name) - say autolanguage "[say auto] ([say [lindex [figure_out_language [guess_lang]] 1]])" - $self add $which_section [list $name choice -choices [concat autolanguage $::langoptions]] - } - color { - set str [string tolower $class$name] - set @$str $look($class:$name) - $self add $which_section [list $str $type] - } - key { - foreach item $name {set @$item $key($class:$item)} - $self add $which_section [list $name $type] - } - toggle { - set @$name $look($class:$name) - $self add $which_section [list $name $type] - } - font { - set str [string tolower $class$name] - set @$str $look($class:$name) - $self add $which_section [list $str $type $class] - } - default { - switch $name { - console {set @$name $look(Client:console)} - pointer_sense {set @$name $look(Canvas:pointer_sense)} - grid_size {set @$name $look(Canvas:grid_size)} - default {} - } - $self add $which_section [list $name $type] - } - } - } -} -def ClientPrefsDialogue dropmenu_set {frame var part val} {set @$var $part; $frame.butt configure -text [say $part]} -def ClientPrefsDialogue dropmenu_open {f name} {super $f} - -############ find dialogue ########### - -class_new FindDialogue {Dialogue} -def FindDialogue init {canvas} { - super cancel find - set @canvas $canvas - set @break 0 - set f .$self - $self add $f [list "string" "entry"] - focus .find.string.entry -} -def FindDialogue find {} {$self ok} -def FindDialogue ok {} { - $@canvas find_string= $@string - $@canvas search - super -} -############ other stuff ######### - -def Client client_class_tree {} {ClientClassTreeDialogue new} -class_new ClientClassTreeDialogue {Dialogue} - -proc* place_stuff {args} {} - -def ClientClassTreeDialogue make_row {w tree} { - pack [frame $w] -fill x - pack [frame $w.row] -side top -fill x - pack [button $w.row.butt -image icon_minus] -side left - pack [label $w.row.label -text [lindex $tree 0]] -side left -fill x - pack [frame $w.dent -width 32] -side left - set i 1 - foreach node [lrange $tree 1 end] { - $self make_row $w.$i $node - incr i - } -} -def ClientClassTreeDialogue init {} { - super close - pack [frame .$self.1 -width 600 -height 400] -fill y -expand y - pack [frame .$self.1.1 -width 600 -height 400 -bg "#6688aa"] -side left -fill y -expand y - # "$w.1.scroll set" - # i'd like a scrollable frame - pack [scrollbar .$self.1.scroll -command "ClientClassTreeDialogue_scroll $self"] -side left -fill y -expand y - place [frame .$self.1.1.tree] -x 0 -y 0 - set w .$self.1.1.tree.1 - $self make_row $w [Thing get_hierarchy] - after 100 "$self update_scrollbar" -} -def ClientClassTreeDialogue update_scrollbar {} { - set w .$self.1.1 - set zy [winfo height $w] - set sy [winfo height $w.tree] - set y1 [expr 0.0-[winfo y $w.tree]] - set y2 [expr 0.0+$y1+$zy] - .$self.1.scroll set [expr $y1/$sy] [expr $y2/$sy] -} -def ClientClassTreeDialogue scroll {args} { - set w .$self.1.1 - set zy [winfo height $w] - set sy [winfo height $w.tree] - switch [lindex $args 0] { - moveto { - set y [clip [expr (0.0-[lindex $args 1])*$sy] [expr $zy-$sy] 0] - place .$self.1.1.tree -x 0 -y $y - puts "args=[list $args] zy=$zy sy=$sy y=$y" - } - scroll { - } - } - after 100 "$self update_scrollbar" -} - -class_new AboutDialogue {Dialogue} -def AboutDialogue init {} { - super close - wm title .$self "About DesireData" - pack [label .$self.title -text $::pd_version -font {helvetica 18}] -side top - pack [text .$self.text -yscrollcommand ".$self.scroll set" -width 72 -height 36] -side left -fill both -expand yes - pack [scrollbar .$self.scroll -command ".$self.text yview"] -side right -fill y -expand yes -#12345678901234567890123456789012345678901234567890123456789012345678901 <- 72 chars - .$self.text insert 0.0 \ -"DesireData is a free (libre) real-time computer programming language -interpreter focused on realtime audio and video. -You can get DesireData from http://desiredata.goto10.org/ - -DesireData and PureData work on Linux, MacOSX, Windows, and others. - -PureData is copyrighted, but is free for you to use for any reasonable -purpose, according to the SIBSD license. DesireData's client section -also is free, according to the GPL license. DesireData's server section -is an adaptation of the PureData code and is also using the SIBSD -license. - -(insert here: links to both licenses) - -Credits: - DesireData server: Mathieu Bouchard - DesireData client: Mathieu Bouchard & Chun Lee - PureData: Miller Puckette feat. Thomas Musil, - Günther Geiger, Krzysztof Czaja, Iohannes Zmölnig & others. - - Translations: - Français (French): Patrice Colet - Català (Catalan): Núria Verges - Español (Spanish): Mario Mora, Ramiro Cosentino - Deutsch (German): Max Neupert, Georg Holzmann, Thomas Grill - Norsk Bokmål (Norwegian): Gisle Frøysland - Português (Portuguese): Nuno Godinho - Português do Brasil (Brazilian Portuguese): Carlos Paulino - Italiano (Italian): Davide Morelli, Federico Ferri - Euskara (Basque): Ibon Rodriguez Garcia - Nihongo (Japanese): Kentaro Fukuchi - Polski (Polish): Michal Seta - Dansk (Danish): Steffen Leve Poulsen - Zong wen (Chinese): Chun Lee - Nederlands (Dutch): Tim Vets - Türkçe (Turkish): Koray Tahiroglu - Russkij (Russian): Ilya Dmitrichenko - -Much more documentation and other resources at http://puredata.info/ -The Pd mailing list archive at http://lists.puredata.info/pipermail/pd-list/ - -(insert here: link to \"reference documentation for Pd\", that is, chapter 1)" - - # this looks bad on OSX, iirc - .$self.text configure -state disabled -} - -set manager [Manager new] - -def Class post_hierarchy {{i 0}} { - post %*s%s [expr $i*2] "" $self - foreach sub $@subclasses {$sub post_hierarchy [expr $i+1]} -} -def Class get_hierarchy {} { - set l [list $self] - foreach sub $@subclasses {lappend l [$sub get_hierarchy]} - return $l -} - -# Thing post_hierarchy - -#---------------------------------------------------------------- -class_new ClipboardDialogue {Dialogue} -def ClipboardDialogue init {clipboard} { - super close - set @clipboard $clipboard - wm title .$self "Clipboard" - pack [text .$self.text -yscrollcommand ".$self.scroll set" -width 72] -side left -fill both -expand yes - pack [scrollbar .$self.scroll -command ".$self.text yview"] -side right -fill y - $@clipboard subscribe $self - $self notice -} -def ClipboardDialogue notice {args} { - .$self.text delete 0.0 end - .$self.text insert 0.0 [$@clipboard value] -} -def ClipboardDialogue delete {} { - $@clipboard unsubscribe $self - super -} - -#---------------------------------------------------------------- -class_new ListDialogue {Dialogue} -def ListDialogue init {history title} { - super close - set @history $history - wm title .$self $title - frame .$self.1 - pack [listbox .$self.1.list -yscrollcommand ".$self.1.scroll set" -width 72 -height 20] -side left -fill both -expand yes - pack [scrollbar .$self.1.scroll -command ".$self.1.list yview"] -side right -fill y - pack .$self.1 - $@history subscribe $self - $self notice -} -def ListDialogue listbox {} {return .$self.1.list} -def ListDialogue notice {args} { - set w [$self listbox] - $w delete 0 end - foreach e [$@history list] {$w insert end $e} - $w see end -} -def ListDialogue delete {} { - $@history unsubscribe $self - super -} - -class_new EventHistoryDialogue {ListDialogue} -def EventHistoryDialogue init {history} { - super $history [say event_history_view] - pack [checkbutton .$self.hide -text [say hide_key_release]] -fill x - [$self listbox] configure -font {Mono -10} -} - -#---------------------------------------------------------------- -#class_new Splash {Thing} -#def Splash init {} { -# toplevel .$self -# frame .$self.f -# canvas .$self.f.canvas -# image create photo .dd -format GIF -file desiredata.gif -# .$self.f.canvas create image 0 0 -image .dd -# pack .$self.f.canvas -# pack .$self.f -#} - -class_new KeyboardDialogue {Dialogue} - -set keyboard_layouts { - { - {9 " " 67 68 69 70 " " 71 72 73 74 " " 75 76 95 96} - {49 10 11 12 13 14 15 16 17 18 19 20 21 22} - {23 24 25 26 27 28 29 30 31 32 33 34 35 51} - {66 38 39 40 41 42 43 44 45 46 47 48 36} - {50 52 53 54 55 56 57 58 59 60 61 62} - {37 115 64 65 113 116 117 109} - } { - {" " " " 98 " "} - {100 " " " " 102} - {" " " " 104 " "} - {" "} - {" " " " 4 " "} - {1 2 3} - {" " " " 5 " "} - } -} - -foreach {k v} { - 9 5 - 22 5 - 23 4 51 4 - 66 5 36 7 - 50 8 62 8 - 37 4 115 4 64 4 65 24 113 4 116 4 117 4 109 4 - 98 2 100 2 102 2 104 2 - 1 2 2 2 3 2 4 2 5 2 -} {set keyboard_width_of($k) $v} - -proc namekey {i args} {foreach name $args {set ::keyboard_text_of($i) $name; incr i}} -namekey 9 Esc -namekey 67 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 -namekey 95 F11 F12 -namekey 49 ` -namekey 10 "1 !" "2 @" "3 #" "4 \$" "5 %" "6 ^" "7 &" "8 *" "9 (" "0 )" "- _" "= +" BkSp -namekey 23 Tab Q W E R T Y U I O P "\{ \[" "\} \]" -namekey 51 "\\ |" -namekey 66 Caps -namekey 38 A S D F G H J K L "\; :" "' \"" -namekey 36 Return -namekey 50 Shift -namekey 52 Z X C V B N M ", <" ". >" "/ ?" Shift -namekey 37 Ctrl -namekey 115 Sup -namekey 64 Alt Space -namekey 113 AltGr -namekey 116 Sup Menu -namekey 109 Ctrl -namekey 98 (up) -namekey 100 (left) -namekey 102 (right) -namekey 104 (down) -namekey 1 1 2 3 4 5 -#mouse clicks - -def KeyboardDialogue init {history} { - super close - set @history $history - set @fade [dict create] - wm title .$self "Keyboard View" ;# say - set i 0; set j 0 - set @names {key misc} - frame .$self.board - set layouts {::keyboard_layout ::keyboard_layout2} - set @keycount 0 - foreach layout $::keyboard_layouts { - $self pack_keys $layout [lindex $@names $i] [llength [lindex $::keyboard_layouts [expr $i-1]]] - incr i - } - pack .$self.board - $@history subscribe $self - $self fade -} - -def KeyboardDialogue pack_keys {keys name off} { - set i $off - frame .$self.board.$name - foreach row $keys { - frame .$self.board.$name.$i - foreach key $row { - if {$key==" "} { - pack [label .$self.board.$name.$i.shim$@keycount -image icon_empty] -side left - incr @keycount - continue - } - set ::keyboard_row_of($key) $i - if {[info exists ::keyboard_width_of($key)]} {set width $::keyboard_width_of($key)} else {set width 3} - if {[info exists ::keyboard_text_of($key)]} {set text $::keyboard_text_of($key) } else {set text $key} - if {[regexp {\((\w+)\)} $text foo bar]} { - set font [$self look font] - pack [label .$self.board.$name.$i.key$key -image icon_$bar -relief raise -border 4 \ - -side left -bg "#dddddd" -width [expr $width*[font measure $font 0]] \ - -height [font metrics $font -linespace]] - } else { - pack [label .$self.board.$name.$i.key$key -text " $text " -relief raise -border 4 \ - -side left -bg "#dddddd" -width $width -font [$self look font]] - } - } - pack .$self.board.$name.$i -fill x - if {$i==0} {pack [label .$self.board.$name.shim -image icon_empty] -fill x -expand yes} - incr i - } - switch $name { - key {pack .$self.board.key -side left} - misc {pack .$self.board.misc -side right} - } -} - -def KeyboardDialogue notice {origin add event} { - mset {type W x y mod K k} $event - if {![info exists ::keyboard_row_of($k)]} {puts "unknown key $k"; return} - set i $::keyboard_row_of($k) - if {$i<[llength [lindex $::keyboard_layouts 0]]} {set section "key"} else {set section "misc"} - switch -regexp -- $type { - ^KeyPress|ButtonPress$ { - if { [dict exists $@fade $k]} {dict unset @fade $k} - .$self.board.$section.$i.key$k configure -bg "#ff0000" - } - ^KeyRelease|ButtonRelease$ {if {![dict exists $@fade $k]} {dict set @fade $k 255}} - } -} - -def KeyboardDialogue fade {} { - foreach {k v} $@fade { - incr v -85 - if {$v<0} {set v 0} - set r [expr 221+$v*2/15] - set g [expr 221-$v*13/15] - set i $::keyboard_row_of($k) - if {$i<[llength [lindex $::keyboard_layouts 0]]} {set section "key"} else {set section "misc"} - .$self.board.$section.$i.key$k configure -bg [format #%02x%02x%02x $r $g $g] - if {$v} {dict set @fade $k $v} {dict unset @fade $k} - } - set @after [after 100 "$self fade"] -} - -def KeyboardDialogue delete {} { - $@history unsubscribe $self - after cancel $@after - super -} - -#---------------------------------------------------------------- -# Deconstructors - -def Wire deconstruct {{selcanvas ""}} { - # the selcanvas system could be abstracted out using an ObjectList such that - # Canvas<ObjectList and $selection class == ObjectList - if {$selcanvas == ""} { - list #X connect \ - [[$@canvas objects] search $@from] $@outlet \ - [[$@canvas objects] search $@to] $@inlet - } { - list #X connect \ - $::obj_index_sel($@canvas:$@from) $@outlet \ - $::obj_index_sel($@canvas:$@to) $@inlet - } -} - -def MessageBox deconstruct {} {concat [list #X msg $@x1 $@y1] $@text} -def FloatBox deconstruct {} {concat [list #X floatatom $@x1 $@y1] $@w $@min $@max $@pos $@lab $@snd $@rcv} -def SymbolBox deconstruct {} {concat [list #X symbolatom $@x1 $@y1] $@w $@min $@max $@pos $@lab $@snd $@rcv} -def Comment deconstruct {} {concat [list #X text $@x1 $@y1] $@text} - -def Box deconstruct {} { - if {[array names ::fields -exact $@pdclass] == ""} { - return [concat [list #X obj $@x1 $@y1] $@text] - } { - set r {} - foreach field $::fields($@pdclass) {lappend r $_($self:$field)} - return $r - } -} - -def View deconstruct_to {stream args} { - $stream << [philtre [eval [concat [list $self deconstruct] $args]]] - $stream << ";\n" -} - -def Canvas deconstruct {} { - return [concat [list #X restore $@x1 $@y1] $@text] -} -def Canvas deconstruct_to {stream args} { - set r [concat [list #N canvas] $@canvas_pos $@canvas_size] - if {$@subpatch || $@abs} {lappend r $@name $@mapped} else {lappend r $@fontsize} - $stream << "[philtre $r];\n" - foreach i [lsort -integer [$@objects keys]] {eval [concat [list [$@objects get $i] deconstruct_to $stream]]} - foreach i [lsort -integer [ $@wires keys]] {eval [concat [list [ $@wires get $i] deconstruct_to $stream]]} - $stream << [philtre [eval [concat [list $self deconstruct] $args]]] - $stream << ";\n" -} - -#---------------------------------------------------------------- -# openpanel & savepanel - -proc pdtk_openpanel {target localdir} { - if {$localdir == ""} {set localdir $::pd_opendir} - set filename [tk_getOpenFile -parent $::current_window -initialdir $localdir] - if {$filename != ""} { - set directory [string range $filename 0 [expr [string last / $filename]-1]] - set pd_opendir $directory - netsend [list $target callback [enquote $filename]] - } -} - -proc pdtk_savepanel {target localdir} { - if {$localdir == ""} { - set filename [tk_getSaveFile -parent $::current_window] - } else { - set filename [tk_getSaveFile -parent $::current_window -initialdir $localdir] - } - if {$filename != ""} { - netsend [list $target callback [enquote $filename]] - } -} - -#---------------------------------------------------------------- -# To err is human. - -#proc bgerror {err} { -# set info [error_dump] -# tk_messageBox2 -message "$err: $info" -type ok -#} - -class_new OopsDialogue {Dialogue} - -def OopsDialogue init {sig1 sig2 where} { - super damn - wm title .$self [say oops] - pack [label .$self.head -text $sig2 -font {Helvetica -14 bold}] -side top - pack [label .$self.note -text [say oops_text]] -side top - pack [text .$self.text -yscrollcommand ".$self.scroll set" -width 108 -height 15] -side left -fill both -expand 1 - pack [scrollbar .$self.scroll -command ".$self.text yview"] -side right -fill y - .$self.text insert 0.0 $where -} - -# Nous sommes donc en présence d'un incendie. C'est normal... -def OopsDialogue damn {} {$self ok} - -#---------------------------------------------------------------- - -set main [Client new] -set window_list [list $main] - -def Canvas auto_test {} { - $self editmode= 1 - $self select_all - $self selection_move +10 0 - $self selection_move +10 0 - $self selection_move +10 0 -} - -#----------------------------------------------------------------- -def Canvas visual_diff {} { - if {$@blinky != ""} { - .$self.c delete BLINKY - after cancel $@blinky - set @blinky "" - return - } - set filename [$self name] - set initialfile "" - foreach suffix {gif jpg jpeg png} { - set t [$self folder]/$filename.$suffix - post %s $t - if {[file exist $t]} {set initialfile $filename.$suffix; break} - } - set filename [tk_getOpenFile -parent $::current_window -defaultextension .pd \ - -filetypes $::image_filetypes -initialdir [$self folder] -initialfile $initialfile] - if {$filename == ""} {return} - image create photo image_$self -file $filename - $self blink_image -} - -def Canvas blink_image {} { - set @blinky [after 300 [list $self blink_image]] - if {[llength [.$self.c gettags BLINKY]]} { - .$self.c delete BLINKY - } else { - # there's something that causes the pd screenshot to be off by 1 pixel. i don't know what. - .$self.c create image 0 -1 -image image_$self -tag BLINKY -anchor nw - } -} - -#----------------------------------------------------------------- - -proc widget_tree {w {indent 0}} { - foreach element [winfo children $w] { - puts [format "%*s%s" [expr 2*$indent] "" $element] - widget_tree $element [expr 2+$indent] - } -} - -if 0 { -def Canvas :-) {} { - if {![info exists ::pd_path]} {netsend [list pd update-path]} - if {![info exists ::class_list]} {return [netsend [list pd update-class-list $self :-)]]} - search_for_externs - set class_list [luniq [lsort $::class_list]] - set n 0 - post "there are [llength $::class_list] classes" - foreach c $::class_list { - netsend [list .$self obj [expr int(1050*rand())] [expr int(650*rand())] $c] - incr n - if {$n>1500} {return "stopped at $n"} - } - return "finished" -} -} - -def Canvas :-) {} { - if {![info exists ::pd_path]} {netsend [list pd update-path]} - if {![info exists ::class_list]} {return [netsend [list pd update-class-list $self :-)]]} - search_for_externs - set ::class_list [luniq [lsort $::class_list]] - post "there are [llength $::class_list] classes" - $self :-)2 1000 "" -} - -def Canvas :-)2 {n meuh} { - if {$n >= [llength $::class_list]} {return} - set c [lindex $::class_list $n] - set x [expr int(1050*rand())]; set y [expr int(650*rand())] - set x [expr int($n/36)*16]; set y [expr ($n%36)*18] - puts ":-) $c" - netsend [list .$self obj $x $y $c] [list $self :-)2 [expr {$n+1}]] - #if {$n>1500} {post "stopped at %d" $n} -} - -proc pd {args} {post %s "what is 'proc pd' ?"} |