1
# ------------------------------------------------------------------------------
3
# This file is part of Unifix BWidget Toolkit
4
# $Id: dropsite.tcl,v 1.1 2004/12/03 00:31:24 tjikkun Exp $
5
# ------------------------------------------------------------------------------
10
# - DropSite::setcursor
11
# - DropSite::setoperation
12
# - DropSite::_update_operation
13
# - DropSite::_compute_operation
14
# - DropSite::_draw_operation
15
# - DropSite::_init_drag
17
# - DropSite::_release
18
# ----------------------------------------------------------------------------
21
namespace eval DropSite {
22
Widget::define DropSite dropsite -classonly
24
Widget::declare DropSite [list \
25
[list -dropovercmd String "" 0] \
26
[list -dropcmd String "" 0] \
27
[list -droptypes String "" 0] \
33
variable _opw ".drag.\#op"
58
if { $tcl_platform(platform) == "unix" } {
59
set _tabops(mod,alt) 8
61
set _tabops(mod,alt) 16
68
copy,img @[file join $::BWIDGET::LIBRARY "images" "opcopy.xbm"] \
69
move,img @[file join $::BWIDGET::LIBRARY "images" "opmove.xbm"] \
70
link,img @[file join $::BWIDGET::LIBRARY "images" "oplink.xbm"]]
72
bind DragTop <KeyPress-Shift_L> {DropSite::_update_operation [expr %s | 1]}
73
bind DragTop <KeyPress-Shift_R> {DropSite::_update_operation [expr %s | 1]}
74
bind DragTop <KeyPress-Control_L> {DropSite::_update_operation [expr %s | 4]}
75
bind DragTop <KeyPress-Control_R> {DropSite::_update_operation [expr %s | 4]}
76
if { $tcl_platform(platform) == "unix" } {
77
bind DragTop <KeyPress-Alt_L> {DropSite::_update_operation [expr %s | 8]}
78
bind DragTop <KeyPress-Alt_R> {DropSite::_update_operation [expr %s | 8]}
80
bind DragTop <KeyPress-Alt_L> {DropSite::_update_operation [expr %s | 16]}
81
bind DragTop <KeyPress-Alt_R> {DropSite::_update_operation [expr %s | 16]}
84
bind DragTop <KeyRelease-Shift_L> {DropSite::_update_operation [expr %s & ~1]}
85
bind DragTop <KeyRelease-Shift_R> {DropSite::_update_operation [expr %s & ~1]}
86
bind DragTop <KeyRelease-Control_L> {DropSite::_update_operation [expr %s & ~4]}
87
bind DragTop <KeyRelease-Control_R> {DropSite::_update_operation [expr %s & ~4]}
88
if { $tcl_platform(platform) == "unix" } {
89
bind DragTop <KeyRelease-Alt_L> {DropSite::_update_operation [expr %s & ~8]}
90
bind DragTop <KeyRelease-Alt_R> {DropSite::_update_operation [expr %s & ~8]}
92
bind DragTop <KeyRelease-Alt_L> {DropSite::_update_operation [expr %s & ~16]}
93
bind DragTop <KeyRelease-Alt_R> {DropSite::_update_operation [expr %s & ~16]}
98
# ----------------------------------------------------------------------------
99
# Command DropSite::include
100
# ----------------------------------------------------------------------------
101
proc DropSite::include { class types } {
102
set dropoptions [list \
103
[list -dropenabled Boolean 0 0] \
104
[list -dropovercmd String "" 0] \
105
[list -dropcmd String "" 0] \
106
[list -droptypes String $types 0] \
108
Widget::declare $class $dropoptions
112
# ----------------------------------------------------------------------------
113
# Command DropSite::setdrop
114
# Widget interface to register
115
# ----------------------------------------------------------------------------
116
proc DropSite::setdrop { path subpath dropover drop {force 0}} {
117
set cen [Widget::hasChanged $path -dropenabled en]
118
set ctypes [Widget::hasChanged $path -droptypes types]
120
if { $force || $cen || $ctypes } {
124
-dropovercmd $dropover
132
# ----------------------------------------------------------------------------
133
# Command DropSite::register
134
# ----------------------------------------------------------------------------
135
proc DropSite::register { path args } {
138
upvar \#0 DropSite::$path drop
140
Widget::init DropSite .drop$path $args
141
if { [info exists drop] } {
144
set dropcmd [Widget::getMegawidgetOption .drop$path -dropcmd]
145
set types [Widget::getMegawidgetOption .drop$path -droptypes]
146
set overcmd [Widget::getMegawidgetOption .drop$path -dropovercmd]
147
Widget::destroy .drop$path
148
if { $dropcmd != "" && $types != "" } {
149
set drop(dropcmd) $dropcmd
150
set drop(overcmd) $overcmd
151
foreach {type ops} $types {
152
set drop($type,ops) {}
153
foreach {descop lmod} $ops {
154
if { ![llength $descop] || [llength $descop] > 3 } {
155
return -code error "invalid operation description \"$descop\""
157
foreach {subop baseop imgop} $descop {
158
set subop [string trim $subop]
159
if { ![string length $subop] } {
160
return -code error "sub operation is empty"
162
if { ![string length $baseop] } {
165
if { [info exists drop($type,ops,$subop)] } {
166
return -code error "operation \"$subop\" already defined"
168
if { ![info exists _tabops(ops,$baseop)] } {
169
return -code error "invalid base operation \"$baseop\""
171
if { ![string equal $subop $baseop] &&
172
[info exists _tabops(ops,$subop)] } {
173
return -code error "sub operation \"$subop\" is a base operation"
175
if { ![string length $imgop] } {
176
set imgop $_defops($baseop,img)
179
if { [string equal $lmod "program"] } {
180
set drop($type,ops,$subop) $baseop
181
set drop($type,img,$subop) $imgop
183
if { ![string length $lmod] } {
184
set lmod $_defops($baseop,mod)
188
if { ![info exists _tabops(mod,$mod)] } {
189
return -code error "invalid modifier \"$mod\""
191
set mask [expr {$mask | $_tabops(mod,$mod)}]
193
if { ($mask == 0) != ([string equal $subop "default"]) } {
194
return -code error "sub operation default can only be used with modifier \"none\""
196
set drop($type,mod,$mask) $subop
197
set drop($type,ops,$subop) $baseop
198
set drop($type,img,$subop) $imgop
199
lappend masklist $mask
202
if { ![info exists drop($type,mod,0)] } {
203
set drop($type,mod,0) default
204
set drop($type,ops,default) copy
205
set drop($type,img,default) $_defops(copy,img)
208
set drop($type,ops,force) copy
209
set drop($type,img,force) $_defops(copy,img)
210
foreach mask [lsort -integer -decreasing $masklist] {
211
lappend drop($type,ops) $mask $drop($type,mod,$mask)
218
# ----------------------------------------------------------------------------
219
# Command DropSite::setcursor
220
# ----------------------------------------------------------------------------
221
proc DropSite::setcursor { cursor } {
222
catch {.drag configure -cursor $cursor}
226
# ----------------------------------------------------------------------------
227
# Command DropSite::setoperation
228
# ----------------------------------------------------------------------------
229
proc DropSite::setoperation { op } {
234
upvar \#0 DropSite::$_target drop
236
if { [info exist drop($_type,ops,$op)] &&
237
$_dragops($drop($_type,ops,$op)) } {
240
# force to a copy operation
246
# ----------------------------------------------------------------------------
247
# Command DropSite::_init_drag
248
# ----------------------------------------------------------------------------
249
proc DropSite::_init_drag { top evt source state X Y type ops data } {
261
if {[info exists _dragops]} {
264
array set _dragops {copy 1 move 0 link 0}
275
label $_opw -relief flat -bd 0 -highlightthickness 0 \
276
-foreground black -background white
278
bind $top <ButtonRelease-$evt> {DropSite::_release %X %Y}
279
bind $top <B$evt-Motion> {DropSite::_motion %X %Y}
280
bind $top <Motion> {DropSite::_release %X %Y}
287
# ----------------------------------------------------------------------------
288
# Command DropSite::_update_operation
289
# ----------------------------------------------------------------------------
290
proc DropSite::_update_operation { state } {
295
if { $_status & 3 } {
297
_motion [winfo pointerx $_top] [winfo pointery $_top]
302
# ----------------------------------------------------------------------------
303
# Command DropSite::_compute_operation
304
# ----------------------------------------------------------------------------
305
proc DropSite::_compute_operation { target state type } {
308
upvar \#0 DropSite::$target drop
310
foreach {mask op} $drop($type,ops) {
311
if { ($state & $mask) == $mask } {
312
if { $_dragops($drop($type,ops,$op)) } {
322
# ----------------------------------------------------------------------------
323
# Command DropSite::_draw_operation
324
# ----------------------------------------------------------------------------
325
proc DropSite::_draw_operation { target type } {
332
upvar \#0 DropSite::$target drop
334
if { !($_status & 1) } {
335
catch {place forget $_opw}
340
if { ![info exist drop($type,ops,$_curop)] ||
341
!$_dragops($drop($type,ops,$_curop)) } {
342
# force to a copy operation
345
$_opw configure -bitmap $_tabops(img,copy)
346
place $_opw -relx 1 -rely 1 -anchor se
349
} elseif { [string equal $_curop "default"] } {
350
catch {place forget $_opw}
353
$_opw configure -bitmap $drop($type,img,$_curop)
354
place $_opw -relx 1 -rely 1 -anchor se
360
# ----------------------------------------------------------------------------
361
# Command DropSite::_motion
362
# ----------------------------------------------------------------------------
363
proc DropSite::_motion { X Y } {
374
set script [bind $_top <B$_evt-Motion>]
375
bind $_top <B$_evt-Motion> {}
376
bind $_top <Motion> {}
377
wm geometry $_top "+[expr {$X+1}]+[expr {$Y+1}]"
379
if { ![winfo exists $_top] } {
382
set path [winfo containing $X $Y]
383
if { ![string equal $path $_target] } {
384
# path != current target
385
if { $_status & 2 } {
386
# current target is valid and has recall status
387
# generate leave event
388
upvar \#0 DropSite::$_target drop
389
uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data]
392
upvar \#0 DropSite::$_target drop
393
if { [info exists drop($_type,ops)] } {
394
# path is a valid target
395
_compute_operation $_target $_state $_type
396
if { $drop(overcmd) != "" } {
397
set arg [list $_target $_source enter $X $Y $_curop $_type $_data]
398
set _status [uplevel \#0 $drop(overcmd) $arg]
401
catch {$_top configure -cursor based_arrow_down}
403
_draw_operation $_target $_type
406
bind $_top <B$_evt-Motion> {DropSite::_motion %X %Y}
407
bind $_top <Motion> {DropSite::_release %X %Y}
412
catch {$_top configure -cursor dot}
413
_draw_operation "" ""
415
} elseif { $_status & 2 } {
416
upvar \#0 DropSite::$_target drop
417
_compute_operation $_target $_state $_type
418
set arg [list $_target $_source motion $X $Y $_curop $_type $_data]
419
set _status [uplevel \#0 $drop(overcmd) $arg]
420
_draw_operation $_target $_type
424
bind $_top <B$_evt-Motion> {DropSite::_motion %X %Y}
425
bind $_top <Motion> {DropSite::_release %X %Y}
431
# ----------------------------------------------------------------------------
432
# Command DropSite::_release
433
# ----------------------------------------------------------------------------
434
proc DropSite::_release { X Y } {
442
if { $_status & 1 } {
443
upvar \#0 DropSite::$_target drop
445
set res [uplevel \#0 $drop(dropcmd) [list $_target $_source $X $Y $_curop $_type $_data]]
446
DragSite::_end_drag $_source $_target $drop($_type,ops,$_curop) $_type $_data $res
448
if { $_status & 2 } {
450
upvar \#0 DropSite::$_target drop
451
uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data]
453
DragSite::_end_drag $_source "" "" $_type $_data 0