#!../src/bltwish if {[lindex $argv end] != "spawn"} { exec [info nameofexecutable] [info script] spawn & } package require BLT # -------------------------------------------------------------------------- # Starting with Tcl 8.x, the BLT commands are stored in their own # namespace called "blt". The idea is to prevent name clashes with # Tcl commands and variables from other packages, such as a "table" # command in two different packages. # # You can access the BLT commands in a couple of ways. You can prefix # all the BLT commands with the namespace qualifier "blt::" # # blt::graph .g # blt::table . .g -resize both # # or you can import all the command into the global namespace. # # namespace import blt::* # graph .g # table . .g -resize both # # -------------------------------------------------------------------------- if { $tcl_version >= 8.0 } { namespace import blt::* namespace import -force blt::tile::* } source scripts/demo.tcl if { ([info exists tcl_platform]) && ($tcl_platform(platform) == "windows") } { error "This script works only under X11" } canvas .c -width 320 -height 320 -background white blt::table . .c -fill both set lastCell "" set cellWidth 1 set cellHeight 1 proc RedrawWorld { canvas } { global cells cellWidth cellHeight $canvas delete all set width [winfo width $canvas] set height [winfo height $canvas] set cellWidth [expr $width / 8] set cellHeight [expr $height / 8] for { set row 0 } { $row < 8 } { incr row } { set y [expr $row * $cellHeight] set h [expr $y + $cellHeight] for { set column 0 } { $column < 8 } { incr column } { set x [expr $column * $cellWidth] set w [expr $x + $cellWidth] $canvas create rectangle $x $y $w $h -fill white -outline "" \ -tags "$row,$column" } } for { set row 0 } { $row < 8 } { incr row } { set y [expr $row * $cellHeight] $canvas create line 0 $y $width $y } for { set column 0 } { $column < 8 } { incr column } { set x [expr $column * $cellWidth] $canvas create line $x 0 $x $height } foreach name [array names cells] { set rc [split $name ,] set row [lindex $rc 0] set column [lindex $rc 1] set x [expr ($column * $cellWidth) + 5] set y [expr ($row * $cellHeight) + 5] set w [expr $cellWidth - 10] set h [expr $cellHeight - 10] set color [lindex $cells($name) 0] set type [lindex $cells($name) 1] set pi1_2 [expr 3.14159265358979323846/180.0] set points {} switch $type { hexagon { lappend points $x [expr $y + $h/2] [expr $x + $w * 1/3] \ $y [expr $x + $w * 2/3] $y [expr $x + $w] [expr $y + $h/2] \ [expr $x + $w * 2/3] [expr $y + $h] \ [expr $x + $w * 1/3] [expr $y + $h] } parallelogram { lappend points $x [expr $y + $h * 2/3] \ [expr $x + $w * 2/3] $y \ [expr $x + $w] [expr $y + $h * 1/3] \ [expr $x + $w * 1/3] [expr $y + $h] } triangle { lappend points \ $x [expr $y + $h] \ [expr $x + $w * 1/2] $y \ [expr $x + $w] [expr $y + $h] } } eval .c create polygon $points -fill $color -outline black } } bind .c <Configure> { RedrawWorld %W } # ---------------------------------------------------------------------- # USAGE: random ?<max>? ?<min>? # # Returns a random number in the range <min> to <max>. # If <min> is not specified, the default is 0; if max is not # specified, the default is 1. # ---------------------------------------------------------------------- proc random {{max 1.0} {min 0.0}} { global randomSeed set randomSeed [expr (7141*$randomSeed+54773) % 259200] set num [expr $randomSeed/259200.0*($max-$min)+$min] return $num } set randomSeed [clock clicks] set itemTypes { parallelogram hexagon triangle } set itemTypes { hexagon triangle parallelogram } for { set i 0 } { $i < 20 } { incr i } { while { 1 } { set row [expr int([random 8])] set column [expr int([random 8])] set type [expr int([random 3])] set type [lindex $itemTypes $type] if { ![info exists cells($row,$column)] } { set r [expr int([random 256 128])] set g [expr int([random 256 128])] set b [expr int([random 256 128])] set cells($row,$column) [format "#%.2x%.2x%.2x %s" $r $g $b $type] break } } } proc ScreenToCell { widget x y } { global cellWidth cellHeight set column [expr $x / $cellWidth] set row [expr $y / $cellHeight] return $row,$column } set count 0 foreach i [winfo interps] { puts $i if { [string match "dnd2.tcl*" $i] } { incr count } } if { $count == 1 } { toplevel .info raise .info text .info.text -width 65 -height 12 -font { Helvetica 10 } -bg white \ -tabs { 0.25i } .info.text insert end { This is a more involved example of the new "dnd" command. Run this script again to get another window. You can then drag and drop symbols between the windows by clicking with the left mouse button on a symbol. It demonstates how to o Drag-and-drop on specific areas (canvas items) of a widget. o How to receive and handle Enter/Leave/Motion events in the target. o How to send drag feedback to the source. o Use a drag threshold. } button .info.quit -text "Dismiss" -command { destroy .info } blt::table .info \ 0,0 .info.text -fill both \ 1,0 .info.quit } # ----------------------------------------------------------------- # # Setup finished. Start of drag-and-drop code here. # # Set up the entire canvas as a drag&drop source. dnd register .c -source yes -dragthreshold 5 -button 1 # Register code to pick up the information about a canvas item dnd getdata .c color GetColor proc GetColor { widget args } { array set info $args global itemInfo set id $itemInfo($info(timestamp)) set color [$widget itemcget $id -fill] set ncoords [llength [$widget coords $id]] if { $ncoords == 6 } { set type triangle } elseif { $ncoords == 8 } { set type parallelogram } elseif { $ncoords == 12 } { set type hexagon } else { error "unknown type n=$ncoords" } return [list $color $type] } dnd configure .c -package PackageSample proc PackageSample { widget args } { array set info $args # Check if we're over a canvas item set items [$widget find overlapping $info(x) $info(y) $info(x) $info(y)] set pickedItem "" foreach i $items { if { [$widget type $i] == "polygon" } { set pickedItem $i break } } if { $pickedItem == "" } { # Cancel the drag puts "Cancel the drag x=$info(x) y=$info(y)" return 0 } set fill [$widget itemcget $pickedItem -fill] set outline [$widget itemcget $pickedItem -outline] set ncoords [llength [$widget coords $pickedItem]] if { $ncoords == 6 } { set type triangle } elseif { $ncoords == 8 } { set type parallelogram } elseif { $ncoords == 12 } { set type hexagon } else { error "unknown type n=$ncoords" } set tag [ScreenToCell $widget $info(x) $info(y)] $info(token).label configure -background $fill -foreground $outline \ -text $type update idletasks update global itemInfo set itemInfo($info(timestamp)) $pickedItem return 1 } # Configure a set of animated cursors. dnd configure .c -cursors { { @bitmaps/hand/hand01.xbm bitmaps/hand/hand01m.xbm black white } { @bitmaps/hand/hand02.xbm bitmaps/hand/hand02m.xbm black white } { @bitmaps/hand/hand03.xbm bitmaps/hand/hand03m.xbm black white } { @bitmaps/hand/hand04.xbm bitmaps/hand/hand04m.xbm black white } { @bitmaps/hand/hand05.xbm bitmaps/hand/hand05m.xbm black white } { @bitmaps/hand/hand06.xbm bitmaps/hand/hand06m.xbm black white } { @bitmaps/hand/hand07.xbm bitmaps/hand/hand07m.xbm black white } { @bitmaps/hand/hand08.xbm bitmaps/hand/hand08m.xbm black white } { @bitmaps/hand/hand09.xbm bitmaps/hand/hand09m.xbm black white } { @bitmaps/hand/hand10.xbm bitmaps/hand/hand10m.xbm black white } { @bitmaps/hand/hand11.xbm bitmaps/hand/hand11m.xbm black white } { @bitmaps/hand/hand12.xbm bitmaps/hand/hand12m.xbm black white } { @bitmaps/hand/hand13.xbm bitmaps/hand/hand13m.xbm black white } { @bitmaps/hand/hand14.xbm bitmaps/hand/hand14m.xbm black white } } # Create a widget to place in the drag-and-drop token set token [dnd token window .c] label $token.label -bd 2 -highlightthickness 1 pack $token.label dnd token configure .c \ -borderwidth 2 \ -relief raised -activerelief raised \ -outline pink -fill red \ -anchor s dnd configure .c -target yes dnd setdata .c color { NewObject } proc NewObject { widget args } { array set info $args set tag [ScreenToCell $widget $info(x) $info(y)] global cells if { [info exists cells($tag)] } { error "Cell already exists" } set cells($tag) $info(value) RedrawWorld $widget } dnd configure .c -onmotion OnMotion -onenter OnMotion -onleave OnMotion proc OnMotion { widget args } { global cells lastCell array set info $args set tag [ScreenToCell $widget $info(x) $info(y)] if { $lastCell != "" } { $widget itemconfigure $lastCell -fill white -outline "" -width 1 \ -stipple "" } # Check that we're not over a canvas item if { ![info exists cells($tag)] } { $widget itemconfigure $tag -outline lightblue -fill lightblue \ -width 2 -stipple BLT set lastCell $tag return 1 } return 0 }