ANNOUNCE: Actions for Tk

29 views
Skip to first unread message

bryan schofield

unread,
Nov 19, 2003, 12:50:44 AM11/19/03
to
hello -

I wrote a fairly small package the provides the "action" concept for
Tcl/Tk user interfaces. If your are unfamiliar with "actions", an action
is a set of data that represents something a user would do. An action is
applied to one or more widgets, commonly buttons or menus. Modification
to action is automatically propogated to any widgets that the action has
been applied to.

The action frame work provides a simple mechanism for describing what an
action is composed of and what classes of widgets actions can be applied
to. The framework itself does not make any assumptions on what an action
is, other than it is a collection of data. However, since buttons and
menus are most likely the widgets that actions will be applied, the
action package provides everything you need to create actions and apply
them to buttons and menus. The action framework makes it simple to apply
actions to other classes of Tk widgets and custom megawidgets based on
the "class" (winfo class $w) of the widget. It is also very simple to
specify what data an action is composed of.

The fully documented code and demo program can be found here for the
time being. I'd appreciate any comments and suggestions. If the TCL
community deems this to be a worth-while package, I'd like suggestions
on a permanent home.

http://home.cfl.rr.com/lewca43/tcl/action.tcl.txt
http://home.cfl.rr.com/lewca43/tcl/action-demo.tcl.txt


- bryan (bschofield at users dot sourceforge dot net)


Simple Example:

package require action
namespace eval ::img {}
image create photo ::img::myImg -file myImg.gif
::action::create myAction \
-text "Do Something" \
-image ::img::myImg \
-command doSomething
button .b
menu .m
::action::apply myAction .b .m
...
# disable all of the widgets associated with the action
::action::configure myAction -state "disabled"
...
# re-enable all of the widgets associated with the action,
# but now make it do something else
::action::configure myAction \
-state "normal" \
-text "Do Something Else" \
-command doSomethingElse

John Seal

unread,
Nov 23, 2003, 3:45:12 PM11/23/03
to
In article <UwDub.7189$KI4....@twister.tampabay.rr.com>,
bryan schofield <bscho...@users.sourceforge.net> wrote:

> an action
> is a set of data that represents something a user would do. An action is
> applied to one or more widgets, commonly buttons or menus.

In the source file you define action as "A collection of options and
values that can be set and queried at a single data repository but
applies to any number of Tk widgets. These options, typically refered to
as 'configuration options', may not be applicable to all widgets."

Calling this an "action" seems confusing to me. I understand that it's
very common for a GUI to change state whenever the user takes certain
actions. For example, changing modes may require whole bunches of
buttons and menu items to be enabled or disabled, and certain labels and
images to change state according to the selected mode. But this seems
like a "response" rather than an "action".

Perhaps I'm taking the wrong point of view. The user takes a certain
action, so the code responds by invoking one of your "actions" to change
state on many widgets at once. User actions trigger code actions. It
still seems more like a response, to me.

Bryan Oakley

unread,
Nov 23, 2003, 11:59:36 PM11/23/03
to
John Seal wrote:
>
> Calling this an "action" seems confusing to me. I understand that it's
> very common for a GUI to change state whenever the user takes certain
> actions. For example, changing modes may require whole bunches of
> buttons and menu items to be enabled or disabled, and certain labels and
> images to change state according to the selected mode. But this seems
> like a "response" rather than an "action".
>
> Perhaps I'm taking the wrong point of view. The user takes a certain
> action, so the code responds by invoking one of your "actions" to change
> state on many widgets at once. User actions trigger code actions. It
> still seems more like a response, to me.

I may be responding out of turn because I'm not overly familiar with
Bryan Schofield's actions and don't mean to speak for him, but I've
developed various incarnations of actions for years so I'm familiar with
the concept in general. I think Mr. Schofields' and my concepts are
quite similar, even down to some (but not all) of the implementation
details, so hopefully my comments will apply.

The way I see it, the actions are indeed what the user does. That is, if
they press the "cut" button it invokes the "cut" action. That is the
primary purpose of an action -- to implement the behavior behind an
action performed by a user (button press, key press, etc). Looking at it
that way, the term "action" seems quite correct.

However, that's really nothing more than what one can get with procs.
The value-add of an action is that an action also knows which widgets
are associated with itself. This enables an action to be able to enable
or disable all user interface elements that the user uses to invoke the
action when the action itself is enabled or disabled.

To my way of thinking then, the main purpose of an action is to define
code to be run when the user performs a specific action -- cut, copy,
paste, exit, calculate, etc. By associating actions with interface
elements, a side benefit is that an action knows how to enable or
disable all user interface elements the user may use to invoke that
particular action when the action itself is enabled or disabled.

