aboutsummaryrefslogtreecommitdiff
path: root/test/toxy/kb.wid
blob: 901db158611176212853018ebfa0392ffc4caa37 (plain)
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
proc ::toxy::kbout {path target remote oldchord newchord} {
    foreach key $oldchord {
	pd [concat $target _cb [lindex $key 0] 0 \;]
	if {$remote != "."} {
	    pd [concat $remote [lindex $key 0] 0 \;]
	}
    }
    foreach key $newchord {
	pd [concat $target _cb [lindex $key 0] [lindex $key 1] \;]
	if {$remote != "."} {
	    pd [concat $remote [lindex $key 0] [lindex $key 1] \;]
	}
    }
}

proc ::toxy::kbput {path target remote keys appendmode doout} {
    set oldchord {}
    set newchord {}
    if {$appendmode} {
	foreach key $keys {
	    set ndx [lindex $key 0]
# FIXME upper limit
	    if {$ndx >= 0} {
		if {$appendmode == 1} {
		    set found \
			[lsearch $::toxy::kbchord($target) [concat $ndx *]]
		} else { set found -1 }
		if {$found < 0} {
		    $path itemconfig $path.$ndx -fill grey
		    lappend newchord $key
		    lappend ::toxy::kbchord($target) $key
		} else {
		    $path itemconfig $path.$ndx \
			-fill [lindex [$path gettags $path.$ndx] 2]
		    lappend oldchord $key
		    set ::toxy::kbchord($target) \
			[lreplace $::toxy::kbchord($target) $found $found]
		}
	    }
	}
# FIXME oldchord
	set ::toxy::kbchord($target) \
	    [lsort -unique -integer -index 0 $::toxy::kbchord($target)]
    } else {
	set oldchord $::toxy::kbchord($target)
	foreach key $::toxy::kbchord($target) {
	    set ndx [lindex $key 0]
	    $path itemconfig $path.$ndx \
		-fill [lindex [$path gettags $path.$ndx] 2]
	}
	foreach key $keys {
	    set ndx [lindex $key 0]
# FIXME upper limit
	    if {$ndx >= 0} {
		$path itemconfig $path.$ndx -fill grey
		lappend newchord $key
	    }
	}
	set ::toxy::kbchord($target) [lsort -unique -integer -index 0 $newchord]
    }
    if {$doout} {
	::toxy::kbout $path $target $remote $oldchord $newchord
    }
}

proc ::toxy::kb {path target remote noctaves size} {
# guard against BadAlloc crashes
    if {$size > 10} {set size 10}
    set lft [expr {round(5 * $size)}]
    set top [expr {round(5 * $size)}]
    set bot [expr {round(100 * $size)}]
    set dx [expr {round(17 * $size)}]
    set wid [expr {round($dx - $size * .5)}]
    set blbot [expr {round($bot * .65)}]

    $path config -height [expr {$bot + $top}] \
	-width [expr {$dx * ($noctaves * 7 + 1) + $lft * 2 - 1}]

    bind $path <Enter> +[concat ::toxy::kbenter $path $target]
    bind $path <Leave> +[concat ::toxy::kbleave $path $target]
    bind $path <B1-Motion> \
	 +[concat ::toxy::kbdrag $path $target $remote %X %Y 0]
    bind $path <B1-Shift-Motion> \
	+[concat ::toxy::kbdrag $path $target $remote %X %Y 1]
    bind $path <B1-Control-Motion> \
	+[concat ::toxy::kbdrag $path $target $remote %X %Y 2]

    for {set octave 0} {$octave <= $noctaves} {incr octave} {
	set prevkey 0
	foreach key {0 2 4 5 7 9 11} {
	    set ndx [expr $octave * 12 + $key]
	    set id [$path create rect $lft $top [expr {$lft + $wid}] $bot \
		-fill white -tags "$ndx $path.$ndx white"]
	    $path bind $id <1> \
		[concat ::toxy::kbpress  $path $target $remote $ndx %y 0]
	    $path bind $id <Shift-1> \
		[concat ::toxy::kbpress $path $target $remote $ndx %y 1]
	    $path bind $id <Control-1> \
		[concat ::toxy::kbcontrolon $path $target $remote $ndx %y]
	    $path bind $id <Control-ButtonRelease> \
		[concat ::toxy::kbcontroloff $path $target $remote $ndx]
	    if {$key - $prevkey > 1} {
		incr ndx -1
		set x [expr {$lft - $wid * .22}]
		set id [$path create rect $x $top [expr {$x + $wid * .44}] \
		    $blbot -fill black -tags "$ndx $path.$ndx black"]
		$path bind $id <1> \
		    [concat ::toxy::kbpress $path $target $remote $ndx %y 0]
		$path bind $id <Shift-1> \
		    [concat ::toxy::kbpress $path $target $remote $ndx %y 1]
		$path bind $id <Control-1> \
		    [concat ::toxy::kbcontrolon $path $target $remote $ndx %y]
		$path bind $id <Control-ButtonRelease> \
		    [concat ::toxy::kbcontroloff $path $target $remote $ndx]
	    }
	    set prevkey $key
	    incr lft $dx
	    if {$octave == $noctaves && $key == 0} break
	}
    }
    set ::toxy::kbisinside($target) 0
    set chord $::toxy::kbchord($target)
    set ::toxy::kbchord($target) {}
    ::toxy::kbput $path $target $remote $chord 0 0
}

