[Bryan Oakley] - 20-May-2004 An ''action'' is a pseudo-object that has properties that mostly resemble procs. In addition, actions have state and are generally associated with one or more widgets. The main advantage an action has over a proc is that it "knows" which widgets it is associated with and can enable or disable all of the widgets when the action itself becomes enabled or disabled. Bryan Schofield posted to comp.lang.tcl a nice example of one implementation of actions [http://groups.google.com/groups?th=ddf110816a167ca9]. The use of actions is also mentioned at [Tk coding styles and philosophies]. Following is a quick example of how actions can be used, using a simpler implementation than the one described by Bryan Schofield. This comes from what I presently use and which, I might add, takes only 177 lines of code to implement (and 20% of that is comments). button .cut -text Cut -command [list action invoke cutAction] .menubar.editMenu add command -label "Cut" -command [list action invoke cutAction] .popup add command -label "Cut" -command [list action invoke cutAction] action associcate cutAction .cut [list .menubar.editMenu "Cut"] [list .popup "Cut"] bind all [list action invoke cutAction] ... action define cutAction {} { } proc toggleSelection {} { # called whenever the selection changes if {} { action disable cutAction copyAction } else { action enable cutAction copyAction } Notice that the use of actions adds only one extra line of code in your application (the line that begins "action associate"), and is actually a net loss of several lines of code. Without actions you might have to code '''toggleSelection''' as: proc toggleSelection {} { if {} { .cut configure -state normal .menubar.editMenu entryconfigure "Cut" -state normal .popup entryconfigure "Cut" -state normal } else { ... } Not only that, but without actions you also have to add code to make sure that if there is no selection that the procedure that does the cutting won't do anything if called via the accelerator. As you can see, actions make it much easier to maintain a consistent state across all widgets that implement a particular functionality. You only have to make a single function call to disable all controls that invoke the particular action. In addition, should you add new controls (speech recognition, gestures, additional buttons or menus, etc) you do not have to hunt down all the places where you might need to enable the widgets; associate the new control with the action and the action takes care of the rest. The above is just one sort of implementation. Many people might prefer a more object oriented approach. For example: new Action cutAction {...} cutAction button .cut -label "Cut" ... cutAction menuitem .menubar.editMenu "Cut" ... cutAction menuitem .popup "Cut" ... cutAction accelerator . In addition to the sheer convenience of actions, they also provide a nice API into your application, making your scripts scriptable. The scripts can be used to implement user defined macros, automated tests, or even compound actions. [Category Actions]