diff options
author | petasis <petasis@f3661a36-4baa-549a-d6c7-40e0ffef350e> | 2009-08-31 11:31:30 (GMT) |
---|---|---|
committer | petasis <petasis@f3661a36-4baa-549a-d6c7-40e0ffef350e> | 2009-08-31 11:31:30 (GMT) |
commit | c57f1a14fbd0396a19f7b8493ea31cef600e9f48 (patch) | |
tree | 1c15743d1472a4b30015012e2a2e9f132f64e584 /library | |
download | tkdnd-c57f1a14fbd0396a19f7b8493ea31cef600e9f48.zip tkdnd-c57f1a14fbd0396a19f7b8493ea31cef600e9f48.tar.gz tkdnd-c57f1a14fbd0396a19f7b8493ea31cef600e9f48.tar.bz2 |
Initial Import
Diffstat (limited to 'library')
-rw-r--r-- | library/tkdnd.tcl | 303 | ||||
-rw-r--r-- | library/tkdnd_compat.tcl | 159 | ||||
-rw-r--r-- | library/tkdnd_unix.tcl | 365 | ||||
-rw-r--r-- | library/tkdnd_windows.tcl | 360 |
4 files changed, 1187 insertions, 0 deletions
diff --git a/library/tkdnd.tcl b/library/tkdnd.tcl new file mode 100644 index 0000000..2d205d3 --- /dev/null +++ b/library/tkdnd.tcl @@ -0,0 +1,303 @@ +# +# tkdnd.tcl -- +# +# This file implements some utility procedures that are used by the TkDND +# package. +# +# This software is copyrighted by: +# George Petasis, National Centre for Scientific Research "Demokritos", +# Aghia Paraskevi, Athens, Greece. +# e-mail: petasis@iit.demokritos.gr +# +# The following terms apply to all files associated +# with the software unless explicitly disclaimed in individual files. +# +# The authors hereby grant permission to use, copy, modify, distribute, +# and license this software and its documentation for any purpose, provided +# that existing copyright notices are retained in all copies and that this +# notice is included verbatim in any distributions. No written agreement, +# license, or royalty fee is required for any of the authorized uses. +# Modifications to this software may be copyrighted by their authors +# and need not follow the licensing terms described here, provided that +# the new terms are clearly indicated on the first page of each file where +# they apply. +# +# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +# MODIFICATIONS. +# + +package require Tk + +namespace eval tkdnd { + variable _topw ".drag" + variable _tabops + variable _state + variable _x0 + variable _y0 + variable _platform_namespace + variable _drop_file_temp_dir + variable _auto_update 1 + + bind TkDND_Drag1 <ButtonPress-1> {tkdnd::_begin_drag press %W %s %X %Y} + bind TkDND_Drag1 <B1-Motion> {tkdnd::_begin_drag motion %W %s %X %Y} + bind TkDND_Drag2 <ButtonPress-2> {tkdnd::_begin_drag press %W %s %X %Y} + bind TkDND_Drag2 <B2-Motion> {tkdnd::_begin_drag motion %W %s %X %Y} + bind TkDND_Drag3 <ButtonPress-3> {tkdnd::_begin_drag press %W %s %X %Y} + bind TkDND_Drag3 <B3-Motion> {tkdnd::_begin_drag motion %W %s %X %Y} + + # ---------------------------------------------------------------------------- + # Command tkdnd::initialise: Initialise the TkDND package. + # ---------------------------------------------------------------------------- + proc initialise { dir PKG_LIB_FILE PACKAGE_NAME} { + variable _platform_namespace + variable _drop_file_temp_dir + global env + + ## Get User's home directory: We try to locate the proper path from a set of + ## environmental variables... + foreach var {HOME HOMEPATH USERPROFILE ALLUSERSPROFILE APPDATA} { + if {[info exists env($var)]} { + if {[file isdirectory $env($var)]} { + set UserHomeDir $env($var) + break + } + } + } + ## Under windows we have to also combine HOMEDRIVE & HOMEPATH... + if {![info exists UserHomeDir] && + [string equal $tcl_platform(platform) windows] && + [info exist env(HOMEDRIVE)] && [info exist env(HOMEPATH)]} { + if {[file isdirectory $env(HOMEDRIVE)$env(HOMEPATH)]} { + set UserHomeDir $env(HOMEDRIVE)$env(HOMEPATH) + } + } + ## Have we located the needed path? + if {![info exists UserHomeDir]} { + set UserHomeDir [pwd] + } + + ## Try to locate a temporary directory... + foreach var {TKDND_TEMP_DIR TEMP TMP} { + if {[info exists env($var)]} { + if {[file isdirectory $env($var)] && [file writable $env($var)]} { + set _drop_file_temp_dir $env($var) + break + } + } + } + if {![info exists _drop_file_temp_dir]} { + foreach _dir [list $UserHomeDir/Local Settings/Temp /tmp \ + C:/WINDOWS/Temp C:/Temp C:/tmp D:/WINDOWS/Temp D:/Temp D:/tmp] { + if {[file isdirectory $_dir] && [file writable $_dir]} { + set _drop_file_temp_dir $_dir + break + } + } + } + if {![info exists _drop_file_temp_dir]} { + set _drop_file_temp_dir $UserAppDir + } + set _drop_file_temp_dir [file native $_drop_file_temp_dir] + + switch $::tcl_platform(platform) { + unix { + source $dir/tkdnd_unix.tcl + set _platform_namespace xdnd + load $dir/$PKG_LIB_FILE $PACKAGE_NAME + } + windows { + source $dir/tkdnd_windows.tcl + set _platform_namespace olednd + load $dir/libtkdnd20.dll TkDND + } + } + source $dir/tkdnd_compat.tcl + };# initialise + + proc GetDropFileTempDirectory { } { + variable _drop_file_temp_dir + return $_drop_file_temp_dir + } + proc SetDropFileTempDirectory { dir } { + variable _drop_file_temp_dir + set _drop_file_temp_dir $dir + } + +};# namespace tkdnd + +# ---------------------------------------------------------------------------- +# Command tkdnd::drag_source +# ---------------------------------------------------------------------------- +proc tkdnd::drag_source { mode path { types {} } { event 1 } } { + set tags [bindtags $path] + set idx [lsearch $tags "TkDND_Drag*"] + switch -- $mode { + register { + if { $idx != -1 } { + bindtags $path [lreplace $tags $idx $idx TkDND_Drag$event] + } else { + bindtags $path [concat $tags TkDND_Drag$event] + } + set types [platform_specific_types $types] + set old_types [bind $path <<DragSourceTypes>>] + foreach type $types { + if {[lsearch $old_types $type] < 0} {lappend old_types $type} + } + bind $path <<DragSourceTypes>> $old_types + } + unregister { + if { $idx != -1 } { + bindtags $path [lreplace $tags $idx $idx] + } + } + } +};# tkdnd::drag_source + +# ---------------------------------------------------------------------------- +# Command tkdnd::drop_target +# ---------------------------------------------------------------------------- +proc tkdnd::drop_target { mode path { types {} } } { + switch -- $mode { + set types [platform_specific_types $types] + register { + switch $::tcl_platform(platform) { + unix { + _register_types $path [winfo toplevel $path] $types + } + windows { + _RegisterDragDrop $path + bind <Destroy> $path {+ tkdnd::_RevokeDragDrop %W} + } + } + set old_types [bind $path <<DropTargetTypes>>] + foreach type $types { + if {[lsearch $old_types $type] < 0} {lappend old_types $type} + } + bind $path <<DropTargetTypes>> $old_types + } + unregister { + switch $::tcl_platform(platform) { + unix { + } + windows { + _RevokeDragDrop $path + } + } + bind $path <<DropTargetTypes>> {} + } + } +};# tkdnd::drop_target + +# ---------------------------------------------------------------------------- +# Command tkdnd::_begin_drag +# ---------------------------------------------------------------------------- +proc tkdnd::_begin_drag { event source state X Y } { + variable _x0 + variable _y0 + variable _state + + switch -- $event { + press { + set _x0 $X + set _y0 $Y + set _state "press" + } + motion { + if { ![info exists _state] } { + # This is just extra protection. There seem to be + # rare cases where the motion comes before the press. + return + } + if { [string equal $_state "press"] } { + if { abs($_x0-$X) > 3 || abs($_y0-$Y) > 3 } { + set _state "done" + _init_drag $source $state $X $Y + } + } + } + } +};# tkdnd::_begin_drag + +# ---------------------------------------------------------------------------- +# Command tkdnd::_init_drag +# ---------------------------------------------------------------------------- +proc tkdnd::_init_drag { source state rootX rootY } { + # Call the <<DragInitCmd>> binding. + set cmd [bind $source <<DragInitCmd>>] + if {[string length $cmd]} { + set cmd [string map [list %W $source %X $rootX %Y $rootY \ + %S $state %e <<DragInitCmd>> %A \{\} \ + %t [bind $source <<DragSourceTypes>>]] $cmd] + set info [uplevel \#0 $cmd] + if { $info != "" } { + foreach { actions types data } $info { break } + set types [platform_specific_types $types] + set action [_DoDragDrop $source $actions $types $data] + _end_drag $source {} $action {} $data {} $state $rootX $rootY + } + } +};# tkdnd::_init_drag + +# ---------------------------------------------------------------------------- +# Command tkdnd::_end_drag +# ---------------------------------------------------------------------------- +proc tkdnd::_end_drag { source target action type data result + state rootX rootY } { + set rootX 0 + set rootY 0 + # Call the <<DragEndCmd>> binding. + set cmd [bind $source <<DragEndCmd>>] + if {[string length $cmd]} { + set cmd [string map [list %W $source %X $rootX %Y $rootY \ + %S $state %e <<DragEndCmd>> %A \{$action\}] $cmd] + set info [uplevel \#0 $cmd] + if { $info != "" } { + foreach { actions types data } $info { break } + set types [platform_specific_types $types] + set action [_DoDragDrop $source $actions $types $data] + _end_drag $source {} $action {} $data {} + } + } +};# tkdnd::_end_drag + +# ---------------------------------------------------------------------------- +# Command tkdnd::platform_specific_types +# ---------------------------------------------------------------------------- +proc tkdnd::platform_specific_types { types } { + variable _platform_namespace + return [${_platform_namespace}::_platform_specific_types $types] +}; # tkdnd::platform_specific_types + +# ---------------------------------------------------------------------------- +# Command tkdnd::platform_independent_types +# ---------------------------------------------------------------------------- +proc tkdnd::platform_independent_types { types } { + variable _platform_namespace + return [${_platform_namespace}::_platform_independent_types $types] +}; # tkdnd::platform_independent_types + +# ---------------------------------------------------------------------------- +# Command tkdnd::platform_specific_type +# ---------------------------------------------------------------------------- +proc tkdnd::platform_specific_type { type } { + variable _platform_namespace + return [${_platform_namespace}::_platform_specific_type $type] +}; # tkdnd::platform_specific_type + +# ---------------------------------------------------------------------------- +# Command tkdnd::platform_independent_type +# ---------------------------------------------------------------------------- +proc tkdnd::platform_independent_type { type } { + variable _platform_namespace + return [${_platform_namespace}::_platform_independent_type $type] +}; # tkdnd::platform_independent_type diff --git a/library/tkdnd_compat.tcl b/library/tkdnd_compat.tcl new file mode 100644 index 0000000..791eb68 --- /dev/null +++ b/library/tkdnd_compat.tcl @@ -0,0 +1,159 @@ +# +# tkdnd_compat.tcl -- +# +# This file implements some utility procedures, to support older versions +# of the TkDND package. +# +# This software is copyrighted by: +# George Petasis, National Centre for Scientific Research "Demokritos", +# Aghia Paraskevi, Athens, Greece. +# e-mail: petasis@iit.demokritos.gr +# +# The following terms apply to all files associated +# with the software unless explicitly disclaimed in individual files. +# +# The authors hereby grant permission to use, copy, modify, distribute, +# and license this software and its documentation for any purpose, provided +# that existing copyright notices are retained in all copies and that this +# notice is included verbatim in any distributions. No written agreement, +# license, or royalty fee is required for any of the authorized uses. +# Modifications to this software may be copyrighted by their authors +# and need not follow the licensing terms described here, provided that +# the new terms are clearly indicated on the first page of each file where +# they apply. +# +# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +# MODIFICATIONS. +# + +namespace eval compat { + +};# namespace compat + +# ---------------------------------------------------------------------------- +# Command ::dnd +# ---------------------------------------------------------------------------- +proc ::dnd {method window args} { + switch $method { + bindtarget { + switch [llength $args] { + 0 {return [tkdnd::compat::bindtarget0 $window]} + 1 {return [tkdnd::compat::bindtarget1 $window [lindex $args 0]]} + 2 {return [tkdnd::compat::bindtarget2 $window [lindex $args 0] \ + [lindex $args 1]]} + 3 {return [tkdnd::compat::bindtarget3 $window [lindex $args 0] \ + [lindex $args 1] [lindex $args 2]]} + 4 {return [tkdnd::compat::bindtarget4 $window [lindex $args 0] \ + [lindex $args 1] [lindex $args 2] [lindex $args 3]]} + } + } + cleartarget { + return [tkdnd::compat::cleartarget $window] + } + bindsource { + switch [llength $args] { + 0 {return [tkdnd::compat::bindsource0 $window]} + 1 {return [tkdnd::compat::bindsource1 $window [lindex $args 0]]} + 2 {return [tkdnd::compat::bindsource2 $window [lindex $args 0] \ + [lindex $args 1]]} + 3 {return [tkdnd::compat::bindsource3 $window [lindex $args 0] \ + [lindex $args 1] [lindex $args 2]]} + } + } + clearsource { + return [tkdnd::compat::clearsource $window] + } + drag { + return [tkdnd::_init_drag $window "press" 0 0] + } + } + error "invalid number of arguments!" +};# ::dnd + +# ---------------------------------------------------------------------------- +# Command compat::bindtarget +# ---------------------------------------------------------------------------- +proc compat::bindtarget0 {window} { + return [bind $window <<DropTargetTypes>>] +};# compat::bindtarget0 + +proc compat::bindtarget1 {window type} { + return [bindtarget2 $window $type <Drop>] +};# compat::bindtarget1 + +proc compat::bindtarget2 {window type event} { + switch $event { + <DragEnter> {return [bind $window <<DropEnter>>]} + <Drag> {return [bind $window <<DropPosition>>]} + <DragLeave> {return [bind $window <<DropLeave>>]} + <Drop> {return [bind $window <<Drop>>]} + } +};# compat::bindtarget2 + +proc compat::bindtarget3 {window type event script} { + set type [normalise_type $type] + ::tkdnd::drop_target register $window [list $type] + switch $event { + <DragEnter> {return [bind $window <<DropEnter>> $script]} + <Drag> {return [bind $window <<DropPosition>> $script]} + <DragLeave> {return [bind $window <<DropLeave>> $script]} + <Drop> {return [bind $window <<Drop>> $script]} + } +};# compat::bindtarget3 + +proc compat::bindtarget4 {window type event script priority} { + return [bindtarget3 $window $type $event $script] +};# compat::bindtarget4 + +proc compat::normalise_type { type } { + switch $type { + text/plain - + {text/plain;charset=UTF-8} - + Text {return DND_Text} + text/uri-list - + Files {return DND_Files} + default {return $type} + } +};# compat::normalise_type + +# ---------------------------------------------------------------------------- +# Command compat::bindsource +# ---------------------------------------------------------------------------- +proc compat::bindsource0 {window} { + return [bind $window <<DropTargetTypes>>] +};# compat::bindsource0 + +proc compat::bindsource1 {window type} { + return [bindsource2 $window $type <Drop>] +};# compat::bindsource1 + +proc compat::bindsource2 {window type script} { + ::tkdnd::drag_source register $window $type 2 + bind $window <<DragInitCmd>> "list {copy} %t \[$script\]" +};# compat::bindsource2 + +proc compat::bindsource3 {window type script priority} { + return [bindsource2 $window $type $script] +};# compat::bindsource3 + +# ---------------------------------------------------------------------------- +# Command compat::cleartarget +# ---------------------------------------------------------------------------- +proc compat::cleartarget {window} { +};# compat::cleartarget + +# ---------------------------------------------------------------------------- +# Command compat::clearsource +# ---------------------------------------------------------------------------- +proc compat::clearsource {window} { +};# compat::clearsource diff --git a/library/tkdnd_unix.tcl b/library/tkdnd_unix.tcl new file mode 100644 index 0000000..4cc5ecc --- /dev/null +++ b/library/tkdnd_unix.tcl @@ -0,0 +1,365 @@ +# +# tkdnd_unix.tcl -- +# +# This file implements some utility procedures that are used by the TkDND +# package. +# +# This software is copyrighted by: +# George Petasis, National Centre for Scientific Research "Demokritos", +# Aghia Paraskevi, Athens, Greece. +# e-mail: petasis@iit.demokritos.gr +# +# The following terms apply to all files associated +# with the software unless explicitly disclaimed in individual files. +# +# The authors hereby grant permission to use, copy, modify, distribute, +# and license this software and its documentation for any purpose, provided +# that existing copyright notices are retained in all copies and that this +# notice is included verbatim in any distributions. No written agreement, +# license, or royalty fee is required for any of the authorized uses. +# Modifications to this software may be copyrighted by their authors +# and need not follow the licensing terms described here, provided that +# the new terms are clearly indicated on the first page of each file where +# they apply. +# +# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +# MODIFICATIONS. +# + +namespace eval xdnd { + variable _types {} + variable _typelist {} + variable _actionlist {} + variable _pressedkeys {} + variable _action {} + variable _common_drag_source_types {} + variable _common_drop_target_types {} + variable _drag_source {} + variable _drop_target {} +};# namespace xdnd + +# ---------------------------------------------------------------------------- +# Command xdnd::_HandleXdndEnter +# ---------------------------------------------------------------------------- +proc xdnd::_HandleXdndEnter { path drag_source typelist } { + variable _typelist; set _typelist $typelist + variable _pressedkeys; set _pressedkeys 1 + variable _action; set _action {} + variable _common_drag_source_types; set _common_drag_source_types {} + variable _common_drop_target_types; set _common_drop_target_types {} + variable _actionlist + variable _drag_source; set _drag_source $drag_source + variable _drop_target; set _drop_target {} + variable _actionlist; set _actionlist \ + {copy move link ask private} + # puts "xdnd::_HandleXdndEnter: path=$path, drag_source=$drag_source,\ + # typelist=$typelist" + update +};# xdnd::_HandleXdndEnter + +# ---------------------------------------------------------------------------- +# Command xdnd::_HandleXdndPosition +# ---------------------------------------------------------------------------- +proc xdnd::_HandleXdndPosition { drop_target rootX rootY } { + variable _types + variable _typelist + variable _actionlist + variable _pressedkeys + variable _action + variable _common_drag_source_types + variable _common_drop_target_types + variable _drag_source + variable _drop_target + # puts "xdnd::_HandleXdndPosition: drop_target=$drop_target,\ + # _drop_target=$_drop_target, rootX=$rootX, rootY=$rootY" + + if {![info exists _drag_source] && ![string length $_drag_source]} { + return refuse_drop + } + ## Does the new drop target support any of our new types? + set _types [bind $drop_target <<DropTargetTypes>>] + if {[llength $_types]} { + ## Examine the drop target types, to find at least one match with the drag + ## source types... + set supported_types [_supported_types $_typelist] + foreach type $_types { + foreach matched [lsearch -glob -all -inline $supported_types $type] { + ## Drop target supports this type. + lappend common_drag_source_types $matched + lappend common_drop_target_types $type + } + } + } + + # puts "($_drop_target) -> ($drop_target)" + if {$drop_target != $_drop_target} { + if {[string length $_drop_target]} { + ## Call the <<DropLeave>> event. + set cmd [bind $_drop_target <<DropLeave>>] + if {[string length $cmd]} { + set cmd [string map [list %W $_drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A \{$_action\} %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropLeave>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{\}] $cmd] + uplevel \#0 $cmd + } + } + set _drop_target {} + + if {[info exists common_drag_source_types]} { + set _action copy + set _common_drag_source_types $common_drag_source_types + set _common_drop_target_types $common_drop_target_types + set _drop_target $drop_target + ## Drop target supports at least one type. Send a <<DropEnter>>. + # puts "<<DropEnter>> -> $drop_target" + set cmd [bind $drop_target <<DropEnter>>] + if {[string length $cmd]} { + focus $drop_target + set cmd [string map [list %W $drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropEnter>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{\}] $cmd] + set _action [uplevel \#0 $cmd] + } + } + set _drop_target $drop_target + } + + set _action refuse_drop + set _drop_target {} + if {[info exists common_drag_source_types]} { + set _action copy + set _common_drag_source_types $common_drag_source_types + set _common_drop_target_types $common_drop_target_types + set _drop_target $drop_target + ## Drop target supports at least one type. Send a <<DropPosition>>. + set cmd [bind $drop_target <<DropPosition>>] + if {[string length $cmd]} { + set cmd [string map [list %W $drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropPosition>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{\}] $cmd] + set _action [uplevel \#0 $cmd] + } + } + # Return values: copy, move, link, ask, private, refuse_drop, default + return $_action +};# xdnd::_HandleXdndPosition + +# ---------------------------------------------------------------------------- +# Command xdnd::_HandleXdndLeave +# ---------------------------------------------------------------------------- +proc xdnd::_HandleXdndLeave { } { + variable _types + variable _typelist + variable _actionlist + variable _pressedkeys + variable _action + variable _common_drag_source_types + variable _common_drop_target_types + variable _drag_source + variable _drop_target + + # puts "xdnd::_HandleXdndLeave! ($_drop_target)" + if {[info exists _drop_target] && [string length $_drop_target]} { + set cmd [bind $_drop_target <<DropLeave>>] + if {[string length $cmd]} { + set cmd [string map [list %W $_drop_target %X 0 %Y 0 \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A \{$_action\} %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropLeave>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{\}] $cmd] + set _action [uplevel \#0 $cmd] + } + } + foreach var {_types _typelist _actionlist _pressedkeys _action + _common_drag_source_types _common_drop_target_types + _drag_source _drop_target} { + set $var {} + } +};# xdnd::_HandleXdndLeave + +# ---------------------------------------------------------------------------- +# Command xdnd::_HandleXdndDrop +# ---------------------------------------------------------------------------- +proc xdnd::_HandleXdndDrop { time } { + variable _types + variable _typelist + variable _actionlist + variable _pressedkeys + variable _action + variable _common_drag_source_types + variable _common_drop_target_types + variable _drag_source + variable _drop_target + set rootX 0 + set rootY 0 + + # puts "xdnd::_HandleXdndDrop: $time" + + if {![info exists _drag_source] && ![string length $_drag_source]} { + return refuse_drop + } + if {![info exists _drop_target] && ![string length $_drop_target]} { + return refuse_drop + } + if {![llength $_common_drag_source_types]} {return refuse_drop} + ## Get the dropped data. + set data [_GetDroppedData] + ## Try to select the most specific <<Drop>> event. + foreach type [concat $_common_drag_source_types $_common_drop_target_types] { + set type [_platform_independent_type $type] + set cmd [bind $_drop_target <<Drop:$type>>] + if {[string length $cmd]} { + set cmd [string map [list %W $_drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{$data\} %e <<Drop:$type>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{\}] $cmd] + return [uplevel \#0 $cmd] + } + } + set cmd [bind $_drop_target <<Drop>>] + if {[string length $cmd]} { + set cmd [string map [list %W $_drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{$data\} %e <<Drop>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{\}] $cmd] + set _action [uplevel \#0 $cmd] + } + # Return values: XdndActionCopy, XdndActionMove, XdndActionLink, + # XdndActionAsk, XdndActionPrivate, refuse_drop + return $_action +};# xdnd::_HandleXdndDrop + +# ---------------------------------------------------------------------------- +# Command xdnd::_GetDroppedData +# ---------------------------------------------------------------------------- +proc xdnd::_GetDroppedData { } { + variable _drop_target + return [selection get -displayof $_drop_target \ + -selection XdndSelection -type STRING] +};# xdnd::_GetDroppedData + +# ---------------------------------------------------------------------------- +# Command xdnd::_GetDragSource +# ---------------------------------------------------------------------------- +proc xdnd::_GetDragSource { } { + variable _drag_source + return $_drag_source +};# xdnd::_GetDragSource + +# ---------------------------------------------------------------------------- +# Command xdnd::_GetDropTarget +# ---------------------------------------------------------------------------- +proc xdnd::_GetDropTarget { } { + variable _drop_target + if {[string length $_drop_target]} { + return [winfo id $_drop_target] + } + return 0 +};# xdnd::_GetDropTarget + +# ---------------------------------------------------------------------------- +# Command xdnd::_supported_types +# ---------------------------------------------------------------------------- +proc xdnd::_supported_types { types } { + set new_types {} + foreach type $types { + if {[_supported_type $type]} {lappend new_types $type} + } + return $new_types +}; # xdnd::_supported_types + +# ---------------------------------------------------------------------------- +# Command xdnd::_platform_specific_types +# ---------------------------------------------------------------------------- +proc xdnd::_platform_specific_types { types } { + set new_types {} + foreach type $types { + set new_types [concat $new_types [_platform_specific_type $type]] + } + return $new_types +}; # xdnd::_platform_specific_types + +# ---------------------------------------------------------------------------- +# Command xdnd::_normalise_data +# ---------------------------------------------------------------------------- +proc xdnd::_normalise_data { type data } { + switch $type { + CF_HDROP {return [encoding convertfrom $data]} + default {return $data} + } +}; # xdnd::_normalise_data + +# ---------------------------------------------------------------------------- +# Command xdnd::_platform_specific_type +# ---------------------------------------------------------------------------- +proc xdnd::_platform_specific_type { type } { + switch $type { + DND_Text {return [list text/plain]} + DND_Files {return [list text/uri-list]} + default {return [list $type]} + } +}; # xdnd::_platform_specific_type + +# ---------------------------------------------------------------------------- +# Command xdnd::_platform_independent_type +# ---------------------------------------------------------------------------- +proc xdnd::_platform_independent_type { type } { + switch $type { + text/plain {return DND_Text} + text/uri-list {return DND_Files} + default {return [list $type]} + } +}; # xdnd::_platform_independent_type + +# ---------------------------------------------------------------------------- +# Command xdnd::_supported_type +# ---------------------------------------------------------------------------- +proc xdnd::_supported_type { type } { + switch $type { + {text/plain;charset=UTF-8} - text/plain - + text/uri-list {return 1} + } + return 0 +}; # xdnd::_supported_type diff --git a/library/tkdnd_windows.tcl b/library/tkdnd_windows.tcl new file mode 100644 index 0000000..16d66f0 --- /dev/null +++ b/library/tkdnd_windows.tcl @@ -0,0 +1,360 @@ +# +# tkdnd_windows.tcl -- +# +# This file implements some utility procedures that are used by the TkDND +# package. +# +# This software is copyrighted by: +# George Petasis, National Centre for Scientific Research "Demokritos", +# Aghia Paraskevi, Athens, Greece. +# e-mail: petasis@iit.demokritos.gr +# +# The following terms apply to all files associated +# with the software unless explicitly disclaimed in individual files. +# +# The authors hereby grant permission to use, copy, modify, distribute, +# and license this software and its documentation for any purpose, provided +# that existing copyright notices are retained in all copies and that this +# notice is included verbatim in any distributions. No written agreement, +# license, or royalty fee is required for any of the authorized uses. +# Modifications to this software may be copyrighted by their authors +# and need not follow the licensing terms described here, provided that +# the new terms are clearly indicated on the first page of each file where +# they apply. +# +# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +# MODIFICATIONS. +# + +namespace eval olednd { + variable _types {} + variable _typelist {} + variable _codelist {} + variable _actionlist {} + variable _pressedkeys {} + variable _action {} + variable _common_drag_source_types {} + variable _common_drop_target_types {} + variable _unhandled_types {} +};# namespace olednd + +# ---------------------------------------------------------------------------- +# Command olednd::_HandleDragEnter +# ---------------------------------------------------------------------------- +proc olednd::_HandleDragEnter { drop_target typelist actionlist pressedkeys + rootX rootY codelist } { + variable _typelist; set _typelist $typelist + variable _codelist; set _codelist $codelist + variable _actionlist; set _actionlist $actionlist + variable _pressedkeys; set _pressedkeys $pressedkeys + variable _action; set _action {} + variable _common_drag_source_types; set _common_drag_source_types {} + variable _common_drop_target_types; set _common_drop_target_types {} + # puts "olednd::_HandleDragEnter: drop_target=$drop_target,\ + # typelist=$typelist, actionlist=$actionlist,\ + # pressedkeys=$pressedkeys, rootX=$rootX, rootY=$rootY" + focus $drop_target + + ## Does the new drop target support any of our new types? + variable _types; set _types [bind $drop_target <<DropTargetTypes>>] + if {[llength $_types]} { + ## Examine the drop target types, to find at least one match with the drag + ## source types... + set supported_types [_supported_types $_typelist] + foreach type $_types { + foreach matched [lsearch -glob -all -inline $supported_types $type] { + ## Drop target supports this type. + lappend common_drag_source_types $matched + lappend common_drop_target_types $type + } + } + } + + set _action refuse_drop + if {[info exists common_drag_source_types]} { + set _action copy + set _common_drag_source_types $common_drag_source_types + set _common_drop_target_types $common_drop_target_types + ## Drop target supports at least one type. Send a <<DropEnter>>. + set cmd [bind $drop_target <<DropEnter>>] + if {[string length $cmd]} { + set cmd [string map [list %W $drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropEnter>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{[lindex $_common_drag_source_types 0]\} \ + %c \{$_codelist\} %C \{[lindex $_codelist 0]\} \ + ] $cmd] + set _action [uplevel \#0 $cmd] + } + } + if {$::tkdnd::_auto_update} {update} + # Return values: copy, move, link, ask, private, refuse_drop, default + return $_action +};# olednd::_HandleDragEnter + +# ---------------------------------------------------------------------------- +# Command olednd::_HandleDragOver +# ---------------------------------------------------------------------------- +proc olednd::_HandleDragOver { drop_target pressedkeys rootX rootY } { + variable _types + variable _typelist + variable _codelist + variable _actionlist + variable _pressedkeys + variable _action + variable _common_drag_source_types + variable _common_drop_target_types + # puts "olednd::_HandleDragOver: drop_target=$drop_target,\ + # pressedkeys=$pressedkeys, rootX=$rootX, rootY=$rootY" + + if {![llength $_common_drag_source_types]} {return refuse_drop} + set _pressedkeys $pressedkeys + set cmd [bind $drop_target <<DropPosition>>] + if {[string length $cmd]} { + set cmd [string map [list %W $drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropPosition>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{[lindex $_common_drag_source_types 0]\} \ + %c \{$_codelist\} %C \{[lindex $_codelist 0]\} \ + ] $cmd] + set _action [uplevel \#0 $cmd] + } + if {$::tkdnd::_auto_update} {update} + # Return values: copy, move, link, ask, private, refuse_drop, default + return $_action +};# olednd::_HandleDragOver + +# ---------------------------------------------------------------------------- +# Command olednd::_HandleDragLeave +# ---------------------------------------------------------------------------- +proc olednd::_HandleDragLeave { drop_target } { + variable _types + variable _typelist + variable _codelist + variable _actionlist + variable _pressedkeys + variable _action + variable _common_drag_source_types + variable _common_drop_target_types + if {![llength $_common_drag_source_types]} {return} + foreach var {_types _typelist _actionlist _pressedkeys _action + _common_drag_source_types _common_drop_target_types} { + set $var {} + } + + set cmd [bind $drop_target <<DropLeave>>] + if {[string length $cmd]} { + set cmd [string map [list %W $drop_target %X 0 %Y 0 \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A \{$_action\} %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{\} %e <<DropLeave>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{[lindex $_common_drag_source_types 0]\} \ + %u \{$_codelist\} %C \{[lindex $_codelist 0]\} \ + ] $cmd] + set _action [uplevel \#0 $cmd] + } + if {$::tkdnd::_auto_update} {update} +};# olednd::_HandleDragLeave + +# ---------------------------------------------------------------------------- +# Command olednd::_HandleXdndDrop +# ---------------------------------------------------------------------------- +proc olednd::_HandleDrop { drop_target pressedkeys rootX rootY _type data } { + variable _types + variable _typelist + variable _codelist + variable _actionlist + variable _pressedkeys + variable _action + variable _common_drag_source_types + variable _common_drop_target_types + set data [_normalise_data $_type $data] + # puts "olednd::_HandleDrop: drop_target=$drop_target,\ + # pressedkeys=$pressedkeys, rootX=$rootX, rootY=$rootY,\ + # data=\"$data\"" + + if {![llength $_common_drag_source_types]} {return refuse_drop} + set _pressedkeys $pressedkeys + ## Try to select the most specific <<Drop>> event. + foreach type [concat $_common_drag_source_types $_common_drop_target_types] { + set type [_platform_independent_type $type] + set cmd [bind $drop_target <<Drop:$type>>] + if {[string length $cmd]} { + set cmd [string map [list %W $drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{$data\} %e <<Drop:$type>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{[lindex $_common_drag_source_types 0]\} \ + %c \{$_codelist\} %C \{[lindex $_codelist 0]\} \ + ] $cmd] + return [uplevel \#0 $cmd] + } + } + set cmd [bind $drop_target <<Drop>>] + if {[string length $cmd]} { + set cmd [string map [list %W $drop_target %X $rootX %Y $rootY \ + %CST \{$_common_drag_source_types\} \ + %CTT \{$_common_drop_target_types\} \ + %ST \{$_typelist\} %TT \{$_types\} \ + %A $_action %a \{$_actionlist\} \ + %b \{$_pressedkeys\} %m \{$_pressedkeys\} \ + %D \{$data\} %e <<Drop>> \ + %L \{$_typelist\} %% % \ + %t \{$_typelist\} %T \{[lindex $_common_drag_source_types 0]\} \ + %c \{$_codelist\} %C \{[lindex $_codelist 0]\} \ + ] $cmd] + set _action [uplevel \#0 $cmd] + } + if {$::tkdnd::_auto_update} {update} + # Return values: copy, move, link, ask, private, refuse_drop + return $_action +};# olednd::_HandleXdndDrop + +# ---------------------------------------------------------------------------- +# Command olednd::_GetDropTypes +# ---------------------------------------------------------------------------- +proc olednd::_GetDropTypes { drop_target } { + variable _common_drag_source_types + return $_common_drag_source_types +};# olednd::_GetDropTypes + +# ---------------------------------------------------------------------------- +# Command olednd::_GetDroppedData +# ---------------------------------------------------------------------------- +proc olednd::_GetDroppedData { } { + variable _drop_target + return [selection get -displayof $_drop_target \ + -selection XdndSelection -type STRING] +};# olednd::_GetDroppedData + +# ---------------------------------------------------------------------------- +# Command olednd::_GetDragSource +# ---------------------------------------------------------------------------- +proc olednd::_GetDragSource { } { + variable _drag_source + return $_drag_source +};# olednd::_GetDragSource + +# ---------------------------------------------------------------------------- +# Command olednd::_GetDropTarget +# ---------------------------------------------------------------------------- +proc olednd::_GetDropTarget { } { + variable _drop_target + return [winfo id $_drop_target] +};# olednd::_GetDropTarget + +# ---------------------------------------------------------------------------- +# Command olednd::_supported_types +# ---------------------------------------------------------------------------- +proc olednd::_supported_types { types } { + set new_types {} + foreach type $types { + if {[_supported_type $type]} {lappend new_types $type} + } + return $new_types +}; # olednd::_supported_types + +# ---------------------------------------------------------------------------- +# Command olednd::_platform_specific_types +# ---------------------------------------------------------------------------- +proc olednd::_platform_specific_types { types } { + set new_types {} + foreach type $types { + set new_types [concat $new_types [_platform_specific_type $type]] + } + return $new_types +}; # olednd::_platform_specific_types + +# ---------------------------------------------------------------------------- +# Command olednd::_platform_independent_types +# ---------------------------------------------------------------------------- +proc olednd::_platform_independent_types { types } { + set new_types {} + foreach type $types { + set new_types [concat $new_types [_platform_independent_type $type]] + } + return $new_types +}; # olednd::_platform_independent_types + +# ---------------------------------------------------------------------------- +# Command olednd::_normalise_data +# ---------------------------------------------------------------------------- +proc olednd::_normalise_data { type data } { + switch $type { + CF_HDROP {return [encoding convertfrom $data]} + DND_Text {return [list CF_UNICODETEXT CF_TEXT]} + DND_Files {return [list CF_HDROP]} + default {return $data} + } +}; # olednd::_normalise_data + +# ---------------------------------------------------------------------------- +# Command olednd::_platform_specific_type +# ---------------------------------------------------------------------------- +proc olednd::_platform_specific_type { type } { + switch $type { + DND_Text {return [list CF_UNICODETEXT CF_TEXT]} + DND_Files {return [list CF_HDROP]} + default { + # variable _unhandled_types + # if {[lsearch -exact $_unhandled_types $type] == -1} { + # lappend _unhandled_types $type + # } + return [list $type]} + } +}; # olednd::_platform_specific_type + +# ---------------------------------------------------------------------------- +# Command olednd::_platform_independent_type +# ---------------------------------------------------------------------------- +proc olednd::_platform_independent_type { type } { + switch $type { + CF_UNICODETEXT - CF_TEXT {return DND_Text} + CF_HDROP {return DND_Files} + default {return [list $type]} + } +}; # olednd::_platform_independent_type + +# ---------------------------------------------------------------------------- +# Command olednd::_supported_type +# ---------------------------------------------------------------------------- +proc olednd::_supported_type { type } { + return 1; + switch $type { + CF_UNICODETEXT - CF_TEXT - + FileGroupDescriptor - FileGroupDescriptorW - + CF_HDROP {return 1} + } + # Is the type in our known, but unhandled types? + variable _unhandled_types + if {[lsearch -exact $_unhandled_types $type] != -1} {return 1} + return 0 +}; # olednd::_supported_type |