1
# ------------------------------------------------------------------------------
3
# This file is part of Unifix BWidget Toolkit
4
# $Id: dropsite.tcl 10192 2002-01-24 19:25:32Z radim $
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::declare DropSite {
23
{-dropovercmd String "" 0}
24
{-dropcmd String "" 0}
25
{-droptypes String "" 0}
31
variable _opw ".drag.\#op"
56
if { $tcl_platform(platform) == "unix" } {
57
set _tabops(mod,alt) 8
59
set _tabops(mod,alt) 16
66
copy,img @[file join $env(BWIDGET_LIBRARY) "images" "opcopy.xbm"] \
67
move,img @[file join $env(BWIDGET_LIBRARY) "images" "opmove.xbm"] \
68
link,img @[file join $env(BWIDGET_LIBRARY) "images" "oplink.xbm"]]
70
bind DragTop <KeyPress-Shift_L> {DropSite::_update_operation [expr %s | 1]}
71
bind DragTop <KeyPress-Shift_R> {DropSite::_update_operation [expr %s | 1]}
72
bind DragTop <KeyPress-Control_L> {DropSite::_update_operation [expr %s | 4]}
73
bind DragTop <KeyPress-Control_R> {DropSite::_update_operation [expr %s | 4]}
74
if { $tcl_platform(platform) == "unix" } {
75
bind DragTop <KeyPress-Alt_L> {DropSite::_update_operation [expr %s | 8]}
76
bind DragTop <KeyPress-Alt_R> {DropSite::_update_operation [expr %s | 8]}
78
bind DragTop <KeyPress-Alt_L> {DropSite::_update_operation [expr %s | 16]}
79
bind DragTop <KeyPress-Alt_R> {DropSite::_update_operation [expr %s | 16]}
82
bind DragTop <KeyRelease-Shift_L> {DropSite::_update_operation [expr %s & ~1]}
83
bind DragTop <KeyRelease-Shift_R> {DropSite::_update_operation [expr %s & ~1]}
84
bind DragTop <KeyRelease-Control_L> {DropSite::_update_operation [expr %s & ~4]}
85
bind DragTop <KeyRelease-Control_R> {DropSite::_update_operation [expr %s & ~4]}
86
if { $tcl_platform(platform) == "unix" } {
87
bind DragTop <KeyRelease-Alt_L> {DropSite::_update_operation [expr %s & ~8]}
88
bind DragTop <KeyRelease-Alt_R> {DropSite::_update_operation [expr %s & ~8]}
90
bind DragTop <KeyRelease-Alt_L> {DropSite::_update_operation [expr %s & ~16]}
91
bind DragTop <KeyRelease-Alt_R> {DropSite::_update_operation [expr %s & ~16]}
96
# ------------------------------------------------------------------------------
97
# Command DropSite::include
98
# ------------------------------------------------------------------------------
99
proc DropSite::include { class types } {
101
{-dropenabled Boolean 0 0}
102
{-dropovercmd String "" 0}
103
{-dropcmd String "" 0}
105
lappend dropoptions [list -droptypes String $types 0]
106
Widget::declare $class $dropoptions
110
# ------------------------------------------------------------------------------
111
# Command DropSite::setdrop
112
# Widget interface to register
113
# ------------------------------------------------------------------------------
114
proc DropSite::setdrop { path subpath dropover drop {force 0}} {
115
set cen [Widget::hasChanged $path -dropenabled en]
116
set ctypes [Widget::hasChanged $path -droptypes types]
118
if { $force || $cen || $ctypes } {
122
-dropovercmd $dropover
130
# ------------------------------------------------------------------------------
131
# Command DropSite::register
132
# ------------------------------------------------------------------------------
133
proc DropSite::register { path args } {
136
upvar \#0 DropSite::$path drop
138
Widget::init DropSite .drop$path $args
139
if { [info exists drop] } {
142
set dropcmd [Widget::getoption .drop$path -dropcmd]
143
set types [Widget::getoption .drop$path -droptypes]
144
set overcmd [Widget::getoption .drop$path -dropovercmd]
145
Widget::destroy .drop$path
146
if { $dropcmd != "" && $types != "" } {
147
set drop(dropcmd) $dropcmd
148
set drop(overcmd) $overcmd
149
foreach {type ops} $types {
150
set drop($type,ops) {}
151
foreach {descop lmod} $ops {
152
if { ![llength $descop] || [llength $descop] > 3 } {
153
return -code error "invalid operation description \"$descop\""
155
foreach {subop baseop imgop} $descop {
156
set subop [string trim $subop]
157
if { ![string length $subop] } {
158
return -code error "sub operation is empty"
160
if { ![string length $baseop] } {
163
if { [info exists drop($type,ops,$subop)] } {
164
return -code error "operation \"$subop\" already defined"
166
if { ![info exists _tabops(ops,$baseop)] } {
167
return -code error "invalid base operation \"$baseop\""
169
if { [string compare $subop $baseop] &&
170
[info exists _tabops(ops,$subop)] } {
171
return -code error "sub operation \"$subop\" is a base operation"
173
if { ![string length $imgop] } {
174
set imgop $_defops($baseop,img)
177
if { ![string compare $lmod "program"] } {
178
set drop($type,ops,$subop) $baseop
179
set drop($type,img,$subop) $imgop
181
if { ![string length $lmod] } {
182
set lmod $_defops($baseop,mod)
186
if { ![info exists _tabops(mod,$mod)] } {
187
return -code error "invalid modifier \"$mod\""
189
set mask [expr {$mask | $_tabops(mod,$mod)}]
191
if { ($mask == 0) != ([string compare $subop "default"] == 0) } {
192
return -code error "sub operation default can only be used with modifier \"none\""
194
set drop($type,mod,$mask) $subop
195
set drop($type,ops,$subop) $baseop
196
set drop($type,img,$subop) $imgop
197
lappend masklist $mask
200
if { ![info exists drop($type,mod,0)] } {
201
set drop($type,mod,0) default
202
set drop($type,ops,default) copy
203
set drop($type,img,default) $_defops(copy,img)
206
set drop($type,ops,force) copy
207
set drop($type,img,force) $_defops(copy,img)
208
foreach mask [lsort -integer -decreasing $masklist] {
209
lappend drop($type,ops) $mask $drop($type,mod,$mask)
216
# ------------------------------------------------------------------------------
217
# Command DropSite::setcursor
218
# ------------------------------------------------------------------------------
219
proc DropSite::setcursor { cursor } {
220
catch {.drag configure -cursor $cursor}
224
# ------------------------------------------------------------------------------
225
# Command DropSite::setoperation
226
# ------------------------------------------------------------------------------
227
proc DropSite::setoperation { op } {
232
upvar \#0 DropSite::$_target drop
234
if { [info exist drop($_type,ops,$op)] &&
235
$_dragops($drop($_type,ops,$op)) } {
238
# force to a copy operation
244
# ------------------------------------------------------------------------------
245
# Command DropSite::_init_drag
246
# ------------------------------------------------------------------------------
247
proc DropSite::_init_drag { top evt source state X Y type ops data } {
259
catch {unset _dragops}
260
array set _dragops {copy 1 move 0 link 0}
271
label $_opw -relief flat -bd 0 -highlightthickness 0 \
272
-foreground black -background white
274
bind $top <ButtonRelease-$evt> {DropSite::_release %X %Y}
275
bind $top <B$evt-Motion> {DropSite::_motion %X %Y}
276
bind $top <Motion> {DropSite::_release %X %Y}
283
# ------------------------------------------------------------------------------
284
# Command DropSite::_update_operation
285
# ------------------------------------------------------------------------------
286
proc DropSite::_update_operation { state } {
291
if { $_status & 3 } {
293
_motion [winfo pointerx $_top] [winfo pointery $_top]
298
# ------------------------------------------------------------------------------
299
# Command DropSite::_compute_operation
300
# ------------------------------------------------------------------------------
301
proc DropSite::_compute_operation { target state type } {
304
upvar \#0 DropSite::$target drop
306
foreach {mask op} $drop($type,ops) {
307
if { ($state & $mask) == $mask } {
308
if { $_dragops($drop($type,ops,$op)) } {
318
# ------------------------------------------------------------------------------
319
# Command DropSite::_draw_operation
320
# ------------------------------------------------------------------------------
321
proc DropSite::_draw_operation { target type } {
328
upvar \#0 DropSite::$target drop
330
if { !($_status & 1) } {
331
catch {place forget $_opw}
336
if { ![info exist drop($type,ops,$_curop)] ||
337
!$_dragops($drop($type,ops,$_curop)) } {
338
# force to a copy operation
341
$_opw configure -bitmap $_tabops(img,copy)
342
place $_opw -relx 1 -rely 1 -anchor se
345
} elseif { ![string compare $_curop "default"] } {
346
catch {place forget $_opw}
349
$_opw configure -bitmap $drop($type,img,$_curop)
350
place $_opw -relx 1 -rely 1 -anchor se
356
# ------------------------------------------------------------------------------
357
# Command DropSite::_motion
358
# ------------------------------------------------------------------------------
359
proc DropSite::_motion { X Y } {
370
set script [bind $_top <B$_evt-Motion>]
371
bind $_top <B$_evt-Motion> {}
372
bind $_top <Motion> {}
373
wm geometry $_top "+[expr {$X+1}]+[expr {$Y+1}]"
375
if { ![winfo exists $_top] } {
378
set path [winfo containing $X $Y]
379
if { [string compare $path $_target] } {
380
# path != current target
381
if { $_status & 2 } {
382
# current target is valid and has recall status
383
# generate leave event
384
upvar \#0 DropSite::$_target drop
385
uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data]
388
upvar \#0 DropSite::$_target drop
389
if { [info exists drop($_type,ops)] } {
390
# path is a valid target
391
_compute_operation $_target $_state $_type
392
if { $drop(overcmd) != "" } {
393
set arg [list $_target $_source enter $X $Y $_curop $_type $_data]
394
set _status [uplevel \#0 $drop(overcmd) $arg]
397
catch {$_top configure -cursor based_arrow_down}
399
_draw_operation $_target $_type
402
bind $_top <B$_evt-Motion> {DropSite::_motion %X %Y}
403
bind $_top <Motion> {DropSite::_release %X %Y}
408
catch {$_top configure -cursor dot}
409
_draw_operation "" ""
411
} elseif { $_status & 2 } {
412
upvar \#0 DropSite::$_target drop
413
_compute_operation $_target $_state $_type
414
set arg [list $_target $_source motion $X $Y $_curop $_type $_data]
415
set _status [uplevel \#0 $drop(overcmd) $arg]
416
_draw_operation $_target $_type
420
bind $_top <B$_evt-Motion> {DropSite::_motion %X %Y}
421
bind $_top <Motion> {DropSite::_release %X %Y}
427
# ------------------------------------------------------------------------------
428
# Command DropSite::_release
429
# ------------------------------------------------------------------------------
430
proc DropSite::_release { X Y } {
438
if { $_status & 1 } {
439
upvar \#0 DropSite::$_target drop
441
set res [uplevel \#0 $drop(dropcmd) [list $_target $_source $X $Y $_curop $_type $_data]]
442
DragSite::_end_drag $_source $_target $drop($_type,ops,$_curop) $_type $_data $res
444
if { $_status & 2 } {
446
upvar \#0 DropSite::$_target drop
447
uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data]
449
DragSite::_end_drag $_source "" "" $_type $_data 0