diff --git a/data/tcl/clrpick.tcl b/data/tcl/clrpick8.4.tcl similarity index 100% rename from data/tcl/clrpick.tcl rename to data/tcl/clrpick8.4.tcl diff --git a/data/tcl/clrpick8.5.tcl b/data/tcl/clrpick8.5.tcl new file mode 100644 index 00000000..faf48803 --- /dev/null +++ b/data/tcl/clrpick8.5.tcl @@ -0,0 +1,700 @@ +# clrpick.tcl -- +# +# Color selection dialog for platforms that do not support a +# standard color selection dialog. +# +# RCS: @(#) $Id: clrpick.tcl,v 1.20.2.2 2006/03/17 10:50:11 patthoyts Exp $ +# +# Copyright (c) 1996 Sun Microsystems, Inc. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# ToDo: +# +# (1): Find out how many free colors are left in the colormap and +# don't allocate too many colors. +# (2): Implement HSV color selection. +# + +# Make sure namespaces exist +namespace eval ::tk {} +namespace eval ::tk::dialog {} +namespace eval ::tk::dialog::color { + namespace import ::tk::msgcat::* +} + +# ::tk::dialog::color:: -- +# +# Create a color dialog and let the user choose a color. This function +# should not be called directly. It is called by the tk_chooseColor +# function when a native color selector widget does not exist +# +proc ::tk::dialog::color:: {args} { + variable ::tk::Priv + set dataName __tk__color + upvar ::tk::dialog::color::$dataName data + set w .$dataName + + # The lines variables track the start and end indices of the line + # elements in the colorbar canvases. + set data(lines,red,start) 0 + set data(lines,red,last) -1 + set data(lines,green,start) 0 + set data(lines,green,last) -1 + set data(lines,blue,start) 0 + set data(lines,blue,last) -1 + + # This is the actual number of lines that are drawn in each color strip. + # Note that the bars may be of any width. + # However, NUM_COLORBARS must be a number that evenly divides 256. + # Such as 256, 128, 64, etc. + set data(NUM_COLORBARS) 16 + + # BARS_WIDTH is the number of pixels wide the color bar portion of the + # canvas is. This number must be a multiple of NUM_COLORBARS + set data(BARS_WIDTH) 160 + + # PLGN_WIDTH is the number of pixels wide of the triangular selection + # polygon. This also results in the definition of the padding on the + # left and right sides which is half of PLGN_WIDTH. Make this number even. + set data(PLGN_HEIGHT) 10 + + # PLGN_HEIGHT is the height of the selection polygon and the height of the + # selection rectangle at the bottom of the color bar. No restrictions. + set data(PLGN_WIDTH) 10 + + Config $dataName $args + InitValues $dataName + + set sc [winfo screen $data(-parent)] + set winExists [winfo exists $w] + if {!$winExists || $sc ne [winfo screen $w]} { + if {$winExists} { + destroy $w + } + toplevel $w -class TkColorDialog -screen $sc + BuildDialog $w + } + + # Dialog boxes should be transient with respect to their parent, + # so that they will always stay on top of their parent window. However, + # some window managers will create the window as withdrawn if the parent + # window is withdrawn or iconified. Combined with the grab we put on the + # window, this can hang the entire application. Therefore we only make + # the dialog transient if the parent is viewable. + + if {[winfo viewable [winfo toplevel $data(-parent)]] } { + wm transient $w $data(-parent) + } + + # 5. Withdraw the window, then update all the geometry information + # so we know how big it wants to be, then center the window in the + # display and de-iconify it. + + ::tk::PlaceWindow $w widget $data(-parent) + wm title $w $data(-title) + + # 6. Set a grab and claim the focus too. + + ::tk::SetFocusGrab $w $data(okBtn) + + # 7. Wait for the user to respond, then restore the focus and + # return the index of the selected button. Restore the focus + # before deleting the window, since otherwise the window manager + # may take the focus away so we can't redirect it. Finally, + # restore any grab that was in effect. + + vwait ::tk::Priv(selectColor) + ::tk::RestoreFocusGrab $w $data(okBtn) + unset data + + return $Priv(selectColor) +} + +# ::tk::dialog::color::InitValues -- +# +# Get called during initialization or when user resets NUM_COLORBARS +# +proc ::tk::dialog::color::InitValues {dataName} { + upvar ::tk::dialog::color::$dataName data + + # IntensityIncr is the difference in color intensity between a colorbar + # and its neighbors. + set data(intensityIncr) [expr {256 / $data(NUM_COLORBARS)}] + + # ColorbarWidth is the width of each colorbar + set data(colorbarWidth) \ + [expr {$data(BARS_WIDTH) / $data(NUM_COLORBARS)}] + + # Indent is the width of the space at the left and right side of the + # colorbar. It is always half the selector polygon width, because the + # polygon extends into the space. + set data(indent) [expr {$data(PLGN_WIDTH) / 2}] + + set data(colorPad) 2 + set data(selPad) [expr {$data(PLGN_WIDTH) / 2}] + + # + # minX is the x coordinate of the first colorbar + # + set data(minX) $data(indent) + + # + # maxX is the x coordinate of the last colorbar + # + set data(maxX) [expr {$data(BARS_WIDTH) + $data(indent)-1}] + + # + # canvasWidth is the width of the entire canvas, including the indents + # + set data(canvasWidth) [expr {$data(BARS_WIDTH) + $data(PLGN_WIDTH)}] + + # Set the initial color, specified by -initialcolor, or the + # color chosen by the user the last time. + set data(selection) $data(-initialcolor) + set data(finalColor) $data(-initialcolor) + set rgb [winfo rgb . $data(selection)] + + set data(red,intensity) [expr {[lindex $rgb 0]/0x100}] + set data(green,intensity) [expr {[lindex $rgb 1]/0x100}] + set data(blue,intensity) [expr {[lindex $rgb 2]/0x100}] +} + +# ::tk::dialog::color::Config -- +# +# Parses the command line arguments to tk_chooseColor +# +proc ::tk::dialog::color::Config {dataName argList} { + variable ::tk::Priv + upvar ::tk::dialog::color::$dataName data + + # 1: the configuration specs + # + if {[info exists Priv(selectColor)] && $Priv(selectColor) ne ""} { + set defaultColor $Priv(selectColor) + } else { + set defaultColor [. cget -background] + } + + set specs [list \ + [list -initialcolor "" "" $defaultColor] \ + [list -parent "" "" "."] \ + [list -title "" "" [mc "Color"]] \ + ] + + # 2: parse the arguments + # + tclParseConfigSpec ::tk::dialog::color::$dataName $specs "" $argList + + if {$data(-title) eq ""} { + set data(-title) " " + } + if {[catch {winfo rgb . $data(-initialcolor)} err]} { + error $err + } + + if {![winfo exists $data(-parent)]} { + error "bad window path name \"$data(-parent)\"" + } +} + +# ::tk::dialog::color::BuildDialog -- +# +# Build the dialog. +# +proc ::tk::dialog::color::BuildDialog {w} { + upvar ::tk::dialog::color::[winfo name $w] data + + # TopFrame contains the color strips and the color selection + # + set topFrame [ttk::frame $w.top] + + # StripsFrame contains the colorstrips and the individual RGB entries + set stripsFrame [ttk::frame $topFrame.colorStrip] + + set maxWidth [::tk::mcmaxamp &Red &Green &Blue] + incr maxWidth + set maxWidth [expr {$maxWidth<6?6:$maxWidth}] + set colorList [list \ + red [mc "&Red"] \ + green [mc "&Green"] \ + blue [mc "&Blue"] \ + ] + foreach {color l} $colorList { + # each f frame contains an [R|G|B] entry and the equiv. color strip. + set f [ttk::frame $stripsFrame.$color] + + # The box frame contains the label and entry widget for an [R|G|B] + set box [ttk::frame $f.box] + + bind [::tk::AmpWidget ttk::label $box.label -text $l: -width $maxWidth \ + -anchor ne] <> [list focus $box.entry] + + ttk::entry $box.entry -textvariable \ + ::tk::dialog::color::[winfo name $w]($color,intensity) \ + -width 4 + pack $box.label -side left -fill y -padx 2 -pady 2 + pack $box.entry -side left -anchor n -padx 2 -pady 1 + pack $box -side left -fill both + + set height [expr {[winfo reqheight $box.entry] - 4}] + + canvas $f.color -height $height -width $data(BARS_WIDTH) \ + -relief sunken -bd 2 -highlightthickness 0 + canvas $f.sel -height $data(PLGN_HEIGHT) \ + -width $data(canvasWidth) -highlightthickness 0 \ + -bg [ttk::style lookup . -background] + pack $f.color + pack $f.sel -expand yes -fill both + + pack $f -side top -fill x -padx 0 -pady 2 + + set data($color,entry) $box.entry + set data($color,col) $f.color + set data($color,sel) $f.sel + + bind $data($color,col) \ + [list tk::dialog::color::DrawColorScale $w $color 1] + bind $data($color,col) \ + [list tk::dialog::color::EnterColorBar $w $color] + bind $data($color,col) \ + [list tk::dialog::color::LeaveColorBar $w $color] + + bind $data($color,sel) \ + [list tk::dialog::color::EnterColorBar $w $color] + bind $data($color,sel) \ + [list tk::dialog::color::LeaveColorBar $w $color] + + bind $box.entry [list tk::dialog::color::HandleRGBEntry $w] + } + + pack $stripsFrame -side left -fill both -padx 4 -pady 10 + + # The selFrame contains a frame that demonstrates the currently + # selected color + # + set selFrame [ttk::frame $topFrame.sel] + set lab [::tk::AmpWidget ttk::label $selFrame.lab -text [mc "&Selection:"] \ + -anchor sw] + set ent [ttk::entry $selFrame.ent \ + -textvariable ::tk::dialog::color::[winfo name $w](selection) \ + -width 16] + set f1 [frame $selFrame.f1 -relief sunken -bd 2] + set data(finalCanvas) [canvas $f1.demo -relief flat \ + -width 100 -height 70 -highlightthickness 0] + + pack $lab $ent -side top -fill x -padx 4 -pady 2 + pack $f1 -expand yes -anchor nw -fill both -padx 6 -pady 10 + pack $data(finalCanvas) -expand yes -fill both + + bind $ent [list tk::dialog::color::HandleSelEntry $w] + + pack $selFrame -side left -fill none -anchor nw + pack $topFrame -side top -expand yes -fill both -anchor nw + + # the botFrame frame contains the buttons + # + set sep [ttk::separator $w.sep] + set botFrame [ttk::frame $w.bot] + + set maxWidth [::tk::mcmaxamp &OK &Cancel] + set maxWidth [expr {$maxWidth<8?8:$maxWidth}] + + ::tk::AmpWidget ttk::button $botFrame.ok -text [mc "&OK"] \ + -command [list tk::dialog::color::OkCmd $w] -width $maxWidth + ::tk::AmpWidget ttk::button $botFrame.cancel -text [mc "&Cancel"] \ + -command [list tk::dialog::color::CancelCmd $w] -width $maxWidth + + set data(okBtn) $botFrame.ok + set data(cancelBtn) $botFrame.cancel + + grid x $botFrame.ok x $botFrame.cancel x -sticky e + grid configure $botFrame.ok -pady 8 + grid configure $botFrame.cancel -padx 10 -pady 8 + grid columnconfigure $botFrame 0 -weight 1 + pack $botFrame $sep -side bottom -fill x + + + # Accelerator bindings + bind $lab <> [list focus $ent] + bind $w [list tk::ButtonInvoke $data(cancelBtn)] + bind $w [list tk::AltKeyInDialog $w %A] + + wm protocol $w WM_DELETE_WINDOW [list tk::dialog::color::CancelCmd $w] +} + +# ::tk::dialog::color::SetRGBValue -- +# +# Sets the current selection of the dialog box +# +proc ::tk::dialog::color::SetRGBValue {w color} { + upvar ::tk::dialog::color::[winfo name $w] data + + set data(red,intensity) [lindex $color 0] + set data(green,intensity) [lindex $color 1] + set data(blue,intensity) [lindex $color 2] + + RedrawColorBars $w all + + # Now compute the new x value of each colorbars pointer polygon + foreach color [list red green blue ] { + set x [RgbToX $w $data($color,intensity)] + MoveSelector $w $data($color,sel) $color $x 0 + } +} + +# ::tk::dialog::color::XToRgb -- +# +# Converts a screen coordinate to intensity +# +proc ::tk::dialog::color::XToRgb {w x} { + upvar ::tk::dialog::color::[winfo name $w] data + + set x [expr {($x * $data(intensityIncr))/ $data(colorbarWidth)}] + if {$x > 255} { set x 255 } + return $x +} + +# ::tk::dialog::color::RgbToX +# +# Converts an intensity to screen coordinate. +# +proc ::tk::dialog::color::RgbToX {w color} { + upvar ::tk::dialog::color::[winfo name $w] data + + return [expr {($color * $data(colorbarWidth)/ $data(intensityIncr))}] +} + + +# ::tk::dialog::color::DrawColorScale -- +# +# Draw color scale is called whenever the size of one of the color +# scale canvases is changed. +# +proc ::tk::dialog::color::DrawColorScale {w c {create 0}} { + upvar ::tk::dialog::color::[winfo name $w] data + + # col: color bar canvas + # sel: selector canvas + set col $data($c,col) + set sel $data($c,sel) + + # First handle the case that we are creating everything for the first time. + if {$create} { + # First remove all the lines that already exist. + if { $data(lines,$c,last) > $data(lines,$c,start)} { + for {set i $data(lines,$c,start)} \ + {$i <= $data(lines,$c,last)} { incr i} { + $sel delete $i + } + } + # Delete the selector if it exists + if {[info exists data($c,index)]} { + $sel delete $data($c,index) + } + + # Draw the selection polygons + CreateSelector $w $sel $c + $sel bind $data($c,index) \ + [list tk::dialog::color::StartMove $w $sel $c %x $data(selPad) 1] + $sel bind $data($c,index) \ + [list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)] + $sel bind $data($c,index) \ + [list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)] + + set height [winfo height $col] + # Create an invisible region under the colorstrip to catch mouse clicks + # that aren't on the selector. + set data($c,clickRegion) [$sel create rectangle 0 0 \ + $data(canvasWidth) $height -fill {} -outline {}] + + bind $col \ + [list tk::dialog::color::StartMove $w $sel $c %x $data(colorPad)] + bind $col \ + [list tk::dialog::color::MoveSelector $w $sel $c %x $data(colorPad)] + bind $col \ + [list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(colorPad)] + + $sel bind $data($c,clickRegion) \ + [list tk::dialog::color::StartMove $w $sel $c %x $data(selPad)] + $sel bind $data($c,clickRegion) \ + [list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)] + $sel bind $data($c,clickRegion) \ + [list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)] + } else { + # l is the canvas index of the first colorbar. + set l $data(lines,$c,start) + } + + # Draw the color bars. + set highlightW [expr {[$col cget -highlightthickness] + [$col cget -bd]}] + for {set i 0} { $i < $data(NUM_COLORBARS)} { incr i} { + set intensity [expr {$i * $data(intensityIncr)}] + set startx [expr {$i * $data(colorbarWidth) + $highlightW}] + if {$c eq "red"} { + set color [format "#%02x%02x%02x" \ + $intensity \ + $data(green,intensity) \ + $data(blue,intensity)] + } elseif {$c eq "green"} { + set color [format "#%02x%02x%02x" \ + $data(red,intensity) \ + $intensity \ + $data(blue,intensity)] + } else { + set color [format "#%02x%02x%02x" \ + $data(red,intensity) \ + $data(green,intensity) \ + $intensity] + } + + if {$create} { + set index [$col create rect $startx $highlightW \ + [expr {$startx +$data(colorbarWidth)}] \ + [expr {[winfo height $col] + $highlightW}]\ + -fill $color -outline $color] + } else { + $col itemconfigure $l -fill $color -outline $color + incr l + } + } + $sel raise $data($c,index) + + if {$create} { + set data(lines,$c,last) $index + set data(lines,$c,start) [expr {$index - $data(NUM_COLORBARS) + 1}] + } + + RedrawFinalColor $w +} + +# ::tk::dialog::color::CreateSelector -- +# +# Creates and draws the selector polygon at the position +# $data($c,intensity). +# +proc ::tk::dialog::color::CreateSelector {w sel c } { + upvar ::tk::dialog::color::[winfo name $w] data + set data($c,index) [$sel create polygon \ + 0 $data(PLGN_HEIGHT) \ + $data(PLGN_WIDTH) $data(PLGN_HEIGHT) \ + $data(indent) 0] + set data($c,x) [RgbToX $w $data($c,intensity)] + $sel move $data($c,index) $data($c,x) 0 +} + +# ::tk::dialog::color::RedrawFinalColor +# +# Combines the intensities of the three colors into the final color +# +proc ::tk::dialog::color::RedrawFinalColor {w} { + upvar ::tk::dialog::color::[winfo name $w] data + + set color [format "#%02x%02x%02x" $data(red,intensity) \ + $data(green,intensity) $data(blue,intensity)] + + $data(finalCanvas) configure -background $color + set data(finalColor) $color + set data(selection) $color + set data(finalRGB) [list \ + $data(red,intensity) \ + $data(green,intensity) \ + $data(blue,intensity)] +} + +# ::tk::dialog::color::RedrawColorBars -- +# +# Only redraws the colors on the color strips that were not manipulated. +# Params: color of colorstrip that changed. If color is not [red|green|blue] +# Then all colorstrips will be updated +# +proc ::tk::dialog::color::RedrawColorBars {w colorChanged} { + upvar ::tk::dialog::color::[winfo name $w] data + + switch $colorChanged { + red { + DrawColorScale $w green + DrawColorScale $w blue + } + green { + DrawColorScale $w red + DrawColorScale $w blue + } + blue { + DrawColorScale $w red + DrawColorScale $w green + } + default { + DrawColorScale $w red + DrawColorScale $w green + DrawColorScale $w blue + } + } + RedrawFinalColor $w +} + +#---------------------------------------------------------------------- +# Event handlers +#---------------------------------------------------------------------- + +# ::tk::dialog::color::StartMove -- +# +# Handles a mousedown button event over the selector polygon. +# Adds the bindings for moving the mouse while the button is +# pressed. Sets the binding for the button-release event. +# +# Params: sel is the selector canvas window, color is the color of the strip. +# +proc ::tk::dialog::color::StartMove {w sel color x delta {dontMove 0}} { + upvar ::tk::dialog::color::[winfo name $w] data + + if {!$dontMove} { + MoveSelector $w $sel $color $x $delta + } +} + +# ::tk::dialog::color::MoveSelector -- +# +# Moves the polygon selector so that its middle point has the same +# x value as the specified x. If x is outside the bounds [0,255], +# the selector is set to the closest endpoint. +# +# Params: sel is the selector canvas, c is [red|green|blue] +# x is a x-coordinate. +# +proc ::tk::dialog::color::MoveSelector {w sel color x delta} { + upvar ::tk::dialog::color::[winfo name $w] data + + incr x -$delta + + if { $x < 0 } { + set x 0 + } elseif { $x > $data(BARS_WIDTH)} { + set x $data(BARS_WIDTH) + } + set diff [expr {$x - $data($color,x)}] + $sel move $data($color,index) $diff 0 + set data($color,x) [expr {$data($color,x) + $diff}] + + # Return the x value that it was actually set at + return $x +} + +# ::tk::dialog::color::ReleaseMouse +# +# Removes mouse tracking bindings, updates the colorbars. +# +# Params: sel is the selector canvas, color is the color of the strip, +# x is the x-coord of the mouse. +# +proc ::tk::dialog::color::ReleaseMouse {w sel color x delta} { + upvar ::tk::dialog::color::[winfo name $w] data + + set x [MoveSelector $w $sel $color $x $delta] + + # Determine exactly what color we are looking at. + set data($color,intensity) [XToRgb $w $x] + + RedrawColorBars $w $color +} + +# ::tk::dialog::color::ResizeColorbars -- +# +# Completely redraws the colorbars, including resizing the +# colorstrips +# +proc ::tk::dialog::color::ResizeColorBars {w} { + upvar ::tk::dialog::color::[winfo name $w] data + + if { ($data(BARS_WIDTH) < $data(NUM_COLORBARS)) || + (($data(BARS_WIDTH) % $data(NUM_COLORBARS)) != 0)} { + set data(BARS_WIDTH) $data(NUM_COLORBARS) + } + InitValues [winfo name $w] + foreach color [list red green blue ] { + $data($color,col) configure -width $data(canvasWidth) + DrawColorScale $w $color 1 + } +} + +# ::tk::dialog::color::HandleSelEntry -- +# +# Handles the return keypress event in the "Selection:" entry +# +proc ::tk::dialog::color::HandleSelEntry {w} { + upvar ::tk::dialog::color::[winfo name $w] data + + set text [string trim $data(selection)] + # Check to make sure that the color is valid + if {[catch {set color [winfo rgb . $text]} ]} { + set data(selection) $data(finalColor) + return + } + + set R [expr {[lindex $color 0]/0x100}] + set G [expr {[lindex $color 1]/0x100}] + set B [expr {[lindex $color 2]/0x100}] + + SetRGBValue $w "$R $G $B" + set data(selection) $text +} + +# ::tk::dialog::color::HandleRGBEntry -- +# +# Handles the return keypress event in the R, G or B entry +# +proc ::tk::dialog::color::HandleRGBEntry {w} { + upvar ::tk::dialog::color::[winfo name $w] data + + foreach c [list red green blue] { + if {[catch { + set data($c,intensity) [expr {int($data($c,intensity))}] + }]} { + set data($c,intensity) 0 + } + + if {$data($c,intensity) < 0} { + set data($c,intensity) 0 + } + if {$data($c,intensity) > 255} { + set data($c,intensity) 255 + } + } + + SetRGBValue $w "$data(red,intensity) \ + $data(green,intensity) $data(blue,intensity)" +} + +# mouse cursor enters a color bar +# +proc ::tk::dialog::color::EnterColorBar {w color} { + upvar ::tk::dialog::color::[winfo name $w] data + + $data($color,sel) itemconfigure $data($color,index) -fill red +} + +# mouse leaves enters a color bar +# +proc ::tk::dialog::color::LeaveColorBar {w color} { + upvar ::tk::dialog::color::[winfo name $w] data + + $data($color,sel) itemconfigure $data($color,index) -fill black +} + +# user hits OK button +# +proc ::tk::dialog::color::OkCmd {w} { + variable ::tk::Priv + upvar ::tk::dialog::color::[winfo name $w] data + + set Priv(selectColor) $data(finalColor) +} + +# user hits Cancel button +# +proc ::tk::dialog::color::CancelCmd {w} { + variable ::tk::Priv + set Priv(selectColor) "" +} + diff --git a/data/tcl/fsdialog.tcl b/data/tcl/fsdialog8.4.tcl similarity index 99% rename from data/tcl/fsdialog.tcl rename to data/tcl/fsdialog8.4.tcl index fab4f74b..c6b56bd1 100644 --- a/data/tcl/fsdialog.tcl +++ b/data/tcl/fsdialog8.4.tcl @@ -599,7 +599,7 @@ proc ::ttk::dialog::file::ChangeDir {w dir} { lappend data(history) $data(selectPath) if {[incr data(histpos)]} { $data(prevBtn) state !disabled - set data(selectFile) "" + #set data(selectFile) "" } $data(nextBtn) state disabled diff --git a/data/tcl/fsdialog8.5.tcl b/data/tcl/fsdialog8.5.tcl new file mode 100644 index 00000000..ea9f8035 --- /dev/null +++ b/data/tcl/fsdialog8.5.tcl @@ -0,0 +1,1765 @@ +# Copyright (C) Schelte Bron. Freely redistributable. +# http://wiki.tcl.tk/15897 + +proc ttk::messageBox {args} { + variable ::ttk::Priv + set dataName __ttk_messagebox + set parent . + foreach {opt val} $args { + switch -- $opt { + -parent { + set parent $val + } + default { + lappend opts $opt $val + } + } + } + lappend opts -command {set ::ttk::Priv(button)} + if {$parent eq "."} { + set win .$dataName + } else { + set win $parent.$dataName + } + eval [linsert $opts 0 ttk::dialog $win] + ::tk::PlaceWindow $win widget $parent + ::tk::SetFocusGrab $win $win + vwait ::ttk::Priv(button) + ::tk::RestoreFocusGrab $win $win + return $Priv(button) +} + +interp alias {} ttk_messageBox {} ::ttk::messageBox + +namespace eval ::ttk::dialog {} +namespace eval ::ttk::dialog::file { + variable sort name hidden 1 sepfolders 1 foldersfirst 1 + variable details 0 reverse 0 filetype none + variable dirlist "" filelist "" +} +namespace eval ::ttk::dialog::image {} + +# Images for the configuration menu + +image create photo ::ttk::dialog::image::blank16 -height 16 -width 16 + +image create photo ::ttk::dialog::image::tick16 -data { +R0lGODlhEAAQAMIAAExOTFRSVPz+/AQCBP///////////////yH5BAEKAAQALAAAAAAQABAA +AAM4CAHcvkEAQqu18uqat+4eFoTEwE3eYFLCWK2lelqyChMtbd84+sqX3IXH8pFwrmNPyRI4 +n9CoIAEAOw==} + +image create photo ::ttk::dialog::image::radio16 -data { +R0lGODlhEAAQAMIAAJyZi////83OxQAAAP///////////////yH5BAEKAAEALAAAAAAQABAA +AAMtGLrc/jCAOaNsAGYn3A5DuHTMFp4KuZjnkGJK6waq8qEvzGlNzQlAn2VILC4SADs=} + +# Images for ttk::getOpenFile, ttk::getSaveFile, ttk::getAppendFile + +image create photo ::ttk::dialog::image::next -data { +R0lGODlhFgAWAMYAADt1BDpzBFiJKb7ZpGaVOTx2A8HcqbfVm3ShSjt0BDp1BDx3Bb/apYe7 +V7DSkIOtWzt0A8Dbpr/apL7ao7zZoXu0RXy0R6bMgo23Zz12CbzZoH+2Sn61SX21R3qzRHiy +QnaxPnOvOnCuNpjFb5e/cUV8ELnXnHiyQXaxP3WwPXCtNm2sMmqqLWaoKIm8WJ3FeEuBGLXV +l2+tNGGlIWanJ2urLWutLmqtK2irJ2SpIl+lHJ/GeFaKIjt1A6jNhU+aB06aBk+cBlKhCFWl +CViqDF6uEmCvFWGtFl2qE3e2Op3HdVWLIjt2BKPLflSjCFipClyvDF6zDWC2Dl+0DYTER5zK +cEqDFjt3A1eoClywDGG3DmW9EGfBEWnCE5XTWZjJZ0R9D6TLfqbPf6nUgazYgq/cg2nDEXPM +GqPfaY7DWj53CTlzBD13Ba7bg3HGH6fecn+0SqbWdmufOjhwBKTPelqNKTNmAk6DHi9dAzdu +A////////////////////////yH5BAEKAH8ALAAAAAAWABYAAAfGgH+Cg4SFhoeIiYgAio0B +Ao2JAQMEBZGGAQYHCAmNCgGgoAsMDQ4PEIoBEasREhMUFRYXGBmSGhsbHB0eHyAhIiMkJYgB +JifHKCkhKissLS4vMIcBMTItMzM0NTY3ODk6Jzs9mD4/QEBBQkNERUZHSElKTJhN50FOT1BR +UlJTVFVXptUDIgRLFi1buHTx8gUMsSZNwogZQ6aMmTNo0qhJtCYUKDZt3LyB0+mSoABk4siZ +Y3JQADp17LR0eQfPzEF5burcKSgQADs=} + +image create photo ::ttk::dialog::image::nextbw -data { +R0lGODlhFgAWAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0N +DQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8f +HyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDEx +MTIyMjMzMzQ0NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkND +Q0REREVFRUZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV +VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdn +Z2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5 +eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouL +i4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2d +nZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v +r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHB +wcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT +09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl +5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf3 +9/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///yH5BAEKAP8ALAAAAAAWABYAAAjUAP8JHEiwoMGD +CBMivKKwYZU3DRNWWcaHYcSCVZwVS2SloZUqIEFiYQYK2KWOEpupbLZsmTJLl3CFwiJRWaZM +mDBVoiQJkiNXqr4grHKMklFJkSA1WpTIUChYZQ5WIdbIkCBBhRItUoSoECBKsSwSrJJrjhw5 +dPDsAUTIUCFBlcIarGLrLB09fwgdSpQI0ShZNOfWlYPHDyFFjyRRkvVKqFRbkHP1CkaMUidg +p7JIDAkyyzBNwTChvPivSrBehKaQHlgFl5wlq1mfKRJ7YJTauHMLDAgAOw==} + +image create photo ::ttk::dialog::image::previous -data { +R0lGODlhFgAWAOcAADp0BFSIJTx1Bzp0A2KSNLrWnz93Czt1BHGeRbXUmL/apTx0BH6qVa/R +joS5UrzZoEF7CzpzBD13CIu2Y6TLf3iyQniyQbnXnbzZob7ao7/apMDbpj92CkR7D5S8bJbD +a22sMW+tNHKvOXaxPnqzRH21R361SX+2SrvYn0mAFprDdIe6VWOmI2aoKGqqLW2sMnCtNnOv +OnWwPXaxP7jWmj52CTt1A1SIIJvEdHWxPlqhF16jHGGlIWSnJWmrK2uvLGqwKGevI2uvKXKy +NrTVlT11CDt3A1SKIJrEcVOdDVWeEFSeD1ekD1enC1mrCluuC1ywDFqqC6rThEmCFZXAbE6a +BlKgB1enCV+0DWK4DmS7D2O7D1+zDajUfkJ5DYy5YYa7U1elDFqsC2jBEWvGEmrFEmfBEWO6 +D6rXfzx1CDx2B4GwU5TGY2GxFGC2Dq7dgLLhhLXmhrTlha/dg63Zgjx2CDpyA3WmRZ3Ob2m5 +HK3bgEF9CTtzBDduA2aYNqHQdazYgTNlAleLJaPOeS1ZA0yBGzx0Bv////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////yH5BAEKAP8ALAAAAAAWABYAAAjgAP8JHEiwoMGD +CBMq/AdgYcIAAhwaHECggAGJBA8gSKDgIsZ/Cxg0cPAAQoSTJw8klDCBQgULFzBk0LChJgeE +HTx8ABFCxIgKJEqYOIHipsEUKlawaOHiBYwYMmZYsECjhkEbOHLo2MGjh48fQIIEETKESBGD +RpDASKJkCZMmTp5AgfIkipSzBgFQIVHFypUnWLJo2ZKFSxe8Br18ARNGDBYtY8iUMXMGTZqE +atawaePmDZw4cuDMoVNHoZ07ePLo2YPyJJ+Fffz8AVT6o8BAggbVtv2PUCFDvAn2CU7cdkAA +Ow==} + +image create photo ::ttk::dialog::image::previousbw -data { +R0lGODlhFgAWAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0N +DQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8f +HyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDEx +MTIyMjMzMzQ0NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkND +Q0REREVFRUZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV +VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdn +Z2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5 +eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouL +i4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2d +nZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v +r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHB +wcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT +09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl +5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf3 +9/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///yH5BAEKAP8ALAAAAAAWABYAAAjXAP8JHEiwoMGD +CBMq/GdlYcI2VxwatJLnmBaJBK8YIsbsIkaGk351UtalikmTERFm+WSLEqVjypYta0YzC0Iv +p1YtavRIEqVKmDBlSmbT4BhXnwYZSrQTUiSflIwVzehKEp8/ggglYsRIkaJFkYhhMYjFVSM7 +ePDw6QNoECFCgwD5GjsxVSU5d/oMQrSz0aJDvega5BLqE59AiBpJsmRJUqNfKQ9iucTqUCJi +yJgtQ1ZMmOCDVBjRejTMy8mTC6P4uRXsM8YlcG65xiikTOSPA6Pg3s1bYEAAOw==} + +image create photo ::ttk::dialog::image::up -data { +R0lGODlhFgAWAOcAADx2Azx2BFWLIlWNIjx1A0uBGJzFdZrFckuDF0V8EJzDdnKvOm+tNZbB +bUR7Dz52CZa/cIW5UlqhGFaeEXmzQ467ZD14CIy2ZZTCaWOmI16jHFmgFlSdDoO4UIKyVTt1 +Azp2BIKsWaLKfWysMWaoKGGlIVyiGlSeD0+bCI2+X3anSDt2BHShSa3RjXexQG+tNGusLWir +J2GoHFOhCVGgB1ahDpXDamiaOWSUN7XVmIS4UXm1QXe1O3O0NG6zLFyqEVeoClenCVamCV6o +F5zIcluOKViKKLvXoL/bpb7bo73coH27QXm8OmWzGVywDFyvDKrVganTgKjRgKDLeU+FHzt1 +BDpzBD14BcDeooLBRXK7KmC2DmG4DmK4DmG3DqzZgj55BcLhpYfHSma6FGW9EGe/EGfAEWa/ +EK/cg8TjpnzDOGnDEWvHEmzIE2vGErDfhMbkqXTBKW/MFHHQFW3KE7HghGy9Hma+EGrEEm3J +E27LFGzHE7HfhMXjqa/aha7bg7Deg6/dg/////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////yH5BAEKAP8ALAAAAAAWABYAAAjWAP8JHEiwoMGD +CBMqXMiw4UEAARwWLGDgAAGJAhMoWMCggQOJDyBEkDCBQgULDQFcwJBBwwYOHTx8WAgihIgR +JEqYOIEihYoVCQGwaOHiBYwYMmbQqGHjxsWDOHLo2MGjh48fQIIIGUKkyEEjR5AkUbKESRMn +Tp5AiSJlCpWCVazIvYIli5YtXLp4+QJGrhUQCK2EETOGTBkzZ9BYYWgljRoya9i0cfNm8UIr +cOKccSNnDp06lhVitnMHTx49e/iETmilj58/gPjU4RNodWC/uOVi3L07IAA7} + +image create photo ::ttk::dialog::image::upbw -data { +R0lGODlhFgAWAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0N +DQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8f +HyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDEx +MTIyMjMzMzQ0NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkND +Q0REREVFRUZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV +VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdn +Z2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5 +eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouL +i4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2d +nZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v +r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHB +wcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT +09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl +5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf3 +9/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///yH5BAEKAP8ALAAAAAAWABYAAAjPAP8JHEiwoMGD +CBMqXMiw4cErWBwWLPPK1RWJAr+4etRIlReJWVR54oOn0qgsDa+AUjXoz547nDJdVHjFUq1F +hgT5wUOHVKOZDxP5mtRIEaJBeO7oWQUIaME9xDpZoiTpUSA/ffgEijXnIBxkzMJqyqSIkFlf +vXbVSlPwSpW3WZyBqpRo0SJFwbS8reKUYJVophw9iiQpErEqDKtI8/SI0iVMlowhXliFWqZI +ljZ5ynRsssLKkyBVyqTpUufE04YNM3asdTHPCffK3ouxdu2AADs=} + +image create photo ::ttk::dialog::image::gohome -data { +R0lGODlhFgAWAMYAAKQAAPR1deU5OeInJ+xGRvFMTPBRUfJVVeAmJvNbW/JeXntMSohaWN4m +JvNkZJldW4SFgpubmsCKitwmJvRsbPRmZp11c4+Qjbi5uMLCwbq6ucShodwlJfNjY6ONi5+g +nr+/vt7e3d3d3dfX18m1tZwICKefnaOjotra2urq6unp6efn59zQ0IQiIaGgnqKjodjY2Obm +5uTk5OPj4+Le3tvc21VXU3d4enZ5fXV1dXV2dvPz8+7u7n6Ae3+BfICCfeXl5XZ5fHmZw3eY +wnV4fPLy8u3t7YSGgYWHguLi4nV4e1+Gt0p2rnJ1evHx8ezs7IaIg4qIZYmIcODg4HF4gTRl +pG52gfDw8Ovr64eJhIiJfvn5+bGztri8wbq7vLm9waSkpO/v74iKhd7e3qKioqOjo2VnY5eZ +lJiZlpmalpmal/j4+P////////////////////////////////////////////////////// +/////////////////////////yH5BAEKAH8ALAAAAAAWABYAAAf+gH+Cg4QAAISIiYUBAYeK +j38AjIyOkIsCjAONloOSBAWZmpWPkgYHjZIIopCSCQqNCwySDauJkg4OjQ8QERKSE7WdARQV +jRYXGBkaG5IcwZEBHY0eHyAhISIjJCUBHJvCjSYnKCnlKiorLNzfgpItLi8wMSv0MTIyMzTc +o5E1Nv//0N3AkQOHjh38/tjgYaOHjx8/YgAJIiTHECJFbCSyYcTGkY9IZCRRsiQHkyZONCKy +8cQGFChRpCSZQqVKjipWrqgkZAOLjSxZtPiYsoVLFy9fwITZOchGChtioooZs4VMmatlRDAV +ZOOKmTNo0qjZwaOs2TVbFQJcyxYgp7cEcDkFAgA7} + +image create photo ::ttk::dialog::image::gohomebw -data { +R0lGODlhFgAWAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0N +DQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8f +HyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDEx +MTIyMjMzMzQ0NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkND +Q0REREVFRUZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV +VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdn +Z2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5 +eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouL +i4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2d +nZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v +r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHB +wcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT +09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl +5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf3 +9/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///yH5BAEKAP8ALAAAAAAWABYAAAj+AP8JHEgwRgyC +CBMW3LTpoMKH/2IwZOgQ4kI2DL80tDhQ4p0+GTVWfCgREKGGEruIhCgRkaKGWc6kXJlQoiNH +Dd0Q0qRJIheaHTdRgtQQ0CNcwXKtkrgFaMRNOGNM+uSrm9Vru2hs2rIxaMNQorSpG5su3blp +WrsKlPgDlChs5s7JNUeO3LhvWkdG3Falb1+zd/DUETxP778q7qr4+QMIkLlyeCjVkXRHXpWE +VdpVIcS5EDlxd/7UcUMn3mWEVdhVMWSIUCFx4Ox0qdOFDrzTBKusq3Ko9x9w+WTt0sWL1Dvc +A6uoq4KoOSJv+USNmj6qG3KBVeCVuYQpU6Z57sIPi8d3/bDf8+j9clzPnmNAADs=} + +image create photo ::ttk::dialog::image::reload -data { +R0lGODlhFgAWAOcAADtqqDtrqDdnpTVmpThopjpqpzdopjpqqHeaxaC726zG4q7I46jC3p25 +2X6hyk16sDZnpTdnpjRlpFqDt7fN5bDI4qC82q3G4bfN5rrP5rvR57vQ57vR6K/H4W+VwThp +pnOYxUZ0rkVyrJ+52Ux4sDlppjdmpU56sYWmzbbN5bXM5abC4LHK5KO/3X+iy8PW6kNxrDtq +p1N+sz5tq0BvqzZnpDpppzprqH+kzLHJ45a325G02bTM5cja7EBuqjtrpzVlpE56tGKNw0x4 +r6fA3a/J43Sfz83d7j1sqD9uq2yWyjpqqT5tqbTJ4pS22nKfz9Xi8DdopabA3cna7M3d7dTi +8Nzn8zZnpjRlpTlppzhopzZmpTVlpdrl8eDp8+Dp9OHq9Nnk8FV+szVmpOLr9aC+3qG+3dvm +8n+gx0FwrOPs9Zu63L3S6Nzm8lB8smWOxEd2sDxsqDRmpOTs9crb7K7I4sHV6oKjyzdopz5u +qz1sqUd0ruXt9sDS5tjj8dHf7qrG4sDU6bjN5YSkzGqQv1B7sj1rqEBuqVeBtZOy1sXV6Dlo +pjtppoelysjY6bDJ5LPK5KrE4Zq42j9vqURxqjxpo2qOvJSx07LJ4rbN5qK+3XKXwy9ZjzNl +pDFbkTZlojZno0FuqDdnpDZmpDRfl/////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////yH5BAEKAP8ALAAAAAAWABYAAAj+AP8JHEiwoMGD +CBMWBBBAwAACBQwYHGCwwAEECRQsYNDAwQMIAyNIKFhgAoUKFi5gyKBhA4cOHj5EABGioIgR +JCKUMAHhBIoUKlawaOHiBQyCMWTEmEGjxkAbN3Dk0LGDRw8fBH8ACSLEhsEPQ4gUMXIECUEb +SZT8W3KQSRMnT6B4HShAYRQpU6hUsXJFIUEsEm5k0WLgChaCA7YoXszF78ABXbx8ARNGjMIx +BIGQKWPmDBqJBW8ITAMAsZo1bNq4yWLQwBs4EuIQlDOHTh07Vu7gASlwQB49MPYUlMOnj58/ +gAIJGkSokKFDiFwkIlAQgqJFjBo5osBDxSMWkBYmRJI0yeAYSgMrWbqEiU2mHJo2leBksJNB +T59AhRI1ipTj/wD6FRAAOw==} + +image create photo ::ttk::dialog::image::folder_new -data { +R0lGODlhEAAQAMYAAG1va2dpZc7OzsrEuW1pXvyxPsDAv5aXlZuYkOOrVb6cZODCkfvSkNyy +bMuYSfywPsnJyaamptm5hv3nw/765/740f3urPzJZvuyQGF6mjRlpDtnoFJwlNvFnv766P77 +5P32u/3xkfzkddSsW2R4jMbY677S6MjMy+64Y/zTk/740/32vP3zo/zue/zoYPq+SNCgVK7H +44yx2I+w05yxwebFif3vrv3xkvzufPzrYfzfUe2+YV9hXdCyfvzLavzld/zoYfzgUfvDRNu6 +gVVXU5OwzeGwYs2yf+a7Zvq9SeW6YNCxeem1ZT5onpWwy5Gw0J2xwOOxX7PF2ERrm4+x0p6x +vomu1qbC4Dlnoq3H44uw14qv14iu1oWr1YCo03qk0nOgz26dzpi53Fh2m5u73XCeznCdz26c +zm2czmybzmubzWqazmmZzWiZzZS226mrqYmv12uazWqazWiYzWaYzGWYzWWXzGSWzGOVzJq6 +3lNxlkVdeT5giT9ghv///////yH5BAEKAH8ALAAAAAAQABAAAAfNgH8Ag4MBAX+IiYgAAo2O +AwSIBYoABgeXlwgJCgsMDQ4PghARpKUSExQVFhcYfwEGGRqyGxwdHh8gISIjJAEQGiUmJico +KSorLC0uLzCvGjEyMjM0NTY3ODk6Oxw8v9DRMj0+P0BBQkMaRAbP4EVGR0hJSktMTUTe4E5P +MlBRNDJSpqhjBy4alSozrFxJBwFLFi0ytGzh0sXLFzBhxKQzMIZMGTNhzqBJo2YNmzZu0r2B +oyaOHDZz6NSxcwdPHj17+MjayZNnH0VAgyIKBAA7} + +image create photo ::ttk::dialog::image::configure -data { +R0lGODlhFgAWAMYAAH9/f+rp6Pn5+NjY1/j39vPy8YKXsjRlpOzq6P///050pHx8fLu7u+3r +6szMzK+vr2WErOjn5Orq6q2trePj4vr6+Xl4dNzc3JmZmejn5vLx7+3r6evp5/r6+oeHh8/N +yvj49/n59/n49/7+/p6enrW1tfb29Z+fnvj4+Ofm5LvByEVxqfT09J2wyt/f31l9q6enpiBK +h1R8rqSttvv7+3WQrqS60JCmvqexvcHBwePi4dPf6qKuvJ22zmN7lYScttfi7Y2YpZ240mB3 +kZmtw9/n8IGTqVhthFtxiYaGhqG0yO7z9mB2j+Tj4V9fXpGmvvD095eltgAAALDG2+3y9oGK +lWyFocDR4v////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////yH5BAEKAH8ALAAAAAAWABYAAAfygH+CggAAg4eIiX8AAQID +hoqRhAQFj5EGB5EACAKQiAcJCpl/C4WCDA2diaAODxCEERIAExQIFRarFw+jfxgZGhsIHMOq +gwcdB7yCHh8gAiECwyKQByPKhySFACUCwiYnByjXkgACKSorLOOSiy0HLi8w7Icx9QcsMjM0 +npIxNTY3YhzAkUPHCH6J/O3g0cNHDAAjhh2MFOMHkCA+hAyJsWiEsImIYhApYuSIkBpIOHaU +mISekiVGmJxMeQhiEycgYzyBEkUmSpWCpAgdKvRPjClUqswEGpToUKNWhFx5QjORUymDYlix +4lAS0ZD15hUVFAgAOw==} + +image create photo ::ttk::dialog::image::folder -data { +R0lGODlhEAAQAKUAAG1va2dpZc7OzsbGxWNlYcDAv5aXlVVXU8nJyaampqenp6ioqGF6mjRl +pEZtnMbY677S6K7H44yx2F9hXYmu1qbC4Dlnoq3H44uw14qv14iu1oWr1YCo03qk0nOgz26d +zpi53Fh2m5u73XCeznCdz26czm2czmybzmubzWqazmmZzWiZzZS226mrqYmv12uazWqazWiY +zWaYzGWYzWWXzGSWzGOVzJq63lNxlkVdeT5giT9ghv///////////////yH5BAEKAD8ALAAA +AAAQABAAAAaGwB9gOAwEfsgkEiBoOgcEZRJQMFivhoNWu0QkvmCwYnFABgqMhnrNVjsCiMYD +Qq/bH41zIyLp+/8RDRNxfH+GgQcFe4aHDQeEjICOioWRFBWOCBYXGBIYGRobHB0eHyCTISIj +JB8lJicoKSorLI4tLigvMCoxMjM0NTY3ODk6bcdqO1LLy0EAOw==} + +image create photo ::ttk::dialog::image::file -data { +R0lGODlhEAAQAIQAAJmZmYGBgf///+zs7Orq6uvr6+3t7fDw8MTExMXFxcbGxsfHx+7u7u3t +5e3t5u/v78jIyPHx8fLy8pWVlf////////////////////////////////////////////// +/yH5BAEKAB8ALAAAAAAQABAAAAVuIBCMZDl+aCCsbLsGqTAQRGEPg3EI8KcSiERCQVQsdr3f +DWcwMJCxwrBIPPKiBaahMXhefYIClcFweJOynJPxaEPBg+JiAam/VTmyO8L/qgxGdHV8En4C +TWwPBwcREoVoLpE9EyaVARMomZqbmiEAOw==} + +# Images for ttk::chooseDirectory + +image create photo ::ttk::dialog::image::dirclose -data { +R0lGODlhCQAJAKUAAFRWUlVXU1pcWP///1lbV2BiXt/i3Obo5O3u6/P08vj4911fW2NlYeHk +3+bp5Ovt6u/x7vDx72ZoZAAAAGNmYWpsZ93g2t7h2+Di3WdpZG1vatjb1dfb1Njb1Nfb09XZ +0WpsaHBybW1wa3N1cP////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////yH5BAEKAD8ALAAA +AAAJAAkAAAY4QEBgSBwKBsjkgFAYGA6IhGKwYAwajgckMihIBpNweECpDCwXDOYyyGgGG07H +8xmAQsqkaMTv94MAOw==} + +image create photo ::ttk::dialog::image::diropen -data { +R0lGODlhCQAJAKUAAFRWUlVXU1pcWP///1lbV2BiXt/i3Obo5AAAAPP08vj4911fW2NlYeHk +3+bp5O/x7vDx72ZoZGNmYWpsZ93g2t7h2+Di3WdpZG1vatjb1dfb1Nfb09XZ0WpsaHBybW1w +a3N1cP////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////yH5BAEKAD8ALAAA +AAAJAAkAAAY4QEBgSBwKBsjkgFAYGA6IhGKwYAwaDsQDMihEBohweCCZDCgVhKUyuGAGGQ1i +wxl0PMrkB8Tv94MAOw==} + +### ttk::getOpenFile, ttk::getSaveFile, ttk::getAppendFile + +proc ttk::getOpenFile {args} { + return [::ttk::dialog::file::tkFDialog open $args] +} + +proc ttk::getSaveFile {args} { + return [::ttk::dialog::file::tkFDialog save $args] +} + +proc ttk::getAppendFile {args} { + return [::ttk::dialog::file::tkFDialog append $args] +} + +proc ::ttk::dialog::file::Create {win class} { + toplevel $win -class $class + wm withdraw $win + + set dataName [winfo name $win] + upvar ::ttk::dialog::file::$dataName data + + # Additional frame to make sure the toplevel has the correct + # background color for the theme + # + set w [ttk::frame $win.f] + pack $w -fill both -expand 1 + + # f1: the toolbar + # + set f1 [ttk::frame $w.f1 -class Toolbar] + set data(bgLabel) [ttk::label $f1.bg -style Toolbutton] + set data(upBtn) [ttk::button $f1.up -style Toolbutton] + $data(upBtn) configure -image {::ttk::dialog::image::up + disabled ::ttk::dialog::image::upbw} \ + -command [list ::ttk::dialog::file::UpDirCmd $win] + set data(prevBtn) [ttk::button $f1.prev -style Toolbutton] + $data(prevBtn) configure -image {::ttk::dialog::image::previous + disabled ::ttk::dialog::image::previousbw} \ + -command [list ::ttk::dialog::file::PrevDirCmd $win] + set data(nextBtn) [ttk::button $f1.next -style Toolbutton] + $data(nextBtn) configure -image {::ttk::dialog::image::next + disabled ::ttk::dialog::image::nextbw} \ + -command [list ::ttk::dialog::file::NextDirCmd $win] + set data(homeBtn) [ttk::button $f1.home -style Toolbutton] + $data(homeBtn) configure -image {::ttk::dialog::image::gohome \ + disabled ::ttk::dialog::image::gohomebw} \ + -command [list ::ttk::dialog::file::HomeDirCmd $win] + set data(reloadBtn) [ttk::button $f1.reload -style Toolbutton] + $data(reloadBtn) configure -image ::ttk::dialog::image::reload \ + -command [list ::ttk::dialog::file::Update $win] + set data(newBtn) [ttk::button $f1.new -style Toolbutton] + $data(newBtn) configure -image ::ttk::dialog::image::folder_new \ + -command [list ::ttk::dialog::file::NewDirCmd $win] + set data(cfgBtn) [ttk::menubutton $f1.cfg -style Toolbutton] + set data(cfgMenu) [menu $data(cfgBtn).menu -tearoff 0] + $data(cfgBtn) configure -image ::ttk::dialog::image::configure \ + -menu $data(cfgMenu) + set data(dirMenuBtn) [ttk::combobox $f1.menu] + $data(dirMenuBtn) configure \ + -textvariable ::ttk::dialog::file::${dataName}(selectPath) + + set data(sortMenu) [menu $data(cfgMenu).sort -tearoff 0] + + $data(cfgMenu) add cascade -label " Sorting" -menu $data(sortMenu) + $data(cfgMenu) add separator + $data(cfgMenu) add radiobutton -label "Short View" \ + -variable ::ttk::dialog::file::details -value 0 \ + -command [list ::ttk::dialog::file::setopt $win \ + -details ::ttk::dialog::file::details] + $data(cfgMenu) add radiobutton -label "Detailed View" \ + -variable ::ttk::dialog::file::details -value 1 \ + -command [list ::ttk::dialog::file::setopt $win \ + -details ::ttk::dialog::file::details] + $data(cfgMenu) add separator + $data(cfgMenu) add checkbutton -label "Show Hidden Files" \ + -variable ::ttk::dialog::file::hidden \ + -command [list ::ttk::dialog::file::setopt $win \ + -hidden ::ttk::dialog::file::hidden] + $data(cfgMenu) add checkbutton -label "Separate Folders" \ + -variable ::ttk::dialog::file::sepfolders \ + -command [list ::ttk::dialog::file::setopt $win \ + -sepfolders ::ttk::dialog::file::sepfolders] + $data(sortMenu) add radiobutton -label "By Name" \ + -variable ::ttk::dialog::file::sort -value name \ + -command [list ::ttk::dialog::file::setopt $win \ + -sort ::ttk::dialog::file::sort] + $data(sortMenu) add radiobutton -label "By Date" \ + -variable ::ttk::dialog::file::sort -value date \ + -command [list ::ttk::dialog::file::setopt $win \ + -sort ::ttk::dialog::file::sort] + $data(sortMenu) add radiobutton -label "By Size" \ + -variable ::ttk::dialog::file::sort -value size \ + -command [list ::ttk::dialog::file::setopt $win \ + -sort ::ttk::dialog::file::sort] + $data(sortMenu) add separator + $data(sortMenu) add checkbutton -label "Reverse" \ + -variable ::ttk::dialog::file::reverse \ + -command [list ::ttk::dialog::file::setopt $win \ + -reverse ::ttk::dialog::file::reverse] + $data(sortMenu) add checkbutton -label "Folders First" \ + -variable ::ttk::dialog::file::foldersfirst \ + -command [list ::ttk::dialog::file::setopt $win \ + -foldersfirst ::ttk::dialog::file::foldersfirst] + + $data(prevBtn) state disabled + $data(nextBtn) state disabled + if {![info exists ::env(HOME)]} { + $data(homeBtn) state disabled + } + + place $data(bgLabel) -relheight 1 -relwidth 1 + + pack $data(upBtn) -side left -fill y + pack $data(prevBtn) -side left -fill y + pack $data(nextBtn) -side left -fill y + pack $data(homeBtn) -side left -fill y + pack $data(reloadBtn) -side left -fill y + pack $data(newBtn) -side left -fill y + pack $data(cfgBtn) -side left -fill y + pack $data(dirMenuBtn) -side left -fill x -expand 1 -padx 8 + + # f2: the frame with the OK button, cancel button, "file name" field, + # and file types field. + # + set f2 [ttk::frame $w.f2] + ttk::label $f2.lab1 -text "Location:" -anchor w + set data(location) [ttk::combobox $f2.loc] + $data(location) configure \ + -textvariable ::ttk::dialog::file::${dataName}(selectFile) + set data(typeMenuLab) [ttk::label $f2.lab2 -text "Filter:" -anchor w] + set data(typeMenuBtn) [ttk::combobox $f2.filter] + set data(okBtn) [ttk::button $f2.ok -text OK -default active \ + -width 8 -style Slim.TButton \ + -command [list ::ttk::dialog::file::Done $win]] + set data(cancelBtn) [ttk::button $f2.cancel -text Cancel \ + -width 8 -style Slim.TButton \ + -command [list ::ttk::dialog::file::Cancel $win]] + + grid $f2.lab1 $f2.loc $data(okBtn) -padx 4 -pady 5 -sticky ew + grid $f2.lab2 $f2.filter $data(cancelBtn) -padx 4 -pady 5 -sticky ew + grid columnconfigure $f2 1 -weight 1 + + # f3: The file and directory lists + # + set f3 [ttk::panedwindow $w.f3 -orient horizontal] + set font TkDefaultFont + destroy $f3.dummy + $f3 add [ttk::frame $f3.dir] -weight 0 + ttk::label $f3.dir.bg -relief sunken + set data(dirArea) [text $f3.dir.t -bg white -width 20 -height 16 \ + -font $font -bd 0 -highlightthickness 0 -cursor "" \ + -wrap none -spacing1 1 -spacing3 1 -exportselection 0 \ + -state disabled -yscrollcommand [list $f3.dir.y set] \ + -xscrollcommand [list $f3.dir.x set]] + ttk::scrollbar $f3.dir.y -command [list $f3.dir.t yview] + ttk::scrollbar $f3.dir.x -command [list $f3.dir.t xview] \ + -orient horizontal + grid $f3.dir.t $f3.dir.y -sticky ns + grid $f3.dir.x -sticky we + grid $f3.dir.bg -row 0 -column 0 -rowspan 2 -columnspan 2 -sticky news + grid $f3.dir.t -sticky news -padx {2 0} -pady {2 0} + grid columnconfigure $f3.dir 0 -weight 1 + grid rowconfigure $f3.dir 0 -weight 1 + + $f3 add [ttk::frame $f3.file] -weight 1 + + # The short view version + # + set data(short) [ttk::frame $f3.file.short] + ttk::label $data(short).bg -relief sunken + set data(fileArea) [text $data(short).t -width 50 -height 16 \ + -bg white -font $font -bd 0 -highlightthickness 0 \ + -cursor "" -wrap none -spacing1 1 -spacing3 1 \ + -exportselection 0 -state disabled \ + -xscrollcommand [list ::ttk::dialog::file::scrollset $win]] + set data(xScroll) [ttk::scrollbar $data(short).x -orient horizontal \ + -command [list ::ttk::dialog::file::xview $win]] +# set data(xScroll) [ttk::scrollbar $data(short).x -orient horizontal \ +# -command [list $data(short).t xview]] + grid $data(short).t -sticky news -padx 2 -pady {2 0} + grid $data(short).x -sticky ew + grid $data(short).bg -row 0 -column 0 \ + -rowspan 2 -columnspan 2 -sticky news + grid columnconfigure $data(short) 0 -weight 1 + grid rowconfigure $data(short) 0 -weight 1 + + # The detailed view version + # + set data(long) [ttk::frame $f3.file.long] + ttk::label $data(long).bg -relief sunken + ttk::frame $data(long).f + set data(fileHdr) [frame $data(long).f.f] + ttk::label $data(fileHdr).l0 -text Name -style Toolbutton -anchor w + ttk::label $data(fileHdr).l1 -text Size -style Toolbutton -anchor w + ttk::label $data(fileHdr).l2 -text Date -style Toolbutton -anchor w + ttk::label $data(fileHdr).l3 -text Permissions -style Toolbutton -anchor w + ttk::label $data(fileHdr).l4 -text Owner -style Toolbutton -anchor w + ttk::label $data(fileHdr).l5 -text Group -style Toolbutton -anchor w + ttk::separator $data(fileHdr).s1 -orient vertical + ttk::separator $data(fileHdr).s2 -orient vertical + ttk::separator $data(fileHdr).s3 -orient vertical + ttk::separator $data(fileHdr).s4 -orient vertical + ttk::separator $data(fileHdr).s5 -orient vertical + set height [winfo reqheight $data(fileHdr).l1] + $data(long).f configure -height [expr {$height + 1}] + $data(fileHdr) configure -height $height + place $data(fileHdr) -x 1 -relwidth 1 + place $data(fileHdr).l0 -x -1 -relwidth 1 -relheight 1 + place $data(fileHdr).s1 -rely .1 -relheight .8 -anchor n + place $data(fileHdr).s2 -rely .1 -relheight .8 -anchor n + place $data(fileHdr).s3 -rely .1 -relheight .8 -anchor n + place $data(fileHdr).s4 -rely .1 -relheight .8 -anchor n + place $data(fileHdr).s5 -rely .1 -relheight .8 -anchor n + set data(fileList) [text $data(long).t -width 42 -height 12 \ + -bg white -font $font -bd 0 -highlightthickness 0 \ + -cursor "" -wrap none -spacing1 1 -spacing3 1 \ + -exportselection 0 -state disabled \ + -yscrollcommand [list $data(long).y set] \ + -xscrollcommand [list ::ttk::dialog::file::scrollhdr $win]] + ttk::scrollbar $data(long).y -command [list $data(long).t yview] + ttk::scrollbar $data(long).x -orient horizontal \ + -command [list $data(long).t xview] + grid $data(long).f $data(long).y -sticky ew -padx {2 0} -pady {2 0} + grid $data(long).t ^ -sticky news -padx {2 0} + grid $data(long).x -sticky ew + grid $data(long).y -sticky ns -padx 0 -pady 0 + grid $data(long).bg -row 0 -column 0 \ + -rowspan 3 -columnspan 2 -sticky news + grid columnconfigure $data(long) 0 -weight 1 + grid rowconfigure $data(long) 1 -weight 1 + + grid $data(long) $data(short) -row 0 -column 0 -sticky news + grid columnconfigure $f3.file 0 -weight 1 + grid rowconfigure $f3.file 0 -weight 1 + + # Get rid of the default Text bindings + bindtags $data(dirArea) [list $data(dirArea) FileDialogDir $win all] + bindtags $data(fileArea) [list $data(fileArea) FileDialogFile $win all] + bindtags $data(fileList) [list $data(fileList) FileDialogList $win all] + + $data(fileArea) tag bind file <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileArea) tag bind characterSpecial <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileArea) tag bind blockSpecial <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileArea) tag bind fifo <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileArea) tag bind link <1> \ + {set ::ttk::dialog::file::filetype link} + $data(fileArea) tag bind directory <1> \ + {set ::ttk::dialog::file::filetype directory} + $data(fileList) tag bind file <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileList) tag bind characterSpecial <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileList) tag bind blockSpecial <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileList) tag bind fifo <1> \ + {set ::ttk::dialog::file::filetype file} + $data(fileList) tag bind link <1> \ + {set ::ttk::dialog::file::filetype link} + $data(fileList) tag bind directory <1> \ + {set ::ttk::dialog::file::filetype directory} + + set data(paneWin) $f3 + + pack $f1 -side top -fill x + pack $f2 -side bottom -fill x -padx 8 -pady {0 5} + pack $f3 -side bottom -fill both -expand 1 -padx 8 -pady {6 0} + + set data(columns) 0 + set data(history) "" + set data(histpos) -1 + + update idletasks + pack propagate $w 0 + + wm protocol $win WM_DELETE_WINDOW [list $data(cancelBtn) invoke] + + bind $data(fileArea) \ + [list ::ttk::dialog::file::configure $win] + bind $data(dirMenuBtn) [list ::ttk::dialog::file::chdir $win] + bind $data(dirMenuBtn) <> \ + [list ::ttk::dialog::file::chdir $win] + bind $data(location) [list ::ttk::dialog::file::Done $win] + bind $data(typeMenuBtn) \ + [list ::ttk::dialog::file::SetFilter $win] + bind $data(typeMenuBtn) <> \ + [list ::ttk::dialog::file::SelectFilter $win] +} + +proc ::ttk::dialog::file::ChangeDir {w dir} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + set data(history) [lrange $data(history) 0 $data(histpos)] + set cwd [lindex $data(history) $data(histpos)] + set data(selectPath) [file normalize [file join $cwd $dir]] + lappend data(history) $data(selectPath) + if {[incr data(histpos)]} { + $data(prevBtn) state !disabled + #set data(selectFile) "" + } + $data(nextBtn) state disabled + + UpdateWhenIdle $w +} + +proc ::ttk::dialog::file::UpdateWhenIdle {w} { + upvar ::ttk::dialog::file::[winfo name $w] data + + if {[info exists data(updateId)]} { + return + } elseif {[winfo ismapped $w]} { + set after idle + } else { + set after 1 + } + set data(updateId) [after $after [list ::ttk::dialog::file::Update $w]] +} + +proc ::ttk::dialog::file::Update {w} { + # This proc may be called within an idle handler. Make sure that the + # window has not been destroyed before this proc is called + if {![winfo exists $w]} { + return + } + + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + unset -nocomplain data(updateId) + + if {$data(-details)} { + grid $data(long) + grid remove $data(short) + } else { + grid $data(short) + grid remove $data(long) + } + if {$data(-sepfolders)} { + if {![llength [winfo manager $data(paneWin).dir]]} { + $data(paneWin) insert 0 $data(paneWin).dir + } + } else { + if {[llength [winfo manager $data(paneWin).dir]]} { + $data(paneWin) forget 0 + } + } + + $w configure -cursor watch + update + + set dir ::ttk::dialog::image::folder + set file ::ttk::dialog::image::file + + set cwd [lindex $data(history) $data(histpos)] + + if {$data(-hidden)} { + set pattern "* .*" + } else { + set pattern "*" + } + + # Make the directory list + set dlist "" + foreach f [eval glob -nocomplain -tails \ + -directory $cwd -type d $pattern] { + if {[string equal $f .]} continue + if {[string equal $f ..]} continue + lappend dlist [list $f dir] + } + + # Make the file list + set flist "" + set filter $data(filter) + if {[string equal $filter *]} { + set filter $pattern + } + foreach f [eval [linsert $filter 0 glob -nocomplain -tails \ + -directory $cwd -type {f l c b p}]] { + # Links can still be directories. Skip those. + if {[file isdirectory [file join $cwd $f]]} continue + lappend flist [list $f file] + } + + # Combine the two lists, if necessary + if {$data(-sepfolders)} { + set dlist [sort $w $dlist] + set flist [sort $w $flist] + } elseif {$data(-foldersfirst)} { + set flist [concat [sort $w $dlist] [sort $w $flist]] + set dlist "" + } else { + set flist [sort $w [concat $flist $dlist]] + set dlist "" + } + + set t $data(dirArea) + $t configure -state normal + $t delete 1.0 end + foreach f $dlist { + $t image create end -image $dir + $t insert end " [lindex $f 0]\n" + } + $t delete end-1c end + $t configure -state disabled + + if {$data(-details)} { + set t $data(fileList) + $t configure -state normal + $t delete 1.0 end + set size "" + set date "" + set mode "" + set uid "" + set gid "" + set maxsize 50 + set font [$t cget -font] + foreach f $flist { + lassign $f name type size date mode uid gid + if {![info exists users($uid)] || \ + ![info exists groups($gid)]} { + set fname [file join $cwd $name] + # May fail for dead links + if {![catch {array set attr \ + [file attributes $fname]}]} { + if {[info exists attr(-owner)]} { + set users($uid) $attr(-owner) + } else { + set users($uid) "" + } + if {[info exists attr(-group)]} { + set groups($gid) $attr(-group) + } else { + set groups($gid) "" + } + } + } + catch {set uid $users($uid)} + catch {set gid $groups($gid)} + set image [expr {$type eq "directory" ? $dir : $file}] + set img [$t image create end -image $image] + $t tag add name $img + $t tag add $type $img + $t insert end " $name" [list name $type] + $t insert end "\t$size\t" $type + $t insert end "[datefmt $date]\t" $type + $t insert end "[modefmt $type $mode]\t" $type + $t insert end "$uid\t$gid\t\n" $type + set size [font measure $font " $name"] + if {$size > $maxsize} { + set maxsize $size + } + } + $t delete end-1c end + $t configure -state disabled + set today [datefmt [clock seconds]] + set maxp [winfo reqwidth $data(fileHdr).l3] + set maxu [winfo reqwidth $data(fileHdr).l4] + foreach n [array names users] { + set size [font measure $font $users($n)] + if {$size > $maxu} {set maxu $size} + } + set maxg [winfo reqwidth $data(fileHdr).l5] + foreach n [array names groups] { + set size [font measure $font $groups($n)] + if {$size > $maxg} {set maxg $size} + } + set tabs [list [set x [incr maxsize 22]]] + lappend tabs [incr x [font measure $font 1000000000]] \ + [incr x [font measure $font " $today "]] \ + [incr x [incr maxp 8]] \ + [incr x [incr maxu 8]] [incr x [incr maxg 8]] + $t configure -tabs $tabs + set i 1 + foreach n $tabs { + place $data(fileHdr).l$i -x $n + place $data(fileHdr).s$i -x $n + if {[incr i] > 5} break + } + } else { + set t $data(fileArea) + $t configure -state normal + $t delete 1.0 end + set lines [expr {[winfo height $t] / 18}] + set row 1 + set col 0 + set maxsize 50 + set list "" + set font [$t cget -font] + foreach f $flist { + set idx "$row.end" + lassign $f name type + set image [expr {$type eq "directory" ? $dir : $file}] + set img [$t image create $idx -image $image] + $t tag add $type $img + $t tag add name $img + $t insert $idx " $name" [list name $type] "\t" $type + lappend list $name $type + set size [font measure $font " $name"] + if {$size > $maxsize} { + set maxsize $size + } + if {[incr row] > $lines} { + incr col + set row 1 + } elseif {$col == 0} { + $t insert $idx "\n" + } + } + # Make sure maxsize is a multiple of an average size character + set dx [font measure $font 0] + set maxsize [expr {($maxsize + 20 + $dx) / $dx * $dx}] + $t insert 1.end "\t" + $t configure -state disabled + $t configure -tabs $maxsize + set data(columns) [expr {$row > 1 ? $col + 1 : $col}] + set data(rows) $lines + set data(colwidth) $maxsize + set data(list) $list + } + + if {[string equal $cwd "/"]} { + $data(upBtn) state disabled + } else { + $data(upBtn) state !disabled + } + $w configure -cursor "" +} + +proc ::ttk::dialog::file::sort {w list} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + set cwd [lindex $data(history) $data(histpos)] + set order [expr {$data(-reverse) ? "-decreasing" : "-increasing"}] + set newlist "" + foreach f $list { + set file [lindex $f 0] + # Use lstat in case the destination doesn't exists + file lstat [file join $cwd $file] stat + if {[string equal $stat(type) link]} { + # This may fail if the link points to nothing + if {![catch {file stat [file join $cwd $file] dest}]} { + array set stat [array get dest] + if {[string equal $stat(type) file]} { + set stat(type) link + } + } + } + lappend newlist [list $file $stat(type) $stat(size) \ + $stat(mtime) $stat(mode) $stat(uid) $stat(gid)] + } + switch -- $data(-sort) { + size { + set mode -integer + set idx 2 + } + date { + set mode -integer + set idx 3 + } + default { + set mode -dictionary + set idx 0 + } + } + lsort $order $mode -index $idx $newlist +} + +proc ::ttk::dialog::file::datefmt {str} { + clock format $str -format {%d-%m-%Y %H:%M} +} + +proc ::ttk::dialog::file::modefmt {type mode} { + switch $type { + file {set rc -} + default {set rc [string index $type 0]} + } + binary scan [binary format I $mode] B* bits + foreach b [split [string range $bits end-8 end] ""] \ + c {r w x r w x r w x} { + if {$b} {append rc $c} else {append rc -} + } + set rc +} + +proc ::ttk::dialog::file::xview {w cmd number {units ""}} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + set width [winfo width $data(fileArea)] + lassign [$data(fileArea) xview] pos1 pos2 + set cols $data(columns) + set page [expr {int($width / $data(colwidth))}] + if {!$page} {set page 1} + + switch $cmd { + scroll { + set col [expr {round($pos1 * ($cols + 1))}] + if {[string match p* $units]} { + incr col [expr {$number * $page}] + } else { + incr col $number + } + } + moveto { + set col [expr {round($number * $cols)}] + } + } + set max [expr {$cols - $page}] + if {$col > $max} {set col $max} + if {$col < 0} {set col 0} + set pos [expr {double($col) / ($cols + 1)}] + $data(fileArea) xview moveto $pos +} + +proc ::ttk::dialog::file::scrollset {w first last} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + if {$data(columns)} { + if {$last >= 0.999} { + xview $w scroll -1 units + return + } + set w $data(colwidth) + set cols $data(columns) + set width [winfo width $data(fileArea)] + set vwidth [expr {$width % $w + $cols * $w}] + set total [expr {$width / ($last - $first)}] + set first [expr {$first * $total / $vwidth}] + set last [expr {$last * $total / $vwidth}] + } + + $data(xScroll) set $first $last +} + +proc ::ttk::dialog::file::scrollhdr {w first last} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + lassign [$data(fileList) dlineinfo @0,0] x y width height base + place $data(fileHdr) -x $x -width $width + $data(long).x set $first $last +} + +proc ::ttk::dialog::file::configure {w} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + if {$data(columns) == 0} return + + set dir ::ttk::dialog::image::folder + set file ::ttk::dialog::image::file + + set h [winfo height $data(fileArea)] + set rows [expr {$h / 18}] + if {$rows == $data(rows)} return + set t $data(fileArea) + set lines $rows + set row 1 + set col 0 + $t configure -state normal + $t delete 1.0 end + foreach {name type} $data(list) { + set idx $row.end + set image [expr {$type eq "directory" ? $dir : $file}] + $t tag add file [$t image create $idx -image $image] + $t insert $idx " $name" file "\t" + if {[incr row] > $lines} { + incr col + set row 1 + } elseif {$col == 0} { + $t insert $idx "\n" + } + } + $t insert 1.end "\t" + $t configure -state disabled + set data(columns) [expr {$row > 1 ? $col + 1 : $col}] + set data(rows) $lines +} + +proc ::ttk::dialog::file::setopt {w option var} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + upvar #0 $var value + + + set data($option) $value + UpdateWhenIdle $w +} + +proc ::ttk::dialog::file::UpDirCmd {w} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + ChangeDir $w [file dirname [lindex $data(history) $data(histpos)]] +} + +proc ::ttk::dialog::file::PrevDirCmd {w} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + set data(selectFile) "" + incr data(histpos) -1 + set data(selectPath) [lindex $data(history) $data(histpos)] + $data(nextBtn) state !disabled + if {!$data(histpos)} { + $data(prevBtn) state disabled + } + Update $w +} + +proc ::ttk::dialog::file::NextDirCmd {w} { + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + set data(selectFile) "" + incr data(histpos) + set data(selectPath) [lindex $data(history) $data(histpos)] + $data(prevBtn) state !disabled + if {$data(histpos) >= [llength $data(history)] - 1} { + $data(nextBtn) state disabled + } + Update $w +} + +proc ::ttk::dialog::file::HomeDirCmd {w} { + ChangeDir $w ~ +} + +proc ::ttk::dialog::file::NewDirCmd {win} { + set dataName [winfo name $win] + upvar ::ttk::dialog::file::$dataName data + + set dir [lindex $data(history) $data(histpos)] + + toplevel $win.new + wm title $win.new "New Folder" + set w [ttk::frame $win.new.f] + pack $w -expand 1 -fill both + + ttk::label $w.prompt -anchor w -justify left \ + -text "Create new folder in:\n$dir" + ttk::entry $w.box -width 36 -validate all \ + -validatecommand [list ::ttk::dialog::file::NewDirVCmd $w %P] + ttk::separator $w.sep + set f [ttk::frame $w.buttons] + ttk::button $f.clear -text Clear -takefocus 0 \ + -command [list $w.box delete 0 end] + ttk::button $f.ok -text OK -default active \ + -command [list ::ttk::dialog::file::NewDirExit $win 1] + ttk::button $f.cancel -text Cancel \ + -command [list ::ttk::dialog::file::NewDirExit $win] + grid $f.clear $f.ok $f.cancel -padx 4 -pady {0 10} -sticky we + grid columnconfigure $f {0 1 2} -uniform 1 + pack $w.prompt $w.box $w.sep $f \ + -side top -padx 12 -pady 3 -anchor w -fill x + pack $w.prompt -pady {12 0} + pack $f -anchor e -fill none -padx 8 + wm transient $win.new $win + wm resizable $win.new 0 0 + wm protocol $win.new WM_DELETE_WINDOW [list $f.cancel invoke] + + bind $w.box [list $f.ok invoke] + + ::tk::PlaceWindow $win.new widget $win + ::tk::SetFocusGrab $win.new $w.box +} + +proc ::ttk::dialog::file::NewDirVCmd {w str} { + if {[string length $str]} { + $w.buttons.ok state !disabled + $w.buttons.clear state !disabled + } else { + $w.buttons.ok state disabled + $w.buttons.clear state disabled + } + return 1 +} + +proc ::ttk::dialog::file::NewDirExit {w {save 0}} { + upvar ::ttk::dialog::file::[winfo name $w] data + + if {$save} { + set dir [lindex $data(history) $data(histpos)] + set newdir [file join $dir [$w.new.f.box get]] + if {[catch {file mkdir $newdir} err]} { + ttk::messageBox -type ok -parent $w.new -icon error \ + -message "$err" + return + } else { + ChangeDir $w $newdir + } + } + destroy $w.new + ::tk::RestoreFocusGrab $w.new $w.new.f.box +} + +proc ::ttk::dialog::file::Cancel {w} { + variable selectFilePath "" +} + +proc ::ttk::dialog::file::Done {w} { + variable selectFilePath + variable filelist + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + if {![string length $data(selectFile)] || \ + [string equal $data(selectFile) .]} { + return -code break + } + + set cwd [lindex $data(history) $data(histpos)] + set path [file join $cwd $data(selectFile)] + + if {[file isdirectory $path]} { + ChangeDir $w $path + return -code break + } + + if {![string length [file extension $path]]} { + append path $data(-defaultextension) + } + + if {[file exists $path]} { + if {[string equal $data(type) save]} { + set reply [ttk::messageBox -icon warning -type yesno \ + -parent $w -message "File\ + \"$path\" already exists.\nDo\ + you want to overwrite it?"] + if {[string equal $reply "no"]} {return} + } + } else { + if {[string equal $data(type) open]} { + ttk::messageBox -icon warning -type ok -parent $w \ + -message "File \"$path\" does not exist." + return + } + } + + set idx [lsearch -exact $filelist $path] + set filelist [linsert [lreplace $filelist $idx $idx] 0 $path] + + set selectFilePath $path + return -code break +} + +proc ::ttk::dialog::file::chdir {w} { + upvar ::ttk::dialog::file::[winfo name $w] data + + set dir $data(selectPath) + if {[file isdirectory $dir]} { + ChangeDir $w $dir + } else { + ttk::messageBox -type ok -parent $w \ + -message "Cannot change to the directory\ + \"$data(selectPath)\".\nPermission denied." \ + -icon warning + } + return -code break +} + +proc ::ttk::dialog::file::SelectFilter {w} { + upvar ::ttk::dialog::file::[winfo name $w] data + + set data(filter) [lindex $data(-filetypes) \ + [$data(typeMenuBtn) current] 1] + ::ttk::dialog::file::UpdateWhenIdle $w +} + +proc ::ttk::dialog::file::SetFilter {w} { + upvar ::ttk::dialog::file::[winfo name $w] data + + set data(filter) [$data(typeMenuBtn) get] + ::ttk::dialog::file::UpdateWhenIdle $w + return -code break +} + +proc ::ttk::dialog::file::DirButton1 {w x y} { + scan [$w index @$x,$y] %d.%d line char + $w tag remove sel 1.0 end + $w tag add sel $line.2 $line.end +} + +proc ::ttk::dialog::file::DirRelease1 {w x y} { + set top [winfo toplevel $w] + $top configure -cursor "" +} + +proc ::ttk::dialog::file::DirDouble1 {w x y} { + set dir [$w get sel.first sel.last] + ChangeDir [winfo toplevel $w] $dir +} + +proc ::ttk::dialog::file::DirMotion1 {w x y} { + [winfo toplevel $w] configure -cursor "X_cursor #C00 #000" +} + +proc ::ttk::dialog::file::FileButton1 {w x y} { + set dataName [winfo name [winfo toplevel $w]] + upvar ::ttk::dialog::file::$dataName data + variable filetype + + if {[string equal $filetype none]} return + + set range [$w tag prevrange name @$x,$y+1c "@$x,$y linestart"] + if {[llength $range]} { + lassign $range index1 index2 + $w tag remove sel 1.0 end + $w tag add sel $index1+2c $index2 + if {$filetype eq "file" || $filetype eq "link"} { + set data(selectFile) [$w get sel.first sel.last] + } + } +} + +proc ::ttk::dialog::file::FileRelease1 {w x y} { + set dataName [winfo name [winfo toplevel $w]] + upvar ::ttk::dialog::file::$dataName data + variable filetype + + set top [winfo toplevel $w] + if {[llength [$top cget -cursor]]} { + # The mouse has been moved, don't perform the action + $top configure -cursor "" + } elseif {![string equal $filetype directory]} { + # A file was selected + } elseif {[llength [$w tag ranges sel]]} { + set dir [$w get sel.first sel.last] + ChangeDir [winfo toplevel $w] $dir + } + [winfo toplevel $w] configure -cursor "" + set filetype none +} + +proc ::ttk::dialog::file::FileMotion1 {w x y} { + [winfo toplevel $w] configure -cursor "X_cursor #C00 #000" +} + +proc ::ttk::dialog::file::tkFDialog {type arglist} { + global env + variable selectFilePath + variable filelist + set dataName __ttk_filedialog + upvar ::ttk::dialog::file::$dataName data + + ::ttk::dialog::file::Config $dataName $type $arglist + + if {[string equal $data(-parent) .]} { + set w .$dataName + } else { + set w $data(-parent).$dataName + } + + if {![winfo exists $w]} { + ::ttk::dialog::file::Create $w TkFDialog + } elseif {![string equal [winfo class $w] TkFDialog]} { + destroy $w + ::ttk::dialog::file::Create $w TkFDialog + } else { + $data(fileArea) configure -state normal + $data(fileArea) delete 1.0 end + $data(fileArea) configure -state disabled + $data(dirArea) configure -state normal + $data(dirArea) delete 1.0 end + $data(dirArea) configure -state disabled + $data(prevBtn) state disabled + $data(nextBtn) state disabled + $data(upBtn) state disabled + set data(history) "" + set data(histpos) -1 + } + + wm transient $w $data(-parent) + + if {[llength $data(-filetypes)]} { + set titles "" + foreach type $data(-filetypes) { + lassign $type title filter + lappend titles $title + } + $data(typeMenuBtn) configure -values $titles + $data(typeMenuLab) state !disabled + $data(typeMenuBtn) state !disabled + $data(typeMenuBtn) current 0 + ::ttk::dialog::file::SelectFilter $w + } else { + set data(filter) "*" + $data(typeMenuBtn) configure -takefocus 0 + $data(typeMenuBtn) state disabled + $data(typeMenuLab) state disabled + } + + set dirlist "/" + if {[info exists env(HOME)] && ![string equal $env(HOME) /]} { + lappend dirlist $env(HOME) + } + if {[lsearch -exact $dirlist $data(selectPath)] < 0} { + lappend dirlist $data(selectPath) + } + foreach n $filelist { + set dir [file dirname $n] + if {[lsearch -exact $dirlist $dir] < 0} { + lappend dirlist $dir + } + } + $data(dirMenuBtn) configure -values $dirlist + $data(location) configure -values $filelist + + ::ttk::dialog::file::ChangeDir $w $data(selectPath) + + ::tk::PlaceWindow $w widget $data(-parent) + wm title $w $data(-title) + + ::tk::SetFocusGrab $w $data(location) + + tkwait variable ::ttk::dialog::file::selectFilePath + + ::tk::RestoreFocusGrab $w $data(location) withdraw + + return $selectFilePath +} + +proc ::ttk::dialog::file::Config {dataName type argList} { + upvar ::ttk::dialog::file::$dataName data + + set data(type) $type + + # 1: the configuration specs + # + set specs { + {-defaultextension "" "" ""} + {-filetypes "" "" ""} + {-initialdir "" "" ""} + {-initialfile "" "" ""} + {-parent "" "" "."} + {-title "" "" ""} + {-sepfolders "" "" 1} + {-foldersfirst "" "" 1} + {-sort "" "" "name"} + {-reverse "" "" 0} + {-details "" "" 0} + {-hidden "" "" 0} + } + + # 2: default values depending on the type of the dialog + # + if {![info exists data(selectPath)]} { + # first time the dialog has been popped up + set data(selectPath) [pwd] + set data(selectFile) "" + } + + # 3: parse the arguments + # + tclParseConfigSpec ::ttk::dialog::file::$dataName $specs "" $argList + + if {$data(-title) == ""} { + if {[string equal $type "save"]} { + set data(-title) "Save As" + } else { + set data(-title) "Open" + } + } + + # 4: set the default directory and selection according to the -initial + # settings + # + + # Ensure that initialdir is an absolute path name. + if {[string length $data(-initialdir)]} { + set dir [file normalize [file join [pwd] $data(-initialdir)]] + if {[string equal [file type $dir] "link"]} { + set dir [file normalize [file join $dir [file link $dir]]] + } + if {[file isdirectory $dir]} { + set data(selectPath) $dir + } else { + set data(selectPath) [pwd] + } + } + set data(selectFile) $data(-initialfile) + + # 5. Parse the -filetypes option + # + set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)] + + if {![winfo exists $data(-parent)]} { + error "bad window path name \"$data(-parent)\"" + } + + variable sepfolders $data(-sepfolders) + variable foldersfirst $data(-foldersfirst) + variable sort $data(-sort) + variable reverse $data(-reverse) + variable details $data(-details) + variable hidden $data(-hidden) +} + +### ttk::chooseDirectory + +proc ::ttk::dialog::file::treeCreate {w} { + destroy $w + toplevel $w -class TkChooseDir + wm iconname $w Dialog + + set dataName [winfo name $w] + upvar ::ttk::dialog::file::$dataName data + + if {[winfo viewable [winfo toplevel $data(-parent)]] } { + wm transient $w $data(-parent) + } + + set f1 [ttk::frame $w.f1] + set data(dirMenuBtn) [ttk::combobox $f1.dir \ + -textvariable ::ttk::dialog::file::${dataName}(selectPath)] + pack $f1.dir -fill x -expand 1 -padx 8 -pady 5 + + set f2 [ttk::frame $w.f2] + ttk::frame $f2.f + ttk::label $f2.f.bg -relief sunken + set font TkDefaultFont + destroy $f2.f.dummy + ttk::label $f2.f.title -text Folder -anchor w -style Toolbutton + set data(text) [text $f2.f.text -width 48 -height 16 -font $font \ + -tabs 20 -wrap none -highlightthickness 0 -bd 0 -cursor "" \ + -spacing1 1 -spacing3 1 -exportselection 0 \ + -yscrollcommand [list $f2.f.scroll set]] + $data(text) mark set subdir end + $data(text) mark gravity subdir left + ttk::scrollbar $f2.f.scroll -command [list $data(text) yview] + grid $f2.f.title $f2.f.scroll -sticky ns + grid $f2.f.text ^ -sticky news -padx {2 0} -pady {0 2} + grid $f2.f.title -padx {2 0} -pady {2 1} -sticky ew + grid $f2.f.bg -column 0 -row 0 -columnspan 2 -rowspan 2 -sticky news + grid columnconfigure $f2.f 0 -weight 1 + grid rowconfigure $f2.f 1 -weight 1 + pack $f2.f -fill both -expand 1 -padx 8 -pady 4 + + set f3 [ttk::frame $w.f3] + ttk::button $f3.ok -text OK -default active \ + -command [list ::ttk::dialog::file::TreeDone $w] + ttk::button $f3.cancel -text Cancel \ + -command [list ::ttk::dialog::file::Cancel $w] + grid x $f3.ok $f3.cancel -sticky ew -padx {4 8} -pady 8 + grid columnconfigure $f3 {1 2} -uniform buttons -minsize 80 + grid columnconfigure $f3 0 -weight 1 + + pack $f1 -side top -fill x + pack $f3 -side bottom -fill x + pack $f2 -side top -fill both -expand 1 + + $data(text) image create end -padx 1 \ + -image ::ttk::dialog::image::folder + $data(text) insert end " /" name + $data(text) configure -state disabled + + # Get rid of the default Text bindings + bindtags $data(text) [list $data(text) DirDialog $w all] + + bind $data(dirMenuBtn) \ + [list ::ttk::dialog::file::TreeReturn $w] + + wm protocol $w WM_DELETE_WINDOW [list $f3.cancel invoke] +} + +proc ::ttk::dialog::file::treeUpdate {w dir} { + upvar ::ttk::dialog::file::[winfo name $w](text) txt + + set dir [file normalize [file join [pwd] $dir]] + set list [lassign [file split $dir] parent] + lappend list . + $txt configure -state normal + $txt delete 1.end end + $txt mark set subdir end + + foreach d $list { + treeOpen $w $parent subdir $d + set parent [file join $parent $d] + } + $txt yview subdir-5l + TreeSelect $w subdir +} + +proc ::ttk::dialog::file::treeOpen {w path {index insert} {subdir .}} { + upvar ::ttk::dialog::file::[winfo name $w](text) txt + + set level [llength [file split $path]] + set tabs [string repeat "\t" [expr {$level - 1}]] + set img [lindex [$txt dump -image \ + "$index linestart" "$index lineend"] 1] + if {[string length $img] && \ + [string equal [$txt image cget $img -name] diropen]} { + $txt image configure $img -image ::ttk::dialog::image::dirclose + } else { + set img "" + } + + # Do we already have this data available, but perhaps elided? + if {[llength [$txt tag ranges $path]]} { + # Also show all subdirectories that were expanded before + set list [lsearch -all -inline [$txt tag names] $path/*] + foreach n [lappend list $path] { + $txt tag configure $n -elide 0 + } + return + } + + # This may take a little longer so give some indication to the user + $w configure -cursor watch + update + + $txt configure -state normal + $txt mark set insert $index + set list [glob -nocomplain -tails -dir $path -type d * .*] + foreach d [lsort -dictionary $list] { + # Skip . and .. + if {[string equal $d .] || [string equal $d ..]} continue + # Specify no tags so the tags at the current position are used + $txt insert insert "\n" + # Insert the line with the appropriate tags + $txt insert insert $tabs [list $path] + file stat [file join $path $d] stat + if {$stat(nlink) != 2} { + set img [$txt image create insert -name diropen \ + -image ::ttk::dialog::image::diropen -padx 3] + $txt tag add $path $img + } + $txt insert insert "\t" [list $path] + set img [$txt image create insert -padx 1 \ + -image ::ttk::dialog::image::folder] + $txt tag add $path $img + $txt insert insert " $d" [list name $path] + # Remove tags from the lineend + foreach n [$txt tag names insert] { + $txt tag remove $n insert + } + # Add the correct tag to the lineend + $txt tag add $path insert + # Put a mark if this is the specified subdirectory + if {[string equal $d $subdir]} { + $txt mark set subdir insert + } + } + # Directory is considered empty if it only contains . and .. + if {[llength $list] <= 2 && [string length $img]} { + $txt delete $img + } + $txt configure -state disabled + $w configure -cursor "" +} + +proc ::ttk::dialog::file::treeClose {w path} { + upvar ::ttk::dialog::file::[winfo name $w](text) txt + + set img root + set pathindex [lindex [$txt tag ranges $path] 0] + lassign [$txt dump -image "$pathindex-1l" $pathindex] - img pos + if {[string match diropen* $img]} { + $txt image configure $img -image ::ttk::dialog::image::diropen + } + + set list [lsearch -all -inline [$txt tag names] $path/*] + lappend list $path + $txt configure -state normal + foreach n $list { + # Eliding sounds promising, but doesn't work correctly + # $txt tag configure $n -elide 1 + eval [list $txt delete] [$txt tag ranges $n] + $txt tag delete $n + } + $txt configure -state disabled +} + +proc ::ttk::dialog::file::TreeDone {w} { + upvar ::ttk::dialog::file::[winfo name $w] data + + if {[file exists $data(selectPath)]} { + if {![file isdirectory $data(selectPath)]} { + return + } + } elseif {[string is true $data(-mustexists)]} { + return + } + variable selectFilePath $data(selectPath) +} + +proc ::ttk::dialog::file::cdTree {w dir {subdir .}} { + upvar ::ttk::dialog::file::[winfo name $w](text) txt + + set parent [file dirname $dir] + + set ranges [$txt tag ranges $parent] + if {[llength $ranges]} { + set pat [format {^\t* %s$} [file tail $dir]] + foreach {index1 index2} $ranges { + set idx [$txt search -regexp $pat $index1 $index2] + if {[string length $idx]} { + $txt mark set subdir "$idx lineend" + break + } + } + } else { + cdTree $w $parent [file tail $dir] + } + ::ttk::dialog::file::treeOpen $w $dir subdir $subdir +} + +proc ::ttk::dialog::file::TreeSelect {w index} { + upvar ::ttk::dialog::file::[winfo name [winfo toplevel $w]] data + + set idx [$data(text) index "$index lineend"] + set range [$data(text) tag prevrange name $idx "$idx linestart"] + if {[llength $range]} { + lassign $range index1 index2 + $data(text) tag remove sel 1.0 end + $data(text) tag add sel $index1-1c $index2+1c + set path [lsearch -inline [$data(text) tag names $index1] /*] + set dir [$data(text) get $index1+1c $index2] + set data(selectPath) [file join $path $dir] + } +} + +proc ::ttk::dialog::file::TreeRelease1 {w} { + set w [winfo toplevel $w] + upvar ::ttk::dialog::file::[winfo name $w](text) txt + + if {[string length [$w cget -cursor]]} { + $w configure -cursor "" + return + } + + set dir [string range [$txt get sel.first sel.last] 1 end-1] + set path [lsearch -inline [$txt tag names sel.first] /*] + if {![catch {$txt image cget sel.first-2c -image} name]} { + set index [$txt index sel.last-1c] + $txt mark set selmark sel.first + switch -glob $name { + *::diropen { + treeOpen $w [file join $path $dir] $index + } + *::dirclose { + treeClose $w [file join $path $dir] + } + } + $txt tag remove sel 1.0 end + $txt tag add sel selmark "selmark lineend+1c" + } +} + +proc ::ttk::dialog::file::TreeMotion1 {w} { + [winfo toplevel $w] configure -cursor "X_cursor #C00 #000" +} + +proc ::ttk::dialog::file::TreeReturn {w} { + upvar ::ttk::dialog::file::[winfo name $w] data + + if {[file isdirectory $data(selectPath)]} { + ::ttk::dialog::file::cdTree $w $data(selectPath) + $data(text) yview subdir-5l + TreeSelect $w subdir + } + + return -code break +} + +proc ttk::chooseDirectory {args} { + set dataName __ttk_dirdialog + upvar ::ttk::dialog::file::$dataName data + + set specs { + {-initialdir "" "" .} + {-mustexists "" "" 0} + {-parent "" "" .} + {-title "" "" ""} + } + tclParseConfigSpec ::ttk::dialog::file::$dataName $specs "" $args + + if {$data(-title) == ""} { + set data(-title) "[::tk::mc "Choose Directory"]" + } + + if {![winfo exists $data(-parent)]} { + error "bad window path name \"$data(-parent)\"" + } + + if {[string equal $data(-parent) .]} { + set w .$dataName + } else { + set w $data(-parent).$dataName + } + + if {![winfo exists $w]} { + ::ttk::dialog::file::treeCreate $w + } + + ::tk::PlaceWindow $w widget $data(-parent) + wm title $w $data(-title) + ::tk::SetFocusGrab $w $data(text) + + ::ttk::dialog::file::treeUpdate $w $data(-initialdir) + + tkwait variable ::ttk::dialog::file::selectFilePath + + ::tk::RestoreFocusGrab $w $data(text) withdraw + + return $::ttk::dialog::file::selectFilePath +} + +# Alternative procedure names +interp alias {} ttk_getOpenFile {} ::ttk::dialog::file::tkFDialog open +interp alias {} ttk_getSaveFile {} ::ttk::dialog::file::tkFDialog save +interp alias {} ttk_getAppendFile {} ::ttk::dialog::file::tkFDialog append + + +# Need to have a lassign procedure +if {![llength [info procs lassign]]} { + proc lassign {list args} { + uplevel 1 [list foreach $args $list break] + lrange $list [llength $args] end + } +} + +option add *TkFDialog*selectBackground #0a5f89 +option add *TkFDialog*selectForeground #ffffff +option add *TkFDialog*Toolbar*takeFocus 0 +option add *TkFDialog*Text.background white +# option add *TkFDialog*Menu.activeBackground #0a5f89 +# option add *TkFDialog*Menu.activeForeground #ffffff +# option add *TkFDialog*Menu.activeBorderWidth 1 +# option add *TkFDialog*Menu.borderWidth 1 +# option add *TkFDialog*Menu.relief solid +# option add *TkFDialog*Menu.Image ::ttk::dialog::image::blank16 +# option add *TkFDialog*Menu*selectImage ::ttk::dialog::image::tick16 + +# Bindings +bind FileDialogDir {::ttk::dialog::file::DirButton1 %W %x %y} +bind FileDialogDir {::ttk::dialog::file::DirRelease1 %W %x %y} +bind FileDialogDir {::ttk::dialog::file::DirDouble1 %W %x %y} +bind FileDialogDir {::ttk::dialog::file::DirMotion1 %W %x %y} +bind FileDialogDir <4> {%W yview scroll -5 units} +bind FileDialogDir <5> {%W yview scroll 5 units} +bind FileDialogFile {::ttk::dialog::file::FileButton1 %W %x %y} +bind FileDialogFile {::ttk::dialog::file::FileRelease1 %W %x %y} +bind FileDialogFile {::ttk::dialog::file::FileMotion1 %W %x %y} +bind FileDialogFile {::ttk::dialog::file::Done [winfo toplevel %W]} +bind FileDialogFile <4> \ + {::ttk::dialog::file::xview [winfo toplevel %W] scroll -1 units} +bind FileDialogFile <5> \ + {::ttk::dialog::file::xview [winfo toplevel %W] scroll 1 units} +bind FileDialogList {::ttk::dialog::file::FileButton1 %W %x %y} +bind FileDialogList {::ttk::dialog::file::FileRelease1 %W %x %y} +bind FileDialogList {::ttk::dialog::file::FileMotion1 %W %x %y} +bind FileDialogList {::ttk::dialog::file::Done [winfo toplevel %W]} +bind FileDialogList <4> {%W yview scroll -5 units} +bind FileDialogList <5> {%W yview scroll 5 units} + +bind DirDialog <4> {%W yview scroll -5 units} +bind DirDialog <5> {%W yview scroll 5 units} +bind DirDialog {::ttk::dialog::file::TreeSelect %W @%x,%y} +bind DirDialog {::ttk::dialog::file::TreeRelease1 %W} +bind DirDialog {::ttk::dialog::file::TreeMotion1 %W} diff --git a/data/themes/blue/blue.tcl b/data/themes/blue/blue8.4.tcl similarity index 100% rename from data/themes/blue/blue.tcl rename to data/themes/blue/blue8.4.tcl diff --git a/data/themes/blue/blue8.5.tcl b/data/themes/blue/blue8.5.tcl new file mode 100644 index 00000000..22cf14a7 --- /dev/null +++ b/data/themes/blue/blue8.5.tcl @@ -0,0 +1,170 @@ +# blue.tcl - Copyright (C) 2004 Pat Thoyts +# +# blue.tcl,v 1.30 2005/12/13 23:04:25 patthoyts Exp +# +# + +namespace eval ttk::theme::blue { + + package provide ttk::theme::blue 0.7 + + proc LoadImages {imgdir {patterns {*.gif}}} { + foreach pattern $patterns { + foreach file [glob -directory $imgdir $pattern] { + set img [file tail [file rootname $file]] + if {![info exists images($img)]} { + set images($img) [image create photo -file $file] + } + } + } + return [array get images] + } + + variable I + array set I [LoadImages \ + [file join [file dirname [info script]] blue] *.gif] + + variable colors + array set colors { + -frame "#6699cc" + -lighter "#bcd2e8" + -window "#e6f3ff" + -selectbg "#ffff33" + -selectfg "#000000" + -disabledfg "#666666" + } + + ttk::style theme create blue -settings { + + ttk::style configure . \ + -borderwidth 1 \ + -background $colors(-frame) \ + -fieldbackground $colors(-window) \ + -troughcolor $colors(-lighter) \ + -selectbackground $colors(-selectbg) \ + -selectforeground $colors(-selectfg) \ + ; + ttk::style map . -foreground [list disabled $colors(-disabledfg)] + + ## Buttons. + # + ttk::style configure TButton -padding "10 0" + ttk::style layout TButton { + Button.button -children { + Button.focus -children { + Button.padding -children { + Button.label + } + } + } + } + + ttk::style element create button image \ + [list $I(button-n) pressed $I(button-p) active $I(button-h)] \ + -border 4 -sticky ew + + ttk::style element create Checkbutton.indicator image \ + [list $I(check-nu) \ + {!disabled active selected} $I(check-hc) \ + {!disabled active} $I(check-hu) \ + {!disabled selected} $I(check-nc) \ + ] \ + -width 24 -sticky w + + ttk::style element create Radiobutton.indicator image \ + [list $I(radio-nu) \ + {!disabled active selected} $I(radio-hc) \ + {!disabled active} $I(radio-hu) \ + selected $I(radio-nc) \ + ] \ + -width 24 -sticky w + + ttk::style configure TMenubutton -relief raised -padding {10 2} + ttk::style configure TRadiobutton -padding 1 + ttk::style configure TCheckbutton -padding 1 + + ## Toolbar buttons. + # + ttk::style configure Toolbutton \ + -width 0 -relief flat -borderwidth 2 -padding 4 \ + -background $colors(-frame) -foreground #000000 ; + ttk::style map Toolbutton -background [list active $colors(-selectbg)] + ttk::style map Toolbutton -foreground [list active $colors(-selectfg)] + ttk::style map Toolbutton -relief { + disabled flat + selected sunken + pressed sunken + active raised + } + + ## Entry widgets. + # + ttk::style configure TEntry \ + -selectborderwidth 1 -padding 2 -insertwidth 2 -font TkTextFont + ttk::style configure TCombobox \ + -selectborderwidth 1 -padding 2 -insertwidth 2 -font TkTextFont + + ## Notebooks. + # + ttk::style configure TNotebook.Tab -padding {4 2 4 2} + ttk::style map TNotebook.Tab \ + -background \ + [list selected $colors(-frame) active $colors(-lighter)] \ + -padding [list selected {4 4 4 2}] + + ## Labelframes. + # + ttk::style configure TLabelframe -borderwidth 2 -relief groove + + ## Scrollbars. + # + ttk::style layout Vertical.TScrollbar { + Scrollbar.trough -children { + Scrollbar.uparrow -side top + Scrollbar.downarrow -side bottom + Scrollbar.uparrow -side bottom + Vertical.Scrollbar.thumb -side top -expand true -sticky ns + } + } + + ttk::style layout Horizontal.TScrollbar { + Scrollbar.trough -children { + Scrollbar.leftarrow -side left + Scrollbar.rightarrow -side right + Scrollbar.leftarrow -side right + Horizontal.Scrollbar.thumb -side left -expand true -sticky we + } + } + + ttk::style element create Horizontal.Scrollbar.thumb image \ + [list $I(sb-thumb) {pressed !disabled} $I(sb-thumb-p)] -border 3 + + ttk::style element create Vertical.Scrollbar.thumb image \ + [list $I(sb-vthumb) {pressed !disabled} $I(sb-vthumb-p)] -border 3 + + foreach dir {up down left right} { + ttk::style element create ${dir}arrow image \ + [list $I(arrow${dir}) \ + disabled $I(arrow${dir}) \ + pressed $I(arrow${dir}-p) \ + active $I(arrow${dir}-h) \ + ] \ + -border 1 -sticky {} + } + + ## Scales. + # + ttk::style element create Scale.slider \ + image [list $I(slider) {pressed !disabled} $I(slider-p)] + + ttk::style element create Vertical.Scale.slider \ + image [list $I(vslider) {pressed !disabled} $I(vslider-p)] + + ttk::style element create Horizontal.Progress.bar \ + image [list $I(sb-thumb)] -border 2 + ttk::style element create Vertical.Progress.bar \ + image [list $I(sb-vthumb)] -border 2 + + } +} + diff --git a/data/themes/blue/pkgIndex.tcl b/data/themes/blue/pkgIndex.tcl index 4facac70..0ab51063 100644 --- a/data/themes/blue/pkgIndex.tcl +++ b/data/themes/blue/pkgIndex.tcl @@ -1,6 +1,11 @@ # Package index for tile demo pixmap themes. if {[file isdirectory [file join $dir blue]]} { - package ifneeded tile::theme::blue 0.7 \ - [list source [file join $dir blue.tcl]] + if {[package vsatisfies [package require tile] 0.8.0]} { + package ifneeded ttk::theme::blue 0.7 \ + [list source [file join $dir blue8.5.tcl]] + } else { + package ifneeded tile::theme::blue 0.7 \ + [list source [file join $dir blue8.4.tcl]] + } } diff --git a/data/themes/clearlooks/clearlooks.tcl b/data/themes/clearlooks/clearlooks8.4.tcl similarity index 100% rename from data/themes/clearlooks/clearlooks.tcl rename to data/themes/clearlooks/clearlooks8.4.tcl diff --git a/data/themes/clearlooks/clearlooks8.5.tcl b/data/themes/clearlooks/clearlooks8.5.tcl new file mode 100644 index 00000000..91db8dc6 --- /dev/null +++ b/data/themes/clearlooks/clearlooks8.5.tcl @@ -0,0 +1,335 @@ +# clearlooks.tcl + +namespace eval ttk::theme::clearlooks { + + package provide ttk::theme::clearlooks 0.1 + + proc LoadImages {imgdir {patterns {*.gif}}} { + foreach pattern $patterns { + foreach file [glob -directory $imgdir $pattern] { + set img [file tail [file rootname $file]] + if {![info exists images($img)]} { + set images($img) [image create photo -file $file] + } + } + } + return [array get images] + } + + variable I + array set I [LoadImages \ + [file join [file dirname [info script]] clearlooks] *.gif] + + variable colors + + array set colors { + -frame "#efebe7" + -lighter "#f5f3f0" + -dark "#cfcdc8" + -darker "#9e9a9e" + -darkest "#d4cfca" + -selectbg "#7c99ad" + -selectfg "#ffffff" + -disabledfg "#b5b3ac" + -entryfocus "#6f9dc6" + -tabbg "#c9c1bc" + -tabborder "#b5aca7" + -troughcolor "#d7cbbe" + -troughborder "#ae9e8e" + -checklight "#f5f3f0" + } + + + ttk::style theme create clearlooks -parent clam -settings { + + ttk::style configure . \ + -borderwidth 1 \ + -background $colors(-frame) \ + -foreground black \ + -bordercolor $colors(-darkest) \ + -darkcolor $colors(-dark) \ + -lightcolor $colors(-lighter) \ + -troughcolor $colors(-troughcolor) \ + -selectforeground $colors(-selectfg) \ + -selectbackground $colors(-selectbg) \ + -font TkDefaultFont \ + ; + + ttk::style map . \ + -background [list disabled $colors(-frame) \ + active $colors(-lighter)] \ + -foreground [list disabled $colors(-disabledfg)] \ + -selectbackground [list !focus $colors(-darker)] \ + -selectforeground [list !focus white] \ + ; + + +# ttk::style configure Frame.border -relief groove + + ## Treeview. + # + ttk::style element create Treeheading.cell image \ + [list $I(tree-n) \ + selected $I(tree-p) \ + disabled $I(tree-d) \ + pressed $I(tree-p) \ + active $I(tree-h) \ + ] \ + -border 4 -sticky ew + + #ttk::style configure Treeview -fieldbackground white + ttk::style configure Row -background "#efefef" + ttk::style map Row -background [list \ + {focus selected} "#71869e" \ + selected "#969286" \ + alternate white] + ttk::style map Item -foreground [list selected white] + ttk::style map Cell -foreground [list selected white] + + + ## Buttons. + # + ttk::style configure TButton -padding {10 0} + ttk::style layout TButton { + Button.button -children { + Button.focus -children { + Button.padding -children { + Button.label + } + } + } + } + + ttk::style element create button image \ + [list $I(button-n) \ + pressed $I(button-p) \ + {selected active} $I(button-pa) \ + selected $I(button-p) \ + active $I(button-a) \ + disabled $I(button-d) \ + ] \ + -border 4 -sticky ew + + + ## Checkbuttons. + # + ttk::style element create Checkbutton.indicator image \ + [list $I(check-nu) \ + {disabled selected} $I(check-dc) \ + disabled $I(check-du) \ + {pressed selected} $I(check-pc) \ + pressed $I(check-pu) \ + {active selected} $I(check-ac) \ + active $I(check-au) \ + selected $I(check-nc) ] \ + -width 24 -sticky w + + ttk::style map TCheckbutton -background [list active $colors(-checklight)] + ttk::style configure TCheckbutton -padding 1 + + + ## Radiobuttons. + # + ttk::style element create Radiobutton.indicator image \ + [list $I(radio-nu) \ + {disabled selected} $I(radio-dc) \ + disabled $I(radio-du) \ + {pressed selected} $I(radio-pc) \ + pressed $I(radio-pu) \ + {active selected} $I(radio-ac) \ + active $I(radio-au) \ + selected $I(radio-nc) ] \ + -width 24 -sticky w + + ttk::style map TRadiobutton -background [list active $colors(-checklight)] + ttk::style configure TRadiobutton -padding 1 + + + ## Menubuttons. + # + #ttk::style configure TMenubutton -relief raised -padding {10 2} +# ttk::style element create Menubutton.border image $I(toolbutton-n) \ +# -map [list \ +# pressed $I(toolbutton-p) \ +# selected $I(toolbutton-p) \ +# active $I(toolbutton-a) \ +# disabled $I(toolbutton-n)] \ +# -border {4 7 4 7} -sticky nsew + + ttk::style element create Menubutton.border image \ + [list $I(button-n) \ + selected $I(button-p) \ + disabled $I(button-d) \ + active $I(button-a) \ + ] \ + -border 4 -sticky ew + + + ## Toolbar buttons. + # + ttk::style configure Toolbutton -padding -5 -relief flat + ttk::style configure Toolbutton.label -padding 0 -relief flat + + ttk::style element create Toolbutton.border image \ + [list $I(blank) \ + pressed $I(toolbutton-p) \ + {selected active} $I(toolbutton-pa) \ + selected $I(toolbutton-p) \ + active $I(toolbutton-a) \ + disabled $I(blank)] \ + -border 11 -sticky nsew + + + ## Entry widgets. + # + ttk::style configure TEntry -padding 1 -insertwidth 1 \ + -fieldbackground white + + ttk::style map TEntry \ + -fieldbackground [list readonly $colors(-frame)] \ + -bordercolor [list focus $colors(-selectbg)] \ + -lightcolor [list focus $colors(-entryfocus)] \ + -darkcolor [list focus $colors(-entryfocus)] \ + ; + + + ## Combobox. + # + ttk::style configure TCombobox -selectbackground + + ttk::style element create Combobox.downarrow image \ + [list $I(comboarrow-n) \ + disabled $I(comboarrow-d) \ + pressed $I(comboarrow-p) \ + active $I(comboarrow-a) \ + ] \ + -border 1 -sticky {} + + ttk::style element create Combobox.field image \ + [list $I(combo-n) \ + {readonly disabled} $I(combo-rd) \ + {readonly pressed} $I(combo-rp) \ + {readonly focus} $I(combo-rf) \ + readonly $I(combo-rn) \ + ] \ + -border 4 -sticky ew + + + ## Notebooks. + # +# ttk::style element create tab image $I(tab-a) -border {2 2 2 0} \ +# -map [list selected $I(tab-n)] + + ttk::style configure TNotebook.Tab -padding {6 2 6 2} + ttk::style map TNotebook.Tab \ + -padding [list selected {6 4 6 2}] \ + -background [list selected $colors(-frame) {} $colors(-tabbg)] \ + -lightcolor [list selected $colors(-lighter) {} $colors(-dark)] \ + -bordercolor [list selected $colors(-darkest) {} $colors(-tabborder)] \ + ; + + ## Labelframes. + # + ttk::style configure TLabelframe -borderwidth 2 -relief groove + + + ## Scrollbars. + # + ttk::style layout Vertical.TScrollbar { + Scrollbar.trough -sticky ns -children { + Scrollbar.uparrow -side top + Scrollbar.downarrow -side bottom + Vertical.Scrollbar.thumb -side top -expand true -sticky ns + } + } + + ttk::style layout Horizontal.TScrollbar { + Scrollbar.trough -sticky we -children { + Scrollbar.leftarrow -side left + Scrollbar.rightarrow -side right + Horizontal.Scrollbar.thumb -side left -expand true -sticky we + } + } + + ttk::style element create Horizontal.Scrollbar.thumb image \ + [list $I(sbthumb-hn) \ + disabled $I(sbthumb-hd) \ + pressed $I(sbthumb-ha) \ + active $I(sbthumb-ha)] \ + -border 3 + + ttk::style element create Vertical.Scrollbar.thumb image \ + [list $I(sbthumb-vn) \ + disabled $I(sbthumb-vd) \ + pressed $I(sbthumb-va) \ + active $I(sbthumb-va)] \ + -border 3 + + foreach dir {up down left right} { + ttk::style element create ${dir}arrow image \ + [list $I(arrow${dir}-n) \ + disabled $I(arrow${dir}-d) \ + pressed $I(arrow${dir}-p) \ + active $I(arrow${dir}-a)] \ + -border 1 -sticky {} + } + + ttk::style configure TScrollbar -bordercolor $colors(-troughborder) + + + ## Scales. + # + ttk::style element create Scale.slider image \ + [list $I(scale-hn) \ + disabled $I(scale-hd) \ + active $I(scale-ha) \ + ] + + ttk::style element create Scale.trough image $I(scaletrough-h) \ + -border 2 -sticky ew -padding 0 + + ttk::style element create Vertical.Scale.slider image \ + [list $I(scale-vn) \ + disabled $I(scale-vd) \ + active $I(scale-va) \ + ] + ttk::style element create Vertical.Scale.trough image $I(scaletrough-v) \ + -border 2 -sticky ns -padding 0 + + ttk::style configure TScale -bordercolor $colors(-troughborder) + + + ## Progressbar. + # + ttk::style element create Horizontal.Progressbar.pbar image $I(progress-h) \ + -border {2 2 1 1} + ttk::style element create Vertical.Progressbar.pbar image $I(progress-v) \ + -border {2 2 1 1} + + ttk::style configure TProgressbar -bordercolor $colors(-troughborder) + + + ## Statusbar parts. + # + ttk::style element create sizegrip image $I(sizegrip) + + + ## Paned window parts. + # +# ttk::style element create hsash image $I(hseparator-n) -border {2 0} \ +# -map [list {active !disabled} $I(hseparator-a)] +# ttk::style element create vsash image $I(vseparator-n) -border {0 2} \ +# -map [list {active !disabled} $I(vseparator-a)] + + ttk::style configure Sash -sashthickness 6 -gripcount 16 + + + ## Separator. + # + #ttk::style element create separator image $I(sep-h) + #ttk::style element create hseparator image $I(sep-h) + #ttk::style element create vseparator image $I(sep-v) + + } +} + diff --git a/data/themes/clearlooks/pkgIndex.tcl b/data/themes/clearlooks/pkgIndex.tcl index 288fdae3..4d3e987e 100644 --- a/data/themes/clearlooks/pkgIndex.tcl +++ b/data/themes/clearlooks/pkgIndex.tcl @@ -1,7 +1,12 @@ # Package index for tile demo pixmap themes. if {[file isdirectory [file join $dir clearlooks]]} { - package ifneeded tile::theme::clearlooks 0.1 \ - [list source [file join $dir clearlooks.tcl]] + if {[package vsatisfies [package require tile] 0.8.0]} { + package ifneeded ttk::theme::clearlooks 0.1 \ + [list source [file join $dir clearlooks8.5.tcl]] + } else { + package ifneeded tile::theme::clearlooks 0.1 \ + [list source [file join $dir clearlooks8.4.tcl]] + } } diff --git a/pysollib/app.py b/pysollib/app.py index 77db88ee..a87328f2 100644 --- a/pysollib/app.py +++ b/pysollib/app.py @@ -115,6 +115,7 @@ class Options: ('toolbar_compound', 'str'), ('toolbar_size', 'int'), ('statusbar', 'bool'), + ('statusbar_game_number', 'bool'), ('num_cards', 'bool'), ('helpbar', 'bool'), ('num_recent_games', 'int'), @@ -194,6 +195,7 @@ class Options: for w in TOOLBAR_BUTTONS: self.toolbar_vars[w] = True # show all buttons self.statusbar = True + self.statusbar_game_number = False # show game number in statusbar self.num_cards = False self.helpbar = False self.splashscreen = True @@ -399,9 +401,6 @@ class Options: config.write(file(filename, 'w')) #config.write(sys.stdout) - def printOptError(self, key): - pass - def _getOption(self, section, key, t): config = self._config try: @@ -869,11 +868,13 @@ class Application: try: self.loadStatistics() except: + traceback.print_exc() pass # try to load comments try: self.loadComments() except: + traceback.print_exc() pass # startup information if self.getGameClass(self.opt.last_gameid): @@ -886,6 +887,7 @@ class Application: try: game = tmpgame._loadGame(self.fn.holdgame, self) except: + traceback.print_exc() game = None if game: if game.id == self.opt.game_holded and game.gstats.holded: @@ -903,6 +905,7 @@ class Application: self.nextgame.loadedgame = tmpgame._loadGame(self.commandline.loadgame, self) self.nextgame.loadedgame.gstats.holded = 0 except: + traceback.print_exc() self.nextgame.loadedgame = None elif self.commandline.game is not None: gameid = self.gdb.getGameByName(self.commandline.game) @@ -926,6 +929,7 @@ class Application: # create the statusbar(s) self.statusbar = PysolStatusbar(self.top) self.statusbar.show(self.opt.statusbar) + self.statusbar.config('gamenumber', self.opt.statusbar_game_number) self.helpbar = HelpStatusbar(self.top) self.helpbar.show(self.opt.helpbar) # create the canvas @@ -956,7 +960,15 @@ class Application: assert self.cardset is not None id, random = self.nextgame.id, self.nextgame.random self.nextgame.id, self.nextgame.random = 0, None - self.runGame(id, random) + try: + self.runGame(id, random) + except: + # try Klondike if current game fails + if id == 2: + raise # internal error? + traceback.print_exc() + self.nextgame.id = 2 + continue if self.nextgame.holdgame: assert self.nextgame.id <= 0 try: diff --git a/pysollib/main.py b/pysollib/main.py index 87bdf881..9ed1d80a 100644 --- a/pysollib/main.py +++ b/pysollib/main.py @@ -47,7 +47,7 @@ from app import Application from pysolaudio import AbstractAudioClient, PysolSoundServerModuleClient from pysolaudio import Win32AudioClient, OSSAudioClient, PyGameAudioClient from settings import PACKAGE, SOUND_MOD -from winsystems import initRootWindow +from winsystems import init_root_window # Toolkit imports from pysoltk import loadImage @@ -250,7 +250,7 @@ def pysol_init(app, args): app.opt.sound_mode = 0 # init toolkit 2) - initRootWindow(top, app) + init_root_window(top, app) # check games if len(app.gdb.getGamesIdSortedByName()) == 0: diff --git a/pysollib/tile/Tile.py b/pysollib/tile/Tile.py index ce882dac..277893b3 100644 --- a/pysollib/tile/Tile.py +++ b/pysollib/tile/Tile.py @@ -2,24 +2,28 @@ import Tkinter +TileVersion = None +_tile_prefix = '' # XXX def initialize(root=None): + global TileVersion, _tile_prefix if root is None: root = Tkinter._default_root - root.tk.call("package", "require", "tile", "0.7.8") - # This forces an update of the available packages list. - # It's required for package names to find the themes in data/themes/ - root.tk.call('eval', '[package unknown]', 'Tcl', '[package provide Tcl]') + TileVersion = root.tk.call("package", "require", "tile", "0.7.8") + if TileVersion >= '0.8': + _tile_prefix = 'ttk::' # XXX def availableThemes(root=None): if root is None: root = Tkinter._default_root + if TileVersion >= '0.8': + return root.tk.call("ttk::themes") return root.tk.call("tile::availableThemes") def setTheme(root=None, theme=None): if root is None: root = Tkinter._default_root - return root.tk.call("tile::setTheme", theme) + return root.tk.call(_tile_prefix+"setTheme", theme) class Style(Tkinter.Misc): @@ -31,7 +35,7 @@ class Style(Tkinter.Misc): def default(self, style, **kw): """Sets the default value of the specified option(s) in style""" opts = self._options(kw) - return self.tk.call("style", "default", style, *opts) + return self.tk.call(_tile_prefix+"style", "default", style, *opts) def map_style(self, **kw): """Sets dynamic values of the specified option(s) in style. See @@ -56,7 +60,7 @@ class Style(Tkinter.Misc): def element_names(self): """Returns a list of all elements defined in the current theme.""" - return self.tk.call("style", "elements", "names") + return self.tk.call(_tile_prefix+"style", "elements", "names") def theme_create(self, name, parent=None, basedon=None): """Creates a new theme. It is an error if themeName already exists. @@ -76,17 +80,17 @@ class Style(Tkinter.Misc): def theme_names(self): """Returns a list of the available themes.""" - return self.tk.call("style", "theme", "names") + return self.tk.call(_tile_prefix+"style", "theme", "names") def theme_use(self, theme): """Sets the current theme to themeName, and refreshes all widgets.""" - return self.tk.call("style", "theme", "use", theme) + return self.tk.call(_tile_prefix+"style", "theme", "use", theme) def configure(self, style, cnf={}, **kw): """Sets the default value of the specified option(s) in style.""" opts = self._options(cnf, kw) - return self.tk.call("style", "configure", style, *opts) + return self.tk.call(_tile_prefix+"style", "configure", style, *opts) config = configure def lookup(self, style, option, state=None, default=None): @@ -102,7 +106,8 @@ class Style(Tkinter.Misc): opts = [state] if default: opts.append(default) - return self.tk.call("style", "lookup", style, "-"+option, *opts) + return self.tk.call(_tile_prefix+"style", "lookup", style, + "-"+option, *opts) diff --git a/pysollib/tile/colorsdialog.py b/pysollib/tile/colorsdialog.py index 0a4be322..614f1dd7 100644 --- a/pysollib/tile/colorsdialog.py +++ b/pysollib/tile/colorsdialog.py @@ -98,12 +98,16 @@ class ColorsDialog(MfxDialog): self.not_matching_color = self.not_matching_var.get() def selectColor(self, label): - c = askcolor(parent=self.top, initialcolor=label.cget('bg'), - title=_("Select color")) - if c and c[1]: - label.configure(bg=c[1]) - #label.configure(text=c[1]) # don't work - label.setvar(label.cget('textvariable'), c[1]) + try: + c = askcolor(parent=self.top, initialcolor=label.cget('bg'), + title=_("Select color")) + except: + pass + else: + if c and c[1]: + label.configure(bg=c[1]) + #label.configure(text=c[1]) # don't work + label.setvar(label.cget('textvariable'), c[1]) def initKw(self, kw): kw = KwStruct(kw, diff --git a/pysollib/tile/statusbar.py b/pysollib/tile/statusbar.py index 7afbe557..48f08d2b 100644 --- a/pysollib/tile/statusbar.py +++ b/pysollib/tile/statusbar.py @@ -66,6 +66,7 @@ class MfxStatusbar: self._row = row self._column = column self._columnspan = columnspan + self._label_column = 0 # self.padx = 1 self.label_relief = 'sunken' @@ -76,13 +77,19 @@ class MfxStatusbar: self.frame.pack(side='left', expand=True, fill='both', padx=0, pady=1) # util - def _createLabel(self, name, side='left', fill='none', - expand=False, width=0, tooltip=None): + def _createLabel(self, name, expand=False, width=0, tooltip=None): frame = Tile.Frame(self.frame, borderwidth=1, relief=self.label_relief) - frame.pack(side=side, fill=fill, padx=self.padx, expand=expand) + frame.grid(row=0, column=self._label_column, + sticky='nsew', padx=self.padx) + if expand: + self.frame.grid_columnconfigure(self._label_column, + weight=1) + self._label_column += 1 + setattr(self, name + '_frame', frame) + self._widgets.append(frame) label = Tile.Label(frame, width=width) label.pack(expand=True, fill='both') - setattr(self, name + "_label", label) + setattr(self, name + '_label', label) self._widgets.append(label) if tooltip: b = MfxTooltip(label) @@ -101,25 +108,32 @@ class MfxStatusbar: def updateText(self, **kw): for k, v in kw.items(): - label = getattr(self, k + "_label") + label = getattr(self, k + '_label') text = unicode(v) width = label['width'] if width and len(text) > width: label['width'] = len(text) - label["text"] = text + label['text'] = text + + def config(self, name, show): + frame = getattr(self, name + '_frame') + if show: + frame.grid() + else: + frame.grid_remove() def configLabel(self, name, **kw): if 'fg' in kw: kw['foreground'] = kw['fg'] del kw['fg'] - label = getattr(self, name + "_label") + label = getattr(self, name + '_label') label.config(**kw) def show(self, show=True, resize=False): if self._show == show: return False if resize: - self.top.wm_geometry("") # cancel user-specified geometry + self.top.wm_geometry('') # cancel user-specified geometry if not show: # hide self.top_frame.grid_forget() @@ -147,15 +161,14 @@ class PysolStatusbar(MfxStatusbar): MfxStatusbar.__init__(self, top, row=4, column=0, columnspan=3) # for n, t, w in ( - ("time", _("Playing time"), 10), - ("moves", _('Moves/Total moves'), 10), - ("gamenumber", _("Game number"), 26), - ("stats", _("Games played: won/lost"), 12), + ('time', _('Playing time'), 10), + ('moves', _('Moves/Total moves'), 10), + ('gamenumber', _('Game number'), 26), + ('stats', _('Games played: won/lost'), 12), ): self._createLabel(n, tooltip=t, width=w) # - l = self._createLabel("info", fill='both', expand=True) - ##l.config(text="", justify="left", anchor='w') + l = self._createLabel('info', expand=True) l.config(padding=(8, 0)) self._createSizegrip() @@ -163,15 +176,16 @@ class PysolStatusbar(MfxStatusbar): class HelpStatusbar(MfxStatusbar): def __init__(self, top): MfxStatusbar.__init__(self, top, row=3, column=0, columnspan=3) - l = self._createLabel("info", fill='both', expand=True) - l.config(justify="left", anchor='w', padding=(8, 0)) + l = self._createLabel('info', expand=True) + l.config(justify='left', anchor='w', padding=(8, 0)) class HtmlStatusbar(MfxStatusbar): def __init__(self, top, row, column, columnspan): - MfxStatusbar.__init__(self, top, row=row, column=column, columnspan=columnspan) - l = self._createLabel("url", fill='both', expand=True) - l.config(justify="left", anchor='w', padding=(8, 0)) + MfxStatusbar.__init__(self, top, row=row, column=column, + columnspan=columnspan) + l = self._createLabel('url', expand=True) + l.config(justify='left', anchor='w', padding=(8, 0)) self._createSizegrip() @@ -184,8 +198,8 @@ class TestStatusbar(PysolStatusbar): def __init__(self, top, args): PysolStatusbar.__init__(self, top) # test some settings - self.updateText(moves=999, gamenumber="#0123456789ABCDEF0123") - self.updateText(info="Some info text.") + self.updateText(moves=999, gamenumber='#0123456789ABCDEF0123') + self.updateText(info='Some info text.') def statusbar_main(args): tk = Tkinter.Tk() @@ -193,7 +207,7 @@ def statusbar_main(args): tk.mainloop() return 0 -if __name__ == "__main__": +if __name__ == '__main__': sys.exit(statusbar_main(sys.argv)) diff --git a/pysollib/tile/tkstats.py b/pysollib/tile/tkstats.py index 84c52c37..0d2cfa6c 100644 --- a/pysollib/tile/tkstats.py +++ b/pysollib/tile/tkstats.py @@ -433,13 +433,20 @@ class AllGamesFrame(Tile.Frame): # frame = Tile.Frame(self) frame.pack(fill='both', expand=True, padx=10, pady=10) - sb = Tile.Scrollbar(frame) - sb.pack(side='right', fill='y') + vsb = Tile.Scrollbar(frame) + vsb.grid(row=0, column=1, sticky='ns') self.tree = Tile.Treeview(frame, columns=self.COLUMNS, selectmode='browse') - self.tree.pack(side='left', fill='both', expand=True) - self.tree.config(yscrollcommand=sb.set) - sb.config(command=self.tree.yview) + self.tree.grid(row=0, column=0, sticky='nsew') + self.tree.config(yscrollcommand=vsb.set) + vsb.config(command=self.tree.yview) + frame.rowconfigure(0, weight=1) + frame.columnconfigure(0, weight=1) + if Tile.TileVersion >= '0.8': + hsb = Tile.Scrollbar(frame, orient='horizontal') + hsb.grid(row=1, column=0, sticky='ew') + self.tree.config(xscrollcommand=hsb.set) + hsb.config(command=self.tree.xview) bind(self.tree, '<>', self.treeviewSelected) # self.formatter = TreeFormatter(self.app, self.tree, self, diff --git a/pysollib/tile/tkutil.py b/pysollib/tile/tkutil.py index e54b163a..a3429d87 100644 --- a/pysollib/tile/tkutil.py +++ b/pysollib/tile/tkutil.py @@ -138,9 +138,9 @@ def makeToplevel(parent, title=None): def make_help_toplevel(app, title=None): # Create an independent Toplevel window. - from pysollib.winsystems import initRootWindow + from pysollib.winsystems import init_root_window window = Tkinter.Tk(className=PACKAGE) - initRootWindow(window, app) + init_root_window(window, app) return window diff --git a/pysollib/tk/colorsdialog.py b/pysollib/tk/colorsdialog.py index 30a9e8e0..f475c0a0 100644 --- a/pysollib/tk/colorsdialog.py +++ b/pysollib/tk/colorsdialog.py @@ -99,12 +99,16 @@ class ColorsDialog(MfxDialog): self.not_matching_color = self.not_matching_var.get() def selectColor(self, label): - c = askcolor(parent=self.top, initialcolor=label.cget('bg'), - title=_("Select color")) - if c and c[1]: - label.configure(bg=c[1]) - #label.configure(text=c[1]) # don't work - label.setvar(label.cget('textvariable'), c[1]) + try: + c = askcolor(parent=self.top, initialcolor=label.cget('bg'), + title=_("Select color")) + except: + pass + else: + if c and c[1]: + label.configure(bg=c[1]) + #label.configure(text=c[1]) # don't work + label.setvar(label.cget('textvariable'), c[1]) def initKw(self, kw): kw = KwStruct(kw, diff --git a/pysollib/tk/statusbar.py b/pysollib/tk/statusbar.py index 758c493e..93ce7a68 100644 --- a/pysollib/tk/statusbar.py +++ b/pysollib/tk/statusbar.py @@ -66,6 +66,7 @@ class MfxStatusbar: self._row = row self._column = column self._columnspan = columnspan + self._label_column = 0 # self.padx = 1 self.label_relief = 'sunken' @@ -82,22 +83,18 @@ class MfxStatusbar: self.padx = 0 # util - def _createLabel(self, name, side='left', fill='none', - expand=False, width=0, tooltip=None): - if 0: - frame = Tkinter.Frame(self.frame, bd=1, relief=self.label_relief, - highlightbackground='#9e9a9e', - highlightthickness=1) - frame.pack(side=side, fill=fill, padx=self.padx, expand=expand) - label = Tkinter.Label(frame, width=width, bd=0) - label.pack(expand=True, fill='both') - else: - label = Tkinter.Label(self.frame, width=width, - relief=self.label_relief, bd=1, - highlightbackground='black' - ) - label.pack(side=side, fill=fill, padx=self.padx, expand=expand) - setattr(self, name + "_label", label) + def _createLabel(self, name, expand=False, width=0, tooltip=None): + label = Tkinter.Label(self.frame, width=width, + relief=self.label_relief, bd=1, + highlightbackground='black' + ) + label.grid(row=0, column=self._label_column, + sticky='nsew', padx=self.padx) + if expand: + self.frame.grid_columnconfigure(self._label_column, + weight=1) + self._label_column += 1 + setattr(self, name + '_label', label) self._widgets.append(label) if tooltip: b = MfxTooltip(label) @@ -112,22 +109,29 @@ class MfxStatusbar: def updateText(self, **kw): for k, v in kw.items(): - label = getattr(self, k + "_label") + label = getattr(self, k + '_label') text = unicode(v) width = label['width'] if width and len(text) > width: label['width'] = len(text) - label["text"] = text + label['text'] = text + + def config(self, name, show): + label = getattr(self, name + '_label') + if show: + label.grid() + else: + label.grid_remove() def configLabel(self, name, **kw): - label = getattr(self, name + "_label") + label = getattr(self, name + '_label') label.config(**kw) def show(self, show=True, resize=False): if self._show == show: return False if resize: - self.top.wm_geometry("") # cancel user-specified geometry + self.top.wm_geometry('') # cancel user-specified geometry if not show: # hide self.frame.grid_forget() @@ -155,30 +159,30 @@ class PysolStatusbar(MfxStatusbar): MfxStatusbar.__init__(self, top, row=3, column=0, columnspan=3) # for n, t, w in ( - ("time", _("Playing time"), 10), - ("moves", _('Moves/Total moves'), 10), - ("gamenumber", _("Game number"), 26), - ("stats", _("Games played: won/lost"), 12), + ('time', _('Playing time'), 10), + ('moves', _('Moves/Total moves'), 10), + ('gamenumber', _('Game number'), 26), + ('stats', _('Games played: won/lost'), 12), ): self._createLabel(n, tooltip=t, width=w) # - l = self._createLabel("info", fill='both', expand=True) - ##l.config(text="", justify="left", anchor='w') + l = self._createLabel('info', expand=True) + ##l.config(text='', justify='left', anchor='w') l.config(padx=8) class HelpStatusbar(MfxStatusbar): def __init__(self, top): MfxStatusbar.__init__(self, top, row=4, column=0, columnspan=3) - l = self._createLabel("info", fill='both', expand=True) - l.config(justify="left", anchor='w', padx=8) + l = self._createLabel('info', expand=True) + l.config(justify='left', anchor='w', padx=8) class HtmlStatusbar(MfxStatusbar): def __init__(self, top, row, column, columnspan): MfxStatusbar.__init__(self, top, row=row, column=column, columnspan=columnspan) - l = self._createLabel("url", fill='both', expand=True) - l.config(justify="left", anchor='w', padx=8) + l = self._createLabel('url', expand=True) + l.config(justify='left', anchor='w', padx=8) # /*********************************************************************** @@ -190,8 +194,8 @@ class TestStatusbar(PysolStatusbar): def __init__(self, top, args): PysolStatusbar.__init__(self, top) # test some settings - self.updateText(moves=999, gamenumber="#0123456789ABCDEF0123") - self.updateText(info="Some info text.") + self.updateText(moves=999, gamenumber='#0123456789ABCDEF0123') + self.updateText(info='Some info text.') def statusbar_main(args): tk = Tkinter.Tk() @@ -199,7 +203,7 @@ def statusbar_main(args): tk.mainloop() return 0 -if __name__ == "__main__": +if __name__ == '__main__': sys.exit(statusbar_main(sys.argv)) diff --git a/pysollib/tk/tkutil.py b/pysollib/tk/tkutil.py index da188b48..d6dad3a7 100644 --- a/pysollib/tk/tkutil.py +++ b/pysollib/tk/tkutil.py @@ -139,9 +139,9 @@ def makeToplevel(parent, title=None): def make_help_toplevel(app, title=None): # Create an independent Toplevel window. - from pysollib.winsystems import initRootWindow + from pysollib.winsystems import init_root_window window = Tkinter.Tk(className=PACKAGE) - initRootWindow(window, app) + init_root_window(window, app) return window diff --git a/pysollib/tk/tkwidget.py b/pysollib/tk/tkwidget.py index 524dcfbd..63e5b15f 100644 --- a/pysollib/tk/tkwidget.py +++ b/pysollib/tk/tkwidget.py @@ -196,7 +196,8 @@ class MfxDialog: # ex. _ToplevelDialog b.pack(side=kw.image_side, padx=kw.image_padx, pady=kw.image_pady) def createButtons(self, frame, kw): - button = column = -1 + button = -1 + column = 0 padx, pady = kw.get("buttonpadx", 10), kw.get("buttonpady", 10) focus = None max_len = 0 @@ -249,13 +250,13 @@ class MfxDialog: # ex. _ToplevelDialog ## img = self.button_img.get(s) ## b.config(compound='left', image=img) column += 1 - b.grid(column=column, row=0, sticky="nse", padx=padx, pady=pady) + b.grid(column=column, row=0, sticky="ns", padx=padx, pady=pady) if focus is not None: l = (lambda event=None, self=self, button=kw.default: self.mDone(button)) bind(self.top, "", l) bind(self.top, "", l) - # left justify - ##frame.columnconfigure(0, weight=1) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(99, weight=1) return focus diff --git a/pysollib/tk/wizarddialog.py b/pysollib/tk/wizarddialog.py index a75a1d46..25823f1f 100644 --- a/pysollib/tk/wizarddialog.py +++ b/pysollib/tk/wizarddialog.py @@ -127,7 +127,7 @@ class WizardDialog(MfxDialog): v = p[w.var_name] else: v = w.default - if w.widget in ('menu', 'preset'): + if w.widget in ('menu', 'preset', 'entry'): v = _(v) w.variable.set(v) diff --git a/pysollib/util.py b/pysollib/util.py index 789d647f..8c651421 100644 --- a/pysollib/util.py +++ b/pysollib/util.py @@ -64,14 +64,6 @@ import sys, os from settings import DATA_DIRS, TOOLKIT from mfxutil import Image -# PIL -Image = ImageTk = ImageOps = None -if TOOLKIT == 'tk': - try: - import Image, ImageTk, ImageOps - except ImportError: - pass - # /*********************************************************************** # // constants diff --git a/pysollib/winsystems/__init__.py b/pysollib/winsystems/__init__.py index e9691e0c..b5bcac53 100644 --- a/pysollib/winsystems/__init__.py +++ b/pysollib/winsystems/__init__.py @@ -28,5 +28,5 @@ elif WIN_SYSTEM == 'aqua': else: # 'x11' import x11 as gui -initRootWindow = gui.initRootWindow +init_root_window = gui.init_root_window TkSettings = gui.TkSettings diff --git a/pysollib/winsystems/aqua.py b/pysollib/winsystems/aqua.py index 7a16d598..5b951214 100644 --- a/pysollib/winsystems/aqua.py +++ b/pysollib/winsystems/aqua.py @@ -26,28 +26,27 @@ from pysollib.settings import TOOLKIT, USE_TILE from pysollib.tile import Tile from pysollib.macosx.appSupport import hideTkConsole -from common import baseInitRootWindow, BaseTkSettings +from common import base_init_root_window, BaseTkSettings -class initRootWindow(baseInitRootWindow): - def __init__(self, root, app): - baseInitRootWindow.__init__(self, root, app) - if TOOLKIT == 'tk': - hideTkConsole(root) - if TOOLKIT == 'gtk': - pass - elif USE_TILE: - style = Tile.Style(root) - color = style.lookup('.', 'background') - if color: - root.tk_setPalette(color) # for non-Tile widgets +def init_root_window(root, app): + base_init_root_window(root, app) + if TOOLKIT == 'tk': + hideTkConsole(root) + if TOOLKIT == 'gtk': + pass + elif USE_TILE: + style = Tile.Style(root) + color = style.lookup('.', 'background') + if color: + root.tk_setPalette(color) # for non-Tile widgets - # standard Tk scrollbars work on OS X, but Tile ones look weird - Tile.Scrollbar = Tkinter.Scrollbar + # standard Tk scrollbars work on OS X, but Tile ones look weird + Tile.Scrollbar = Tkinter.Scrollbar - else: # pure Tk - #root.option_add(...) - pass + else: # pure Tk + #root.option_add(...) + pass class TkSettings(BaseTkSettings): diff --git a/pysollib/winsystems/common.py b/pysollib/winsystems/common.py index cf632b72..4d79da91 100644 --- a/pysollib/winsystems/common.py +++ b/pysollib/winsystems/common.py @@ -30,10 +30,22 @@ from pysollib.tile import Tile def init_tile(app, top): + Tile.initialize(top) + # load available themes d = os.path.join(app.dataloader.dir, 'themes') if os.path.isdir(d): top.tk.call('lappend', 'auto_path', d) - Tile.initialize(top) + for t in os.listdir(d): + if os.path.exists(os.path.join(d, t, 'pkgIndex.tcl')): + try: + if Tile.TileVersion < '0.8': + top.tk.call('package', 'require', 'tile::theme::'+t) + else: + top.tk.call('package', 'require', 'ttk::theme::'+t) + #print 'load theme:', t + except: + traceback.print_exc() + pass def set_theme(app, top, theme): @@ -64,6 +76,8 @@ def get_font_name(font): traceback.print_exc() else: fa = f.actual() + if fa['size'] > 0: + fa['size'] = -fa['size'] font_name = (fa['family'], fa['size'], fa['slant'], @@ -71,28 +85,28 @@ def get_font_name(font): return font_name -class baseInitRootWindow: - def __init__(self, root, app): - #root.wm_group(root) - root.wm_title(PACKAGE + ' ' + VERSION) - root.wm_iconname(PACKAGE + ' ' + VERSION) - # set minsize - sw, sh, sd = (root.winfo_screenwidth(), - root.winfo_screenheight(), - root.winfo_screendepth()) - if sw < 640 or sh < 480: - root.wm_minsize(400, 300) - else: - root.wm_minsize(520, 360) +def base_init_root_window(root, app): + #root.wm_group(root) + root.wm_title(PACKAGE + ' ' + VERSION) + root.wm_iconname(PACKAGE + ' ' + VERSION) + # set minsize + sw, sh, sd = (root.winfo_screenwidth(), + root.winfo_screenheight(), + root.winfo_screendepth()) + if sw < 640 or sh < 480: + root.wm_minsize(400, 300) + else: + root.wm_minsize(520, 360) + + if TOOLKIT == 'gtk': + pass + elif USE_TILE: + theme = app.opt.tile_theme + init_tile(app, root) + set_theme(app, root, theme) + else: + pass - if TOOLKIT == 'gtk': - pass - elif USE_TILE: - theme = app.opt.tile_theme - init_tile(app, root) - set_theme(app, root, theme) - else: - pass class BaseTkSettings: canvas_padding = (0, 0) diff --git a/pysollib/winsystems/win32.py b/pysollib/winsystems/win32.py index 772fb4e9..2cc8fa36 100644 --- a/pysollib/winsystems/win32.py +++ b/pysollib/winsystems/win32.py @@ -24,29 +24,28 @@ import sys, os from pysollib.settings import TOOLKIT, USE_TILE from pysollib.tile import Tile -from common import baseInitRootWindow, BaseTkSettings +from common import base_init_root_window, BaseTkSettings -class initRootWindow(baseInitRootWindow): - def __init__(self, root, app): - baseInitRootWindow.__init__(self, root, app) - if TOOLKIT == 'gtk': - pass - elif USE_TILE: - theme = app.opt.tile_theme - style = Tile.Style(root) - if theme not in ('winnative', 'xpnative'): - color = style.lookup('.', 'background') - if color: - root.tk_setPalette(color) - ##root.option_add('*Menu.foreground', 'black') - root.option_add('*Menu.activeBackground', '#08246b') - root.option_add('*Menu.activeForeground', 'white') - if theme == 'winnative': - style.configure('Toolbutton', padding=2) - else: - #root.option_add(...) - pass +def init_root_window(root, app): + base_init_root_window(root, app) + if TOOLKIT == 'gtk': + pass + elif USE_TILE: + theme = app.opt.tile_theme + style = Tile.Style(root) + if theme not in ('winnative', 'xpnative'): + color = style.lookup('.', 'background') + if color: + root.tk_setPalette(color) + ##root.option_add('*Menu.foreground', 'black') + root.option_add('*Menu.activeBackground', '#08246b') + root.option_add('*Menu.activeForeground', 'white') + if theme == 'winnative': + style.configure('Toolbutton', padding=2) + else: + #root.option_add(...) + pass class TkSettings(BaseTkSettings): diff --git a/pysollib/winsystems/x11.py b/pysollib/winsystems/x11.py index aea0817a..9f7cb7a5 100644 --- a/pysollib/winsystems/x11.py +++ b/pysollib/winsystems/x11.py @@ -28,106 +28,119 @@ from pysollib.settings import PACKAGE from pysollib.settings import TOOLKIT, USE_TILE from pysollib.tile import Tile -from common import baseInitRootWindow, BaseTkSettings, get_font_name +from common import base_init_root_window, BaseTkSettings, get_font_name # /*********************************************************************** # // Init root window # ************************************************************************/ -class initRootWindow(baseInitRootWindow): - def __init__(self, root, app): - baseInitRootWindow.__init__(self, root, app) +def init_root_window(root, app): + + base_init_root_window(root, app) ## if TOOLKIT == 'tk': ## window.wm_iconbitmap("@"+filename) ## window.wm_iconmask("@"+filename) - ##root.self.wm_maxsize(9999, 9999) # unlimited - if TOOLKIT == 'gtk': - pass - elif USE_TILE: - f = os.path.join(app.dataloader.dir, 'tcl', 'menu8.4.tcl') - if os.path.exists(f): - try: - root.tk.call('source', f) - except: - traceback.print_exc() - f = os.path.join(app.dataloader.dir, 'tcl', 'clrpick.tcl') - if os.path.exists(f): - try: - root.tk.call('source', f) - except: - traceback.print_exc() - f = os.path.join(app.dataloader.dir, 'tcl', 'fsdialog.tcl') - if os.path.exists(f): - try: - root.tk.call('source', f) - except: - traceback.print_exc() - else: - import tkFileDialog - tkFileDialog.Open.command = 'ttk::getOpenFile' - tkFileDialog.SaveAs.command = 'ttk::getSaveFile' - tkFileDialog.Directory.command = 'ttk::chooseDirectory' + ##root.self.wm_maxsize(9999, 9999) # unlimited + if TOOLKIT == 'gtk': + pass + elif USE_TILE: + f = os.path.join(app.dataloader.dir, 'tcl', 'menu8.4.tcl') + if os.path.exists(f): + try: + root.tk.call('source', f) + except: + traceback.print_exc() + f = 'clrpick8.4.tcl' + if Tile.TileVersion >= '0.8': + f = 'clrpick8.5.tcl' + f = os.path.join(app.dataloader.dir, 'tcl', f) + if os.path.exists(f): + try: + root.tk.call('source', f) + except: + traceback.print_exc() + f = 'fsdialog8.4.tcl' + if Tile.TileVersion >= '0.8': + f = 'fsdialog8.5.tcl' + f = os.path.join(app.dataloader.dir, 'tcl', f) + if os.path.exists(f): + try: + root.tk.call('source', f) + except: + traceback.print_exc() + else: + import tkFileDialog + tkFileDialog.Open.command = 'ttk::getOpenFile' + tkFileDialog.SaveAs.command = 'ttk::getSaveFile' + tkFileDialog.Directory.command = 'ttk::chooseDirectory' - style = Tile.Style(root) - color = style.lookup('.', 'background') - if color: - root.tk_setPalette(color) + style = Tile.Style(root) + color = style.lookup('.', 'background') + if color: + root.tk_setPalette(color) - root.option_add('*Menu.borderWidth', 1, 60) - root.option_add('*Menu.activeBorderWidth', 1, 60) - color = style.lookup('.', 'background', 'active') - if color: - root.option_add('*Menu.activeBackground', color, 60) + root.option_add('*Menu.borderWidth', 1, 60) + root.option_add('*Menu.activeBorderWidth', 1, 60) + color = style.lookup('.', 'background', 'active') + if color: + root.option_add('*Menu.activeBackground', color, 60) - root.option_add('*Listbox.background', 'white', 60) - root.option_add('*Listbox.foreground', 'black', 60) - root.option_add('*Listbox*selectBackground', '#0a5f89', 60) - root.option_add('*Listbox*selectForeground', 'white', 60) + root.option_add('*Listbox.background', 'white', 60) + root.option_add('*Listbox.foreground', 'black', 60) + root.option_add('*Listbox*selectBackground', '#0a5f89', 60) + root.option_add('*Listbox*selectForeground', 'white', 60) - font = root.option_get('font', PACKAGE) + font = root.option_get('font', PACKAGE) + if font: + # use font from xrdb + fn = get_font_name(font) + if fn: + root.option_add('*font', font) + style.configure('.', font=font) + app.opt.fonts['default'] = fn + # treeview heading + f = root.tk.splitlist(root.tk.call('font', 'actual', fn)) + root.tk.call('font', 'configure', 'TkHeadingFont', *f) + else: + # use font from Tile settings + font = style.lookup('.', 'font') if font: - # use font from xrdb fn = get_font_name(font) if fn: root.option_add('*font', font) - style.configure('.', font=font) app.opt.fonts['default'] = fn - # treeview heading - f = root.tk.splitlist(root.tk.call('font', 'actual', fn)) - root.tk.call('font', 'configure', 'TkHeadingFont', *f) - else: - # use font from Tile settings - font = style.lookup('.', 'font') - if font: - fn = get_font_name(font) - if fn: - root.option_add('*font', font) - app.opt.fonts['default'] = fn - if app.opt.tile_theme in ('clam', 'clearlooks'): - root.wm_minsize(550, 360) - style.configure('TLabelframe', labeloutside=False, - labelmargins=(8, 0, 8, 0)) + if app.opt.tile_theme in ('clam', 'clearlooks'): + root.wm_minsize(550, 360) + style.configure('TLabelframe', labeloutside=False, + labelmargins=(8, 0, 8, 0)) - # + # + else: + root.option_add('*Entry.background', 'white', 60) + root.option_add('*Entry.foreground', 'black', 60) + root.option_add('*Listbox.background', 'white', 60) + root.option_add('*Listbox.foreground', 'black', 60) + root.option_add('*Listbox*selectBackground', '#0a5f89', 60) + root.option_add('*Listbox*selectForeground', 'white', 60) + ##root.option_add('*borderWidth', '1', 50) + ##root.option_add('*Button.borderWidth', '1', 50) + root.option_add('*Scrollbar.elementBorderWidth', 1, 60) + root.option_add('*Scrollbar.borderWidth', 1, 60) + root.option_add('*Menu.borderWidth', 1, 60) + root.option_add('*Menu.activeBorderWidth', 1, 60) + #root.option_add('*Button.HighlightBackground', '#595d59') + #root.option_add('*Button.HighlightThickness', '1') + font = root.option_get('font', PACKAGE) + if font: + fn = get_font_name(font) + app.opt.fonts['default'] = fn else: - root.option_add('*Entry.background', 'white', 60) - root.option_add('*Entry.foreground', 'black', 60) - root.option_add('*Listbox.background', 'white', 60) - root.option_add('*Listbox.foreground', 'black', 60) - root.option_add('*Listbox*selectBackground', '#0a5f89', 60) - root.option_add('*Listbox*selectForeground', 'white', 60) - ##root.option_add('*borderWidth', '1', 50) - ##root.option_add('*Button.borderWidth', '1', 50) - root.option_add('*Scrollbar.elementBorderWidth', 1, 60) - root.option_add('*Scrollbar.borderWidth', 1, 60) - root.option_add('*Menu.borderWidth', 1, 60) - root.option_add('*Menu.activeBorderWidth', 1, 60) - #root.option_add('*Button.HighlightBackground', '#595d59') - #root.option_add('*Button.HighlightThickness', '1') - root.option_add('*font', 'helvetica 12', 60) + root.option_add('*font', 'helvetica -12', 60) + app.opt.fonts['default'] = ('helvetica', -12, + 'roman', 'normal')