Version 11 of snitfinddialog

Updated 2003-11-24 16:42:37

DDG: Tired of writing again and again those clumsy find dialogs I wrapped all into a Snit's Not Incr Tcl toplevel widget.

 # NAME snitfinddialog
 #    snitfindialog path ?args?
 #   snitfilendialog provides a standard find dialog layout
 #   all buttons and the entries are accessable via the componet subcommand
 #   the components are: find, next (standard tk buttons), entry (standard tk entry)
 #   delegated is -textvariable to the entry component
 #   all other options must be send via the component subcommand
 #   -findcmd The command to invoke if "Find" is pressed.
 #   -findnextcmd The command to invoke if "Find Next" is pressed.
 #   -case Case sensitivity of search either true or false. Defaults to false.
 #   -word Matches whole words only true or false. Defaults to false.
 #   -forward Forward (true) or backward (false) searches. Defaults to true.
 #   pathName component componentname ?args?
 #      without args it returns the component path to be saved inside a variable
 #      with args it evaluates args in the context of the component 
 #      if the first argument of args is bind a binding for the component is created 
 #    Dr. Detlef Groth [email protected]
 #    20/11/2003 Version 0.1 initial release


And here is the actual code about 60 lines:

 package require snit 0.9
 snit::widget snitfinddialog {
    hulltype toplevel
    delegate option -findcmd to component(find) as -command
    delegate option -findnextcmd to component(next) as -command
    delegate option -textvariable to component(entry)
    option -case 0
    option -word 0
    option -forward yes
    variable component
    constructor {args} {
        wm resizable $win false false
        pack [frame $win.left] -side left -padx 5 -pady 5 -ipadx 5 -ipady 5 \
                  -expand yes -fill both
        pack [frame $win.right] -side left -padx 5 -pady 5 -ipadx 5 -ipady 5 \
                  -expand yes -fill both
        pack [button $ -text " Find " -width 15] -side top \
                  -padx 5 -pady 8
        set component(find) $
        pack [button $win.right.searchnext -text " Find Next " -width 15] \
                  -side top -padx 5 -pady 12
        set component(next) $win.right.searchnext
        pack [entry $win.left.entry] -side top -padx 5 -pady 5 -expand yes -fill x
        set component(entry) $win.left.entry
        pack [frame $win.left.bottom] -side top
        pack [frame $win.left.bottom.left] -side left
        pack [checkbutton $win.left.bottom.left.words -text "Whole Words ?  " \
              -variable [varname options(-word)]] -side top -padx 5 -pady 5 -anchor w
        set component(wholewords) $win.left.bottom.left.words
        pack [checkbutton $win.left.bottom.left.uclc -text  "Case sensitive ?" \
              -variable [varname options(-case)]]  -side top -padx 5 -pady 5 -anchor w
        set component(casesensitive) $win.left.bottom.left.uclc
        pack [labelframe $win.left.bottom.right -text " Direction "] -side left \
                  -expand yes -fill both
        pack [radiobutton $win.left.bottom.right.forward -text "Forward " \
              -variable [varname options(-forward)] -value yes] -side top -anchor w -padx 5
        set component(forward) $win.left.bottom.right.forward
        pack [radiobutton $win.left.bottom.right.backward -text "Backward" \
              -variable [varname options(-forward)] -value no] -side top -anchor w  -padx 5
        set component(backward) $win.left.bottom.right.backward
        $self configurelist $args
    method component {w args} {
        if {[llength $args] == 0} {
            if {[info exists component($w)]} {
                return $component($w)
            } else {
                error "Component does not exist! Components are: [array names component]!"
        } else {
            if {[info exists component($w)]} {
                if {[lindex $args 0] eq "bind"} {
                    if {[llength $args] == 3} {
                        eval { bind $component($w) } [lrange $args 1 end]
                    } else {
                        error "Wrong number of arguments: Usage pathName component componentname bind event script"
                } else {
                    eval { $component($w) } $args
            } else {
                error "Component does not exist! Components are: [array names component]!"


And here is an example of usage:

 proc Test_Find {} {
    global textvar
    # testing mFind
    proc Next {} {
        global textvar
        puts "Next $textvar"
    proc Find {} {
        global textvar
        puts "Find $textvar"

    set textvar test
    snitfinddialog .s -case 1 -findnextcmd Next -findcmd Find -textvariable textvar
    wm title .s "Search "
    # demonstrating the component subcommand
    .s component find configure -bg red
    set btn [.s component find]
    $btn configure -bg blue
    .s component find bind <Enter> {puts "Yeah Here Find, I am entered!"}
    .s component next bind <Enter> {puts "Yeah Here Next, I am entered!"} 


DDG: Any suggestions, improvements ? Welcome!

escargo 20 Nov 2003 - Just a couple of things. I have a Windows XP laptop with ActiveState ActiveTcl 8.4.4 installed. That includes tcllib1.5. Apparently the package require snit 0.9 is satisfied with the 0.82 version included in tcllib. You might want to change the require to package require -exact snit 0.9 to avoid that problem (which, admittedly causes a different problem in the future).

Second, since I'm running on Windows, the puts in Test_find have nowhere to go. I changed the bindings on the find and next buttons to change color on enter and leave events instead. You might consider putting some Windows-toleration code in there for people running without consoles.

Re. 0.9 vs. 0.82, note that 9 < 82. If snit was at 0.81 at some point, then a new release should have been bumped to 0.90, not 0.9. The issue could be resolved by releasing 0.91 and never ever using "package require snit 0.9" anywhere -jcw

Mea culpa. I've got some changes to make anyway. -- WHD

DDG: If running on windows why not simply run a wish. Copy the code into the console and see what it's putting! That's the way I Test_Find!

escargo 24 Nov 2003 - I use wish-reaper to download code onto my Windows laptop; I might review what I get with ASED, but then I just want to double-click on the file to run it. Many pages on the wiki are reapable, so that they can run just as they appear. That's a lot simpler than having to start wish, open the code with some application, and copy it into the console. Why make it harder than it needs to be.


See also Snit's Not Incr Tcl, snitbrowser.