This frees the application developer from the tedium of having to
remember to enable or disable all of the various physical manifestations
of a user action and instead focus on enabling and disabling the
functionality itself. This is a very powerful concept, and reaps rewards
not only in an application whose various interface elements are in sync,
but also over time as new ways to invoke various application features
are added or changed. Also, depending on how pervasively the action
concept is used within an application, they can also play an important
role in automated GUI testing.


bryan schofield

unread,
Nov 25, 2003, 1:02:54 AM11/25/03
to
Bryan Oakley hit the nail on the head. But in addition to an action just
being able to know and handle state transition to all widgets that an
user can use to execise some particular piece of the software, the
action also combines the other things that the user needs, so the
developer is again freed from having to the same thing for all widgets.

To help clarify my point, we can define an action as
1. Some command (or proc) that needs to be evaluated to achieve some end
goal. Using Bryan's example, let's say "cut"
2. Some textual string that will identify the action to the user,
perhaps "Cut"
3. Some image that also helps identify the action, say an image of a
pair of scissors, img::cut
4. Some usability state of the action. It be desirable to not allow the
user to invoke the action at some time, and allow it at another.

In addition to those 4 basic things, we may also decide that an action
is more than that. For example, we may want the controls which we
provide to the user to have some context sensitive help that is
displayed in a tooltip or statusbar. In which case we would extend the
action defintion to include "-helptext" (or similar), using the command:
::action::addOption -helptext ""
We'd also want to augment the widget Applicators to understand
"-helptext", which is a trivial task.

Now the developer need only define in one place what a user can do:
action::create cut \
-text "Cut" \
-image img::cut \
-helptext "Cut the selected text" \
-state normal \
-command myCutProc

The task of declaring this to all of the widgets we provide to the user
that allow him or her to cut is now minimized to creating the action
(above) and applying to widgets:

action::apply cut .cutButton .editMenu .text.popupMenu

Additionally, we've simplified the amount of work required to modify the
the controls should we need to change some attribute of the "action",
state being the most obvious, but a program may have a language
preference that user can set while running:

action::configure cut \
-text "Coupe" \
-helptext "Coupez le texte choisi"

Since the "action" is responsible for knowing what to do and how to do
it (using Applicator as helpers) to the various controls, the developer
is able to focus more on the bigger picture instead mundane details.
Another benefit is that your application code will be smaller and easier
to read.

-- bryan

Donald Arseneau

unread,
Nov 25, 2003, 6:29:08 AM11/25/03
to
bryan schofield <bscho...@users.sourceforge.net> writes:

> To help clarify my point, ...

OK, in real life I have a menu that includes a "Write data" entry
when a run is in progress. Also when a run is in progress, a "Write"
button is displayed. The Write button is disabled while data is
being written -- both to prevent users from hammering on it rapidly
and to provide visual feedback for when the Write is completed.

So how would this be coded with an "action"?

Donald Arseneau as...@triumf.ca

bryan schofield

unread,
Nov 28, 2003, 1:08:05 AM11/28/03
to

action::create writedata \
-text "Write Data" \
-command "writeData"

menu .m
button .b

# apply the action to the button, and menu.
# the Menu will get a new command entry for "Write Data"
action::apply writedata .m .b

proc writeData {} {
action::configure writedata -state disabled
...
# write the data
...
action::confidure writedata -state normal
}

Ahhh... so pretty.

-- bryan

John Seal

unread,
Nov 30, 2003, 12:57:39 PM11/30/03
to
In article <igCwb.62570$86.9...@twister.tampabay.rr.com>,
bryan schofield <bscho...@users.sourceforge.net> wrote:

> Bryan Oakley hit the nail on the head.

[Additional clarification snipped.]

I agree with all of that. My sole issue was with the name that you call
them, which I found confusing. Most of the examples people have cited
for them make them seem more like "responses" to user actions, rather
than actions themselves. I can imagine other interpretations, e.g.,
"they place a GUI in a state where the user can take certain actions
that were not available before", which sounds like an action, but on the
other hand, that action was probably a response to a still earlier user
action, and so on ad infinitum.

I guess my point is, I personally would have understood them much more
quickly if they had been called "responses" (or maybe "states") rather
than "actions".

You should also be aware that, among my coworkers, my ability to
misunderstand simple explanations is legendary. And if there are
multiple ways to misunderstand, I will pick the worst possible way!

Reply all
Reply to author
Forward
0 new messages