home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / extra / tkgetdir.tcl < prev   
Text File  |  2000-11-02  |  12KB  |  397 lines

  1. #########################################################
  2. # Directory Selector TCL version 1.3
  3. #
  4. # Daniel Roche, <daniel.roche@bigfoot.com>
  5. #
  6. # thanks to :
  7. #  Cyrille Artho <cartho@netlink.ch> for the 'saving pwd fix'
  8. #  Terry Griffin <terryg@axian.com> for <Return> key bindings on buttons.
  9. #  Kenneth Kehl  <Kenneth.Kehl@marconiastronics.com> for blocking at end of dir tree
  10. #
  11. #########################################################
  12.  
  13.  
  14. #########################################################
  15. # tk_getDirectory [option value ...]
  16. #
  17. #  options are :
  18. #   [-initialdir dir]     display in dir
  19. #   [-title string]       make string title of dialog window
  20. #   [-ok string]          make string the label of OK button
  21. #   [-open string]        make string the label of OPEN button
  22. #   [-cancel string]      make string the label of CANCEL button
  23. #   [-msg1 string]        make string the label of the first directory message
  24. #   [-msg2 string]        make string the label of the second directory message
  25. #
  26. #########################################################
  27.  
  28. namespace eval tkgetdir {
  29.     variable drives
  30.     variable fini
  31.     namespace export tk_getDirectory
  32. }
  33.  
  34. proc tkgetdir::tk_getDirectory {args} {
  35.     global tcl_platform
  36.  
  37.     #
  38.     # arguments
  39.     #
  40.     set _titre "Directory Selector"
  41.     set _ldir Directory:
  42.     set _ldnam "Directory Name:"
  43.     set _open Ok
  44.     set _expand Open
  45.     set _cancel Cancel
  46.     
  47.     set ind 0
  48.     set max [llength $args]
  49.     set pwd [pwd]
  50.     while { $ind < $max } {
  51.     switch -exact -- [lindex $args $ind] {
  52.         "-initialdir" {
  53.         incr ind
  54.         cd [lindex $args $ind]
  55.         incr ind
  56.         }
  57.         "-title" {
  58.         incr ind
  59.         set _titre [lindex $args $ind]
  60.         incr ind
  61.         }
  62.         "-ok" {
  63.         incr ind
  64.         set _open [lindex $args $ind]
  65.         incr ind
  66.         }
  67.         "-open" {
  68.         incr ind
  69.         set _expand [lindex $args $ind]
  70.         incr ind
  71.         }
  72.         "-cancel" {
  73.         incr ind
  74.         set _cancel [lindex $args $ind]
  75.         incr ind
  76.         }
  77.         "-msg1" {
  78.         incr ind
  79.         set _ldir [lindex $args $ind]
  80.         incr ind
  81.         }
  82.         "-msg2" {
  83.         incr ind
  84.         set _ldnam [lindex $args $ind]
  85.         incr ind
  86.         }
  87.         default {
  88.         puts "unknown option [lindex $args $ind]"
  89.         return ""
  90.         }
  91.     }
  92.     }
  93.     
  94.     #
  95.     # variables et data
  96.     #
  97.     set tkgetdir::fini 0
  98.     
  99.     image create bitmap b_up -data "
  100.     #define up_width 31
  101.     #define up_height 23
  102.     static unsigned char up_bits[] = {
  103.     0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
  104.     0x00, 0x00, 0x00, 0x80, 0x00, 0x3f, 0x00, 0x80, 0x80, 0x40, 0x00, 0x80,
  105.     0x40, 0x80, 0x00, 0x80, 0xe0, 0xff, 0xff, 0x83, 0x20, 0x00, 0x00, 0x82,
  106.     0x20, 0x04, 0x00, 0x82, 0x20, 0x0e, 0x00, 0x82, 0x20, 0x1f, 0x00, 0x82,
  107.     0x20, 0x04, 0x00, 0x82, 0x20, 0x04, 0x00, 0x82, 0x20, 0x04, 0x00, 0x82,
  108.     0x20, 0xfc, 0x0f, 0x82, 0x20, 0x00, 0x00, 0x82, 0x20, 0x00, 0x00, 0x82,
  109.     0xe0, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
  110.     0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80};"
  111.  
  112.     image create bitmap b_dir -background #ffff80 -data "
  113.     #define dir_width 17
  114.     #define dir_height 16
  115.     static unsigned char dir_bits[] = {
  116.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x10, 0x02, 0x00,
  117.     0x08, 0x04, 0x00, 0xfc, 0x7f, 0x00, 0x04, 0x40, 0x00, 0x04, 0x40, 0x00,
  118.     0x04, 0x40, 0x00, 0x04, 0x40, 0x00, 0x04, 0x40, 0x00, 0x04, 0x40, 0x00,
  119.     0x04, 0x40, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};" \
  120.         -maskdata "
  121.     #define dirm_width 17
  122.     #define dirm_height 16
  123.     static unsigned char dirm_bits[] = {
  124.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xf0, 0x03, 0x00,
  125.     0xf8, 0x07, 0x00, 0xfc, 0x7f, 0x00, 0xfc, 0x7f, 0x00, 0xfc, 0x7f, 0x00,
  126.     0xfc, 0x7f, 0x00, 0xfc, 0x7f, 0x00, 0xfc, 0x7f, 0x00, 0xfc, 0x7f, 0x00,
  127.     0xfc, 0x7f, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};"
  128.         
  129.     switch -exact $tcl_platform(platform) {
  130.     unix {
  131.         font create myfont -family lucida -size 14 -weight bold
  132.     }
  133.     windows {
  134.         font create myfont -family courier -size 12
  135.     }
  136.     }
  137.  
  138.     #
  139.     # widgets
  140.     #
  141.     toplevel .dirsel
  142.     grab set .dirsel
  143.     wm geometry .dirsel 500x250
  144.     wm title .dirsel $_titre
  145.  
  146.     event add <<RetEnt>> <Return> <KP_Enter>
  147.     
  148.     frame .dirsel.f1 -relief flat -borderwidth 0
  149.     frame .dirsel.f2 -relief sunken -borderwidth 2 
  150.     frame .dirsel.f3 -relief flat -borderwidth 0
  151.     frame .dirsel.f4 -relief flat -borderwidth 0
  152.     
  153.     pack .dirsel.f1 -fill x
  154.     pack .dirsel.f2 -fill both -expand 1 -padx 6 -pady 6
  155.     pack .dirsel.f3 -fill x
  156.     pack .dirsel.f4 -fill x
  157.     
  158.     label .dirsel.f1.lab -text $_ldir
  159.     menubutton .dirsel.f1.dir -relief raised -indicatoron 1 -anchor w \
  160.         -menu .dirsel.f1.dir.m
  161.     menu .dirsel.f1.dir.m -tearoff 0
  162.     button .dirsel.f1.up -image b_up -command tkgetdir::UpDir
  163.     bind .dirsel.f1.up <<RetEnt>> {.dirsel.f1.up invoke}
  164.  
  165.     pack .dirsel.f1.up -side right -padx 4 -pady 4
  166.     pack .dirsel.f1.lab -side left -padx 4 -pady 4
  167.     pack .dirsel.f1.dir -side right -padx 4 -pady 4 -fill x -expand 1
  168.     
  169.     canvas .dirsel.f2.cv -borderwidth 0 -yscrollcommand ".dirsel.f2.sb set"
  170.     if ![string compare $tcl_platform(platform) windows] {
  171.     .dirsel.f2.cv configure -background white
  172.     }
  173.     scrollbar .dirsel.f2.sb -command ".dirsel.f2.cv yview"
  174.     set scw 16
  175.     place .dirsel.f2.cv -x 0 -relwidth 1.0 -width [expr -$scw ] -y 0 \
  176.         -relheight 1.0
  177.     place .dirsel.f2.sb -relx 1.0 -x [expr -$scw ] -width $scw -y 0 \
  178.         -relheight 1.0
  179.     unset scw
  180.     
  181.     .dirsel.f2.cv bind TXT <Any-Enter> tkgetdir::EnterItem
  182.     .dirsel.f2.cv bind TXT <Any-Leave> tkgetdir::LeaveItem
  183.     .dirsel.f2.cv bind TXT <Any-Button> tkgetdir::ClickItem
  184.     .dirsel.f2.cv bind TXT <Double-Button> tkgetdir::DoubleClickItem
  185.     .dirsel.f2.cv bind IMG <Any-Enter> tkgetdir::EnterItem
  186.     .dirsel.f2.cv bind IMG <Any-Leave> tkgetdir::LeaveItem
  187.     .dirsel.f2.cv bind IMG <Any-Button> tkgetdir::ClickItem
  188.     .dirsel.f2.cv bind IMG <Double-Button> tkgetdir::DoubleClickItem
  189.     
  190.     label .dirsel.f3.lnam -text $_ldnam
  191.     entry .dirsel.f3.chosen -takefocus 0
  192.     pack .dirsel.f3.lnam -side left -padx 4 -pady 4
  193.     pack .dirsel.f3.chosen -side right -fill x -expand 1 -padx 4 -pady 4
  194.     
  195.     button .dirsel.f4.open -text $_open -command { 
  196.     set tmp [.dirsel.f3.chosen get]
  197.     if [ string length $tmp ] {
  198.         set tkgetdir::fini 1 
  199.     }
  200.     }
  201.     bind .dirsel.f4.open <<RetEnt>> {.dirsel.f4.open invoke}
  202.  
  203.     button .dirsel.f4.expand -text $_expand -command tkgetdir::DownDir
  204.     bind .dirsel.f4.expand <<RetEnt>> {.dirsel.f4.expand invoke}
  205.  
  206.     button .dirsel.f4.cancel -text $_cancel -command { 
  207.     set tkgetdir::fini -1 
  208.     }
  209.     bind .dirsel.f4.cancel <<RetEnt>> {.dirsel.f4.cancel invoke}
  210.     
  211.     pack .dirsel.f4.open .dirsel.f4.expand -side left -padx 10 -pady 4
  212.     pack .dirsel.f4.cancel -side right -padx 10 -pady 4
  213.     
  214.     #
  215.     # realwork
  216.     #
  217.     tkgetdir::ShowDir [pwd]
  218.     
  219.     #
  220.     # wait user
  221.     #
  222.     tkwait variable tkgetdir::fini
  223.  
  224.     if { $tkgetdir::fini == 1 } {
  225.     set curdir [.dirsel.f1.dir cget -text]
  226.     set nnam [.dirsel.f3.chosen get]
  227.     set retval [ file join $curdir $nnam ]
  228.     } else {
  229.     set retval ""
  230.     }
  231.     
  232.     font delete myfont 
  233.     destroy .dirsel
  234.     event delete <<RetEnt>>
  235.     cd $pwd
  236.  
  237.     return $retval
  238. }
  239.  
  240. proc tkgetdir::ShowDir {curdir} {
  241.  
  242.     global tcl_platform
  243.     variable drives 
  244.     
  245.     cd $curdir
  246.     .dirsel.f1.dir configure -text $curdir
  247.     
  248.     set hi1 [font metrics myfont -linespace]
  249.     set hi2 [image height b_dir]
  250.     if { $hi1 > $hi2 } {
  251.     set hi $hi1
  252.     } else {
  253.     set hi $hi2
  254.     }
  255.     set wi1 [image width b_dir]
  256.     incr wi1 4
  257.     set wi2 [winfo width .dirsel.f2.cv]
  258.     
  259.     set lidir [list]
  260.     foreach file [ glob -nocomplain * ] {
  261.     if [ file isdirectory [string trim $file "~"] ] { 
  262.         lappend lidir $file
  263.     }
  264.     }
  265.     set sldir [lsort $lidir]
  266.     
  267.     .dirsel.f2.cv delete all
  268.     set ind 0
  269.     foreach file $sldir {
  270.     if [ file isdirectory $file ] { 
  271.         .dirsel.f2.cv create image 2 [expr $ind * $hi] \
  272.             -anchor nw -image b_dir -tags IMG
  273.         .dirsel.f2.cv create text $wi1 [expr $ind * $hi] \
  274.             -anchor nw -text $file -font myfont -tags TXT
  275.         set ind [ expr $ind + 1 ]
  276.     }
  277.     }
  278.  
  279.     set ha [expr $ind * $hi]
  280.     .dirsel.f2.cv configure -scrollregion [list 0 0 $wi2 $ha]
  281.     
  282.     set curlst [file split $curdir]
  283.     set nbr [llength $curlst]
  284.     
  285.     .dirsel.f1.dir.m delete 0 last
  286.     incr nbr -2
  287.     for {set ind $nbr} {$ind >= 0} {incr ind -1} {
  288.     set tmplst [ lrange $curlst 0 $ind] 
  289.     set tmpdir [ eval file join $tmplst] 
  290.     .dirsel.f1.dir.m add command -label $tmpdir \
  291.         -command "tkgetdir::ShowDir {$tmpdir}"
  292.     }
  293.     if {[info exist drives] == 0} {
  294.     set drives [file volume]
  295.     }
  296.     if ![string compare $tcl_platform(platform) windows] {
  297.     foreach drive $drives {
  298.         .dirsel.f1.dir.m add command -label $drive \
  299.             -command "tkgetdir::ShowDir {$drive}"
  300.     }
  301.     }
  302.     
  303. }
  304.  
  305. proc tkgetdir::UpDir {} {
  306.     set curdir [.dirsel.f1.dir cget -text]
  307.     set curlst [file split $curdir]
  308.     
  309.     set nbr [llength $curlst]
  310.     if { $nbr < 2 } {
  311.     return
  312.     }
  313.     set tmp [expr $nbr - 2]
  314.     
  315.     set newlst [ lrange $curlst 0 $tmp ]
  316.     set newdir [ eval file join $newlst ]
  317.     
  318.     .dirsel.f3.chosen delete 0 end
  319.     tkgetdir::ShowDir $newdir
  320. }
  321.  
  322. proc tkgetdir::DownDir {} {
  323.     set curdir [.dirsel.f1.dir cget -text]
  324.     set nnam [.dirsel.f3.chosen get]
  325.  
  326.     set newdir [ file join $curdir $nnam ]
  327.  
  328.     # change 07/19/99
  329.     # If there are more dirs, permit display of one level down.
  330.     # Otherwise, block display and hilight selection in red.
  331.     set areDirs 0
  332.     foreach f [glob -nocomplain [file join $newdir *]] {
  333.     if {[file isdirectory $f]} {
  334.         set areDirs 1
  335.         break
  336.     }
  337.     }
  338.  
  339.     if {$areDirs} {
  340.     .dirsel.f3.chosen delete 0 end
  341.     tkgetdir::ShowDir $newdir
  342.     } else {
  343.     set id [.dirsel.f2.cv find withtag HASBOX ]
  344.     .dirsel.f2.cv itemconfigure $id -fill #FF0000
  345.     }
  346. }
  347.  
  348. proc tkgetdir::EnterItem {} {
  349.     global tcl_platform
  350.  
  351.     set id [.dirsel.f2.cv find withtag current]
  352.     set wt [.dirsel.f2.cv itemcget $id -tags]
  353.     if {[lsearch -exact $wt IMG] >= 0} {
  354.     set id [.dirsel.f2.cv find above $id]
  355.     }
  356.     if [string compare $tcl_platform(platform) windows] {
  357.     set cocol #00FF00
  358.     } else {
  359.     set cocol #0000FF
  360.     }
  361.     .dirsel.f2.cv itemconfigure $id -fill $cocol
  362. }
  363.  
  364. proc tkgetdir::LeaveItem {} {
  365.     set id [.dirsel.f2.cv find withtag current]
  366.     set wt [.dirsel.f2.cv itemcget $id -tags]
  367.     if {[lsearch -exact $wt IMG] >= 0} {
  368.     set id [.dirsel.f2.cv find above $id]
  369.     }
  370.     .dirsel.f2.cv itemconfigure $id -fill black
  371. }
  372.  
  373. proc tkgetdir::ClickItem {} {
  374.     .dirsel.f2.cv delete BOX
  375.     .dirsel.f2.cv dtag HASBOX HASBOX
  376.     set id [.dirsel.f2.cv find withtag current]
  377.     set wt [.dirsel.f2.cv itemcget $id -tags]
  378.     if {[lsearch -exact $wt IMG] >= 0} {
  379.     set id [.dirsel.f2.cv find above $id]
  380.     }
  381.     set bxr [.dirsel.f2.cv bbox $id]
  382.     .dirsel.f2.cv addtag HASBOX withtag current
  383.     eval .dirsel.f2.cv create rectangle $bxr -fill #a2a2ff -outline #a2a2ff -tags BOX
  384.     .dirsel.f2.cv lower BOX
  385.     set nam [.dirsel.f2.cv itemcget $id -text]
  386.     .dirsel.f3.chosen delete 0 end
  387.     .dirsel.f3.chosen insert 0 $nam
  388. }
  389.  
  390. proc tkgetdir::DoubleClickItem {} {
  391.     set id [.dirsel.f2.cv find withtag current]
  392.     tkgetdir::DownDir
  393. }
  394.  
  395.  
  396.