Here's a procedure which takes a few parameters (at least a unique tk toplevel window name) and shows a dialog for Search & Replace-type operations:
# 01.02.2010 # ToDo: # - namespace proc sr {w args} { # eingebaute Defaults array set a { -command {} -title {Suchen & Ersetzen} -old {} -new {} -ignoreword 0 -ignorecase 0 -entryWidth 40 -askempty 1 -stay 0 } array set a $args;# Fehler propagieren, kein Catch! toplevel $w if {[winfo viewable .]} { wm transient $w .; # [winfo parent] statt .? } wm withdraw $w wm title $w $a(-title) wm resizable $w 0 0; # wenn überhaupt, dann nur in x-Richtung (da Feldbreite fix) set wf1 [ttk::frame $w.txt -padding {4 8}] set wf2 [ttk::frame $w.but -padding {4 8}] set wf3 [ttk::labelframe $w.opt -padding {2 4} -text Optionen:] ttk::label $wf1.oldLbl -underline 0 -text "Suchen nach:" ttk::label $wf1.newLbl -underline 0 -text "Ersetzen durch:" ttk::entry $wf1.oldEntry -width $a(-entryWidth) -validate key \ -validatecommand [list srVal $wf2.ok %P] ttk::entry $wf1.newEntry -width $a(-entryWidth) ttk::button $wf2.ok -width 10 -text "Start" -state disabled \ -command [list srDo $w $a(-command) $a(-askempty) $a(-stay)]; # -default active ttk::button $wf2.quit -width 10 -text "Abbruch" -command [list destroy $w] ttk::checkbutton $wf3.word -text {Wortgrenzen ignorieren} -underline 0 ttk::checkbutton $wf3.case -text {Schreibweise ignorieren} -underline 1 $wf1.oldEntry insert end $a(-old); # erspart uns globale -textvariable(n) $wf1.newEntry insert end $a(-new) grid $wf1.oldLbl -column 0 -row 0 -sticky nse -padx {4 4} -pady {8 0} grid $wf1.newLbl -column 0 -row 1 -sticky nse -padx {4 4} -pady {8 0} grid $wf1.oldEntry -column 1 -row 0 -sticky nsew -padx {4 4} -pady {8 0} grid $wf1.newEntry -column 1 -row 1 -sticky nsew -padx {4 4} -pady {8 0} grid $wf2.ok -column 0 -row 0 -sticky nsew -padx {0 4} -pady {8 0} grid $wf2.quit -column 0 -row 1 -sticky nsew -padx {0 4} -pady {8 0} pack $wf3.word $wf3.case -side left -anchor nw grid $wf1 -column 0 -row 0 -sticky nsew -padx {4 4} -pady {4 0} grid $wf2 -column 1 -row 0 -sticky nsew -padx {4 4} -pady {4 4} grid $wf3 -column 0 -row 1 -sticky nsew -padx {12 12} -pady {0 12} -columnspan 2 bind $w <Escape> "$wf2.quit invoke; break;"; # <Escape> ist *überall* 'Abbruch' bind $w <Return> "$wf2.ok invoke; break;"; # <Return> ist *überall* 'Go!' (ausser auf Escape-Button) bind TButton <Return> "%W invoke; break;"; # alle Buttons führen sich mit <Return> aus bind $w <Alt-s> "focus -force $wf1.oldEntry; break;" bind $w <Alt-e> "focus -force $wf1.newEntry; break;" bind $w <Alt-w> "$wf3.word invoke; break;" bind $w <Alt-c> "$wf3.case invoke; break;" $wf3.word state !alternate $wf3.case state !alternate # geht das nicht eleganter??? if {$a(-ignoreword)} { $wf3.word state selected } if {$a(-ignorecase)} { $wf3.case state selected } # Farbgebung wie früher korrigieren, nur gemäss Ttk-Systematik bind TButton <FocusIn> {%W state active} bind TButton <FocusOut> {%W state !active} catch {center_window $w} wm deiconify $w catch {tk visibility $w} focus -force $wf1.oldEntry; # die -stay-Option könnte als Checkbox exportiert werden if {!$a(-stay)} { catch {grab set $w} } catch {tkwait window $w} } proc srVal {b v} { # uns interessiert hier nur das Umschalten des Buttos if {[string length $v]} { $b configure -state normal } else { $b configure -state disabled } return 1 } proc srDo {w command ask stay} { # vermeidet globale Vars set old [$w.txt.oldEntry get] set new [$w.txt.newEntry get] set igW [$w.opt.word instate selected] set igC [$w.opt.case instate selected] if {[string length $new] == 0 && $ask == 1} { if {[tk_messageBox -type yesno -title ACHTUNG: \ -message "Die Zeichenkette '$old' wird *gelöscht* werden! Wirklich fortfahren (J/N)?" -icon warning] == "no"} { return } } catch {uplevel #0 [list $command $old $new $igW $igC $w]} if {$stay == 0} { destroy $w } }
Some little tests / demonstrations:
####################### # # Demos # proc dummyCallback {args} { tk_messageBox -message "Dummy S/R-Aktion; args:= $args" } ttk::entry .e1 -width 40 pack .e1 bind .e1 <Control-f> [list sr .w1 -command dummyCallback] bind .e1 <Control-g> [list sr .w2 -command dummyCallback -stay 1 -old Datei -ignorecase 1] focus -force .e1
Some explanations (to be continued):