#!/bin/sh # Restart with tcl: -*- mode: tcl; tab-width: 8; -*- \ exec wish $0 ${1+"$@"} ##+########################################################################## # # WConfig.tcl -- a widget configuration editing tool # by Keith Vetter # # Revisions: # KPV Nov 27, 2001 - initial revision # KPV Sep 24, 2003 - cleaned up for Wiki posting # ##+########################################################################## ############################################################################# package require Tk package require Tktable namespace eval WConfig { variable TableData ;# Used by Tktable variable TableData_org ;# So we can reset variable W ;# The table widget variable widget "" ;# Widget we're configuring variable new "" ;# Display version of widget variable rows ;# Rows of data variable TOP ;# Toplevel for our display } ##+########################################################################## # # ::WConfig::go -- main programming entry to this package. Puts up a dialog # allowing you to view and edit the configuration properties of widget "w" # proc ::WConfig::go {w} { variable W variable widget $w variable rows variable new $w variable TOP set TOP .conf_conf set TOPF "$TOP.top" ;# Various gridding frames set TOPB "$TOP.bottom" set TOPB2 "$TOP.bottom2" set W $TOPF.t ;# The table widget ::WConfig::Refresh set rows [llength [array names ::WConfig::TableData *,2]] if {[winfo exists $TOP]} { ;# Already displayed $W config -rows $rows ::WConfig::Colorize wm title $TOP "[winfo class $w] $w Configuration" return } toplevel $TOP wm protocol $TOP WM_DELETE_WINDOW ::WConfig::Exit set t [winfo toplevel $w] wm geom $TOP "+[expr {[winfo x $t] + [winfo width $t] + 10}]+[winfo y $t]" wm title $TOP "[winfo class $w] $w Configuration" frame $TOPF frame $TOPB -bd 2 -relief ridge frame $TOPB2 -bd 2 -relief ridge table $W -rows $rows \ -cols 3 \ -titlerows 1 \ -autoclear 1 \ -multiline 0 \ -yscrollcommand [list $TOPF.sy set] \ -xscrollcommand [list $TOPF.sx set] \ -colstretchmode all \ -rowstretchmode none \ -selectmode extended \ -sparsearray 0 \ -variable ::WConfig::TableData \ -colwidth 20 \ -validate 1 \ -vcmd [list ::WConfig::vcmd %r %S] \ -coltagcommand ::WConfig::colProc $W tag configure active -fg black $W tag configure col_0 -state disabled $W tag configure col_1 -state disabled $W tag configure ccell -bg red ;# Changed cell $W tag configure mcell -bg green ;# Modified from default $W tag configure ncell ;# Normal cell $W tag raise ccell active $W tag raise mcell active $W tag raise ncell active proc ::WConfig::colProc col { return "col_$col" } scrollbar $TOPF.sy -command [list $W yview] scrollbar $TOPF.sx -command [list $W xview] -orient horizontal button $TOPB.d -text Default -command {::WConfig::Apply default} -width 10 button $TOPB.r -text Refresh -command ::WConfig::Refresh -width 10 button $TOPB.r0 -text Reset -command {::WConfig::Apply reset} -width 10 button $TOPB.a -text Apply -command {::WConfig::Apply apply} -width 10 button $TOPB2.select -text "Select Widget" -command ::WConfig::New bind $TOPB2.select <ButtonRelease-1> [list ::WConfig::NewDrag %X %Y] entry $TOPB2.swidget -textvariable ::WConfig::new bind $TOPB2.swidget <Key-Return> ::WConfig::New button $TOPB2.q -text Quit -width 10 -command ::WConfig::Exit pack $TOPB2 -side bottom -fill both -ipady 5 pack $TOPB -side bottom -fill both -ipady 5 pack $TOPF -side top -fill both -expand 1 pack $TOPB2.select $TOPB2.swidget -side left -padx 5 pack $TOPB2.q -side right -padx 5 pack $TOPB.a $TOPB.d $TOPB.r0 $TOPB.r -side right -padx 5 -expand 1 grid $W $TOPF.sy -sticky news grid $TOPF.sx -sticky ew grid columnconfig $TOPF 0 -weight 1 grid rowconfig $TOPF 0 -weight 1 bind $W <Key-Return> "[bind Table <Down>];break" bind $W <Key-Return> "[bind Table <Down>];break" bind $W <Tab> "[bind Table <Down>];break" bind $W <Shift-Tab> "[bind Table <Up>];break" ::WConfig::Colorize } ##+########################################################################## # # ::WConfig::Refresh -- fills in the TableData array used by the table widget # proc ::WConfig::Refresh {} { variable TableData ;# Used by Tktable variable TableData_org ;# So we can reset variable widget catch {unset TableData} catch {unset TableData_org} array set TableData { 0,0 "Option Name" 0,1 "Default Value" 0,2 "Current Value"} set row 1 foreach datum [$widget configure] { if {[llength $datum] != 5} continue ;# Throw out shortcuts foreach col [list 0 1 2] cdata [list 0 3 4] { set d [lindex $datum $cdata] if {$d == ""} {set d {{}}} set TableData($row,$col) $d } incr row } array set TableData_org [array get TableData] ;# Make a backup of the data ::WConfig::Colorize } proc ::WConfig::vcmd {row newVal} { ::WConfig::ColorizeRow $row $newVal return 1 } ##+########################################################################## # # ::WConfig::ColorizeRow -- marks row w/ appropriate colorized tag # proc ::WConfig::ColorizeRow {row {newVal {}}} { variable TableData variable TableData_org variable W set default $TableData($row,1) set before $TableData_org($row,2) if {$newVal == {}} { set now $TableData($row,2) } else { set now $newVal } set rval 0 ;# Assume no change set ctag ncell ;# Tag for the cell if {$row > 0} { if {! [string equal $before $now]} { ;# Changed by WConfig set ctag ccell set rval 1 } elseif {! [string equal $default $now]} { ;# Changed from default set ctag mcell set rval 2 } } $W tag cell $ctag $row,2 return 1 } ##+########################################################################## # # ::WConfig::Colorize -- colorizes all the rows # proc ::WConfig::Colorize {} { if {! [winfo exists $::WConfig::W]} return for {set row 1} {$row < $::WConfig::rows} {incr row} { ::WConfig::ColorizeRow $row } } ##+########################################################################## # # ::WConfig::Apply -- updates the widget w/ either 1) the new values, # 2) the default values or 3) reset values # proc ::WConfig::Apply {{how "apply"}} { variable TableData ;# Used by Tktable variable TableData_org ;# So we can reset variable W variable widget set errs "" set rows [llength [array names TableData *,2]] for {set row 1} {$row < $rows} {incr row} { if {$how == "apply"} { set now $TableData($row,2) } elseif {$how == "default"} { set now $TableData($row,1) } elseif {$how == "reset"} { set now $TableData_org($row,2) } else continue if {$now == "{}"} {set now {}} set optname $TableData($row,0) set n [catch {$widget configure $optname $now} err] if {$n} { append errs " $optname: $err\n" } } ::WConfig::Refresh if {$errs != ""} { tk_messageBox -title "Widget Configure" -message "ERRORS:\n$errs" } } proc ::WConfig::New {} { variable new variable widget if {$new == $widget || ! [winfo exists $new]} return ::WConfig::go $new } ##+########################################################################## # # ::WConfig::NewDrag -- handles clicking down on select button, the moving # and releasing mouse on top of a different widget. # proc ::WConfig::NewDrag {x y} { set w [winfo containing $x $y] if {$w == ""} return if {[string match "$::WConfig::TOP*" $w]} return ;# Skip ourselves ::WConfig::go $w } proc ::WConfig::Exit {} { destroy $::WConfig::TOP catch {namespace delete ::WConfig} } ########################### # # Testing # pack [button .b -text MyButton -command [list puts "hi"]] ::WConfig::go .b
Category Debugging | Category GUI