proc ::toxy::kbgetvel {path ndx y} {
    set g [$path coords $path.$ndx]
    set top [lindex $g 1]
    set bot [lindex $g 3]
    set vel [expr 100.0 - 99.0 * ($top - $y) / ($top - $bot)]
    if {$vel < 1.0} {set vel 1.0} elseif {$vel > 100.0} {set vel 100.0}
    return $vel
}

proc ::toxy::kbcontrolon {path target remote ndx y} {
    if {[$path cget -state] == "normal"} {
	$path itemconfig $path.$ndx -fill red
	::toxy::kbout $path $target $remote {} \
	    [list [concat $ndx [::toxy::kbgetvel $path $ndx $y]]]
    }
}

proc ::toxy::kbcontroloff {path target remote ndx} {
    if {[$path cget -state] == "normal"} {
	if {[lsearch $::toxy::kbchord($target) [concat $ndx *]] < 0} {
	    $path itemconfig $path.$ndx \
		-fill [lindex [$path gettags $path.$ndx] 2]
	} else {
	    $path itemconfig $path.$ndx -fill grey
	}
	::toxy::kbout $path $target $remote [list [concat $ndx 0]] {}
    }
}

proc ::toxy::kbpress {path target remote ndx y shift} {
    if {[$path cget -state] == "normal"} {
	::toxy::kbput $path $target $remote \
	    [list [concat $ndx [::toxy::kbgetvel $path $ndx $y]]] $shift 1
    }
}

proc ::toxy::kbdrag {path target remote rx ry shift} {
    if {$shift <= 1 && $::toxy::kbisinside($target) && \
	    [$path cget -state] == "normal"} {
	set x [expr $rx - [winfo rootx $path]]
	set y [expr $ry - [winfo rooty $path]]
	set ndx [lindex [$path gettags [$path find closest $x $y]] 0]
	if {[lsearch $::toxy::kbchord($target) [concat $ndx *]] < 0} {
	    ::toxy::kbput $path $target $remote \
		[list [concat $ndx [::toxy::kbgetvel $path $ndx $y]]] $shift 1
	}
    }
}

proc ::toxy::kbenter {path target} {
    set ::toxy::kbisinside($target) 1
}

proc ::toxy::kbleave {path target} {
    set ::toxy::kbisinside($target) 0
}

proc ::toxy::kbbang {path target remote} {
    ::toxy::kbout $path $target $remote {} $::toxy::kbchord($target)
}

proc ::toxy::kbfloat {path target remote ndx} {
    ::toxy::kbput $path $target $remote [list [concat $ndx 50.0]] 0 1
}

proc ::toxy::kblist {path target remote args} {
# LATER (::toxy::kbput ... 1)
}

proc ::toxy::kbset {path target remote args} {
# LATER (::toxy::kbput ... 0)
}

#> kb canvas
#. -bg yellow -cursor hand1
#. #oct 4 #size .75
#. @bang ::toxy::kbbang .- .| .
#. @float ::toxy::kbfloat .- .| . .#1
#. @list ::toxy::kblist .- .| . .#args
#. @set ::toxy::kbset .- .| . .#args
#. @clear ::toxy::kbput .- .| . {} 0 1

::toxy::kb .- .| . .#oct .#size

# undo the "bind Canvas <1> {+focus %W}" from the setup.wid
bind .- <FocusIn> {focus .^.c}

#@ new
set ::toxy::kbchord(.|) {}

#@ free
unset ::toxy::kbchord(.|)