Skip to main content

Actions Article, by Mark Davidson - 05/10/2003

46 replies [Last post]
jeff
Offline
Joined: 2003-06-10

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Mark Davidson
Offline
Joined: 2006-02-17

> 1. The small icon attribute is not being used for
> menuitems in my application or in the demo. Is that
> how it is supposed to work?

Correct. The smicon attribute is not used in this framework. Furthermore, Swing will only recognize the value of the Action.SMALL_ICON attribute of an Action when constructing JMenuItems or JButtons for toolbars. Currently, this is mapped to the icon xml attribute.

You can modify the ActionManager/UIFactory code so that the larger icon is used for toolbar buttons and the small icons are used in menuitems. Here's how:

In ActionManager.configureAction, add the value of the small icon to a custom key:

action.putValue("action-small-icon", getIcon(attr.getValue(SMICON_INDEX)));

In the protected method UIFactory.configureMenuItem, add the line:

menuItem.setIcon((Icon)action.getValue("action-small-icon"));

I should have done this in the framework but it was overlooked.

> 2. In most GUI toolkits if you have a menu that has
> menuitems with and without icons, the text for the
> menitems without icons is indented. That way all the
> text is aligned.

This is a Swing issue and is really out of the domain of the actions framework. This has been a long standing complaint 4199382 and I just checked the bug database and it appears that it still hasn't been fixed - not even in 1.5. I'll ping some people.

> 3. Do you plan on enhancing this in new versions.
> Internalization support via properties files as
> discussed would be my main concern.

I'm not really planning to. A lot of this action framework has already been improved and enhanced and will be part of JDNC.

clavinova
Offline
Joined: 2006-02-17

Mark,

This framework is really nice work. Actaully I have developed a small scale API something similar to your idea but your works are more completed.

I have some questin on the state management. I do not see how could be easily manage the UI state in this framework. For example, when I click the a tree node, the menu should be changed, some menu item is disabled and some menuitem is removed. When the focus moved to other tree node, the menu changed again based on the context. For my application, there could be more than 20 different states there and need to adjust menu/toolbar correspondently. So based on each state to disable/hide menu in hardcoding is really not a way that matches this framework. You do have a state inner class in the demo java file. But how to to make it working with XML? Do you have any idea on how to manage this thing very clean? Is it possible to define the state/menu mapping in the XML also?

You said there is some big article taking about the state management. Do you have any referance resource to direct me reading on this topic?

Thanks a lot,
Clavinova

Mark Davidson
Offline
Joined: 2006-02-17

Hi Clavinova,

We in the JDNC group have been thinking about how changes in application state will affect sets of available actions. We are at the stage where we are facing these same issues.

The actions architecture in JDNC has changed since this article was published. There is a much looser binding between the presentation part of the action - the name, icon, description (the stuff the user sees and interacts with) and the semantics of the action - which used to correspond to the ActionHandler or callback method but is now a tiny Action stuffed in the ActionMap of the JComponent.

These two types of actions are linked by a common identifier in the xml (the id attribute which represents the action command) and is used as the key to lookup the action in the ActionMap of the component. The new architecture no longer needs an explicit registerCallback in the ActionManager to create the binding between the presentation action and the semantic action. This decouples the UI presentation from the semantic action at compile time and defers the lookup until the action is invoked through user input. I have been calling the actions which have been defined by the XML TargetableActions and the invocation is delegated to the TargetManager. You can programatically change the target that the TargetManager will invoke through changes in application state. By default, the TargetManager fetches the component which is the global focus owner and invokes the action in the components ActionMap which corresponds to the action command of the presentation action.

For example, if a JTable and a JEditorPane both contain SearchAction references in their respective ActionMaps, keyed by "search-command" then a Toolbar button which represents "Search" with the id "search-command" will target either the JTable or the JEditor depending on which has the context. By default, the context for the TargetManager is based on the global focus owner.

This architecture provides very flexible dynamic UIs in which the actions embedded in components added to the framework can be invoked by existing menus and toolbars. One thing that I've yet to work out is a way of exposing the available ActionMap held actions to the ActionManager. For example, selection could drive ActionManager context such that the selected item would expose the actions that are available so that new presentation actions could be added to the toolbar and existing actions could be removed or disabled. None of this would be configurable in XML. This should all happen automatically.

If this sounds complicated, I hope to write a blog entry which will illustrate the concept of targetable actions with some code. Now I'm committed to write a blog ;-)

I don't have an articles to reference on state management. I'm just making this up.

--Mark

jtr
Offline
Joined: 2003-06-10

> I hate to be a party pooper, but this seems way more
> complicated than just using the AbstractAction and
> related stuff in swing? Why is having an XML
> configuration file always equated with time saving
> and ease-of-use? Using this, developers have yet
> another thing to learn. I never found the action
> stuff in swing very complicated, so what is the
> motivation for this?

I agree. While I would definately use this XML action definition as
part of a larger XML UI framework, I wouldn't use it stand alone. I'd prefer
to use the analog of this, but code-based. Perhaps as simple as an object I
could extend and provide accessor methods for getting at the attributes (template pattern).

I've seen this in a few places... I think the last one I noticed was
onjava.com's, RelativeLayout. Why would I use XML to describe a layout? It's
and extra set of of things for me to learn to use and maintain later, for
relatively little benefit. But again, as part of a larger XML framework, I'd
use it (or at least consider it).

Hey, maybe we should consider creating a Swing-oriented XML framework with these
sort of features!

nas
Offline
Joined: 2003-07-11

I have completed developing Node API for my application, was starting to write Popup Menu Builder Factories, and luckly saw your framework.

I have decided to use your framework for my application. It fits well in my application ( and every where I guess).
I have an issue which I am figuring out how to do but i could'nt get the right approach. Lemme explain the scenario ,

I am talking about Popups on Tree Nodes. These popups are highly dependednt on state of the node as well as the modules installed in the application.
For example if module A is installed then show ax, ay, az in Popup menu with corresponding methods in ActionHandler class.
like wise if module A as well as B is installed show ax, ay, az, bx ,bh etc with corresponding methods in ActionHandler class. Now Actionhandler class should have all possible methods.

Requirment is unless the module in installed we don't have access to its class files. So if I write my Action Handler class with all possible action handling methods, it would'nt compile/execute if some of the modules are not installed.
Probable solution in my mind is to have the Action Handler class to be dependent on an xml file which specifies what classes to load and execute. Its compilcated i know, but fetches an application great flexibility. There is no (less) coupling between modules.

I am not sure if that is the right approach, it might be an overkill. I need to know that.
If you can suggest me a way to implement the above issue, it would be great.

Message was edited by: nas

Mark Davidson
Offline
Joined: 2006-02-17

>
> What's missing (or maybe I just overlooked it) is
> support to handle enabling/disabling of actions. Any
> suggestions where to do it and how to automat it?

This article was pulled from a larger article which discussed application state management and the effect on ui controls like enabled and selected. Since we felt that the state management part of the article muddied the message about the action framework, it was pulled from this article but will probably appear in it's own article.

In the meantime, the ActionManager has a couple of methods for enabling/disabling actions and setting the selected state of toggle actions. See the setSelected(), setEnabled() methods in the ActionManager javadoc (http://www.javadesktop.org/articles/actions/api/com/sun/jaf/ui/ActionMan...)

For an example of how they are used in a state management mechanism, take a look at the inner class "State" in the ActionDemo.java. Specifically, the StateListener will reconfigure the UI controls based on the state of the application.

maximilianh
Offline
Joined: 2006-02-17

I think this is something like a bug in the class UIFactory. It does not make sense that all menu entries are created with state=false.

/**
* Helper method to add a checkbox menu item
*/
private JCheckBoxMenuItem createCheckBoxMenuItem(StateChangeAction a) {
return createCheckBoxMenuItem(a, false);
}

It should probably be:

return createCheckBoxMenuItem(a, a.isSelected());

Mark Davidson
Offline
Joined: 2006-02-17

Hi Max,

You may want to take a look at JDNC: https://jdnc.dev.java.net. The action framework within the JDNC project is based on this one and contains a lot of fixes and additional features.

> I think this is something like a bug in the class
> UIFactory. It does not make sense that all menu
> entries are created with state=false.

[snip]

> It should probably be:
>
> return createCheckBoxMenuItem(a, a.isSelected());

This bug was fixed in JDNC.

--Mark

Mark Davidson
Offline
Joined: 2006-02-17

>
> When I understand that right, I could make xml
> configurations for different users, lets say
> depending on their experience level which are
> retrieved from a server when the application starts,
> sounds great!

Precisely! You could imagine a scenario in which you provide multiple xml files which represent different configurations for different users. Possibly by adding/removing different actions within the action-lists. When a user identifies himself to the server, the user preferences could indicate which "resource" file to deliver to the Web Started application.

Anonymous

> Precisely! You could imagine a scenario in which you
> provide multiple xml files which represent different
> configurations for different users. Possibly by
> adding/removing different actions within the
> action-lists. When a user identifies himself to the
> server, the user preferences could indicate which
> "resource" file to deliver to the Web Started
> application.

This is cool, you saved my day! Exactly that's what I need currently. This will save me a lot of work ;)

maximilianh
Offline
Joined: 2006-02-17

Hi,
how do you guys use undoable actions together with the actions framework? I mean, I will sooner or later end up with Action-controller-methods that simply instantiate new action objects and add them to the action-list of the action-manager... I'm not sure if this makes Actions really simpler to use.
Max

maximilianh
Offline
Joined: 2006-02-17

I'm supposed to extend the UIFactory by overwriting the createXXX-methods. Ok...hmmm...just how should I extend a singleton in Java? Can anyone give me a hint, since the constructor of UIFactory is protected and I don't know how to derive a class from UIFactory. It works, obvious, as one of the screenshots is showing an application with a status bar...

Max

Mark Davidson
Offline
Joined: 2006-02-17

> I'm supposed to extend the UIFactory by overwriting
> the createXXX-methods. Ok...hmmm...just how should I
> extend a singleton in Java? Can anyone give me a
> hint, since the constructor of UIFactory is protected
> and I don't know how to derive a class from
> UIFactory.

I can't remember if the version of UIFactory on the article still has a private constructor. If it is then make it protected.

Then you can subclass UIFactory and override the protected configure methods:
[code]
public class MyUIFactory extends UIFactory {
protected void configureButton() {
super.configureButton(...)
// custom button config
}
}
[/code]
Then somewhere in your application initializtion sequence before you call UIFactory.getInstance() add this line:
[code]
// set the ui factory
UIFactory.setInstance(new MyUIFactory());
...
// use the ui factory
UIFactory factory = UIFactory.getInstance();
[/code]
Hope this helps.

--Mark

KeithFrohn
Offline
Joined: 2006-02-17

I am a Mac user but I like to create applications for multiple platforms. The common shortcut key on Windows is Ctrl. But on a Mac it is the command key (the clover-like symbol). In the past I used the java.awt.Toolkit method: getMenuShortcutKeyMask(). But when defining the open action accelerator, the xml action framework forces me to choose between "control O" for Windows or "meta O" for a Mac. Is there any way around this? Are there any plans to add a custom mask descriptor such as "shortcut O"?

zander
Offline
Joined: 2003-06-13

> I am a Mac user but I like to create applications for
> multiple platforms. The common shortcut key on
> Windows is Ctrl. But on a Mac it is the command key
> (the clover-like symbol). In the past I used the
> java.awt.Toolkit method: getMenuShortcutKeyMask().
> But when defining the open action accelerator, the
> e xml action framework forces me to choose between
> "control O" for Windows or "meta O" for a Mac. Is
> there any way around this? Are there any plans to
> add a custom mask descriptor such as "shortcut O"?

Would it be an option to auto-replace the 'control' keyword in the string with 'meta' when it is running on the mac?
I like this option better since the many windows (and linux) minded developers will not start typing 'shortcut' all of a sudden..

I'm not yet sure on how to do so, but I would like to hear if its an viable option for you.

Cheers!

augusto
Offline
Joined: 2003-06-11

Mark, now that JDNC is "released" is there any documentation reflecting the latest and greatest on the action framework?

mmenon
Offline
Joined: 2003-09-02

Hi Mark,
Let me congratulate you on ur wonderful architecture. I Have used the action framework in our application. I have a wierd problem. I dont think its to do with the action framework. But U could just confirm my belief.Also if you could suggest a solution
Our Client application is complex combination of applets and DHTML..The reason to have this complexity is the migration we had to do from DHTML to Applets.
Assume my client is divided in to 4 frames..
Top frame - Menu Applet
Left frame - HTML page Right Frame - Applet
Bottom Frame - Status Bar Applet..
The Menu applet contains the Main menu and the Tool bar..
also the Top frame and left Frame.. has contextual menus.. Which are contained in the Top frame but are shown on the HTML pages..
THe problem we face is when the Popup Menu shows up.. it doesnt absorb the click and in the process does not fire the event.
I have modified the code to use.. small icons with text, Large icons.. mouse over icons..etc. If any body ones requires the code let me know..
Regards
Manoj

KeithFrohn
Offline
Joined: 2006-02-17

I love the design but I noticed one problem in ActionDemo2. On initial load, the "history-command" button on the toolbar is selected but the corresponding items in the menu bar and popup menu are not selected. Has anyone else noticed this? Is there a bug in the ActionManager?

Mark Davidson
Offline
Joined: 2006-02-17

> I love the design but I noticed one problem in
> ActionDemo2. On initial load, the "history-command"
> button on the toolbar is selected but the
> corresponding items in the menu bar and popup menu
> are not selected. Has anyone else noticed this? Is
> there a bug in the ActionManager?

The problem is in UIFactory. initActions in ActionDemo2 and ActionDemo3 will set the selected state of the "history-command" to true. The toggle button created in the UIFactory.createToggleButton will honor the selection state of the action but createCheckBoxMenuItem and createRadioButtonMenuItem will not.

The solution is to change setSelected(selected) to setSelected(a.isSelected()).

The two private create..MenuItem methods with the selected argument should probably be removed.

Thanks for finding this bug. I've fixed the action article and the same classes in JDNC. Perhaps I will ship an update to ActionManager/UIFactory with these fixes.

svenmeier
Offline
Joined: 2003-09-05

I see the following problems with this framework:

- it doesn't offer compile time safety
- the xml configuration is a global variables space, it doesn't support development of components
- how can the same action be used in different contexts, e.g. the 'close'-action on multiple frames?
- your ActionController in your demo is a maintenance nightmare, I hope that newbies don't see this code

Recapitulating your framework hides many great features of Swing with a blur of non object-oriented code (looks like VB) and XML.

Sven

snark
Offline
Joined: 2006-02-17

everything works nice, but so far I haven't found a way of sharing a single handler method among several actions.

you can register different actions with the same callback method name, but then you will have no context information to differentiate between them when the method is called.

jasonberry
Offline
Joined: 2009-04-04

I like the utility. Thanks for publishing it. I have a couple of questions.

1. The small icon attribute is not being used for menuitems in my application or in the demo. Is that how it is supposed to work?
2. In most GUI toolkits if you have a menu that has menuitems with and without icons, the text for the menitems without icons is indented. That way all the text is aligned.
3. Do you plan on enhancing this in new versions. Internalization support via properties files as discussed would be my main concern.

Gracias,
Jason

alvarosmr
Offline
Joined: 2004-01-03

I have the same questions that you jasonberry.

Have you resolved them?

Gracias,

Alvaro

Anonymous

Hi there,

the article is great.
but how is it possible, to set a menuitem visible or unvisible.

greetings, frank

uncle_alice
Offline
Joined: 2003-06-16

In your architecture, groups of mutually exclusive actions (like the text alignment actions) have to be defined in the config file. There's nothing to prevent someone from leaving out one or more actions, or from putting several totally unrelated actions together in one group. It seems to me there should be a way to deal with the whole mutex group as if it were a single action. Then you could put a single entry, like "text-align-group", in the toolbar specification, and the ActionManager and UIFactory would automatically create however many JToggleButtons it needed (or, if there were too many actions in the group, it might create a JComboBox instead).

I've created my own action architecture, in which the action properties, menus and toolbars are all specified in a config file, but I haven't come up with a graceful solution to this problem yet. One thing I have discovered, though, is that you don't need to use ButtonGroups once your Actions become selected-aware. Here's what I'm using to handle mutex selection:
[pre]package javapad.action;

import java.util.HashMap;
import java.util.Map;

/**
* An action that represents one of two or more
* mutually-exclusive states. This will typically be
* used to construct radio buttons.
*/
public abstract class MutexAction extends ToggleAction
{
private static Map groups = new HashMap();

public MutexAction(String actionName)
{
super(actionName);
}

/**
* Set the selection status of the action. If the
* action is being selected, this will also unselect
* the previously selected action.
*/
public boolean setSelected(boolean newValue)
{
if (super.setSelected(newValue))
{
Class key = getClass();
MutexAction current = (MutexAction)groups.get(key);
if (current != null)
{
current.setSelected(false);
}
groups.put(key, this);
return true;
}
return false;
}
}[/pre]
That's much nicer than ButtonGroups, IMO.

max333
Offline
Joined: 2004-02-13

well, it looks great but the sample ActionDemo2 doesn't work at my jdk1.4.1 (win)

the error happens in the StateChangeAction.class (setSelected), when i push a button at the toolbar (adjust button)

Exception occurred during event dispatching:
java.lang.NoSuchMethodError
at com.sun.jaf.ui.StateChangeAction.setSelected(StateChangeAction.java:78)
at com.sun.jaf.ui.StateChangeAction.itemStateChanged(StateChangeAction.java:110)
at javax.swing.AbstractButton.fireItemStateChanged(Unknown Source)
at javax.swing.AbstractButton$ForwardItemEvents.itemStateChanged(Unknown Source)
at javax.swing.DefaultButtonModel.fireItemStateChanged(Unknown Source)

can someone help me?

thanx Jens

Anonymous

How do you specify from you code to switch between icon and smicon?

rtalkov
Offline
Joined: 2006-02-17

how about expanding loadActions to handle internationalization the same way ResourceBundle handles it.
so ActionManager.loadActions ("com.appworx.gui.screen1.xml") would look for screen1_en_US.xml, ...

zander
Offline
Joined: 2003-06-13

> how about expanding loadActions to handle
> internationalization the same way ResourceBundle handles it.
> so ActionManager.loadActions ("com.appworx.gui.screen1.xml") would look for screen1_en_US.xml, ...

Hmm, that would mean to duplicate a lot of text; but it gave me another idea.
Instead of
[code]
name="New"
mnemonic="N"
smicon="/toolbarButtonGraphics/general/New16.gif"
icon="/toolbarButtonGraphics/general/New24.gif"
accel="control N"
desc="Create a new object"/>
[/code]
you could do this:
[code]
name="New"
mnemonic="N"
smicon="/toolbarButtonGraphics/general/New16.gif"
icon="/toolbarButtonGraphics/general/New24.gif"
accel="control N"
desc="Create a new object">
name="Nieuw"
mnemonic="N"
desc="Maak een nieuw object"/>

[/code]

When no language is given the normal ones are used; when the language is set to 'nl' the translations are used.
Quite simple actually.

davetron5000
Offline
Joined: 2003-06-10

I hate to be a party pooper, but this seems way more complicated than just using the AbstractAction and related stuff in swing? Why is having an XML configuration file always equated with time saving and ease-of-use? Using this, developers have yet another thing to learn. I never found the action stuff in swing very complicated, so what is the motivation for this?

Mark Davidson
Offline
Joined: 2006-02-17

> I hate to be a party pooper, but this seems way more
> complicated than just using the AbstractAction and
> related stuff in swing?
>
> I never found the action
> stuff in swing very complicated, so what is the
> motivation for this?

There are a lot of people who find Actions to be complicated. Many developers don't use actions at all. Actions are pretty generic and I'm sure you have some sort of framework that manages all the actions, callbacks, enabled state,.... This is just an example of a such a framework but rather than create individual Action subclasses, I'm using a configuration file and the Actions are generated by a factory.

The objective in developing this framework was to provide a simple mechanism for creating toolbars, menus and popup menus that uses the Swing actions but insulates the developer from the nitty gritty details of creating, managing and instantiating these action based widgets.

This framework also extends the Swing Action concept by introducing a mechanism for Toggle (two state) actions and grouped (mutually exclusive) actions that currently aren't available in Swing.

> Why is having an XML
> configuration file always equated with time saving
> and ease-of-use? Using this, developers have yet
> another thing to learn.

True. Developers will have to learn the schema for describing actions using this framework. However, the schema focuses on the presentation aspects of the actions - attributes and its spacial relation to other actions - so that you can potentially hand this off to a usability expert/ui designer to set the descriptions, mnemonics, accellerators, icons and placement and let the Java developer focus on the semantics. The only thing the UI desiger and the Java developer have to agree upon is the values of the "id" attributes. XML is good at hiding complexity and allows you to focus on the specifics of your presentation. Configuring an XML file is also easier to learn than Java programming so this type of task could be handed off to UI experts who aren't necessarily Java programmers.

There are many benefits for having the presentation of an application separated from the semantics of an application. For one, you can go into the XML file and reorganize the menu layout, descriptions, mnemonics and icons without having to recompile. Also, this framework makes it easy to create arbitrary nested sub-menus. This is a real hassle using the API but simple in this framework.

As a little experiment, copy the XML-actions.jar and the jlfgr-1.0.jar and the actions-demo.xml files to a separate directory.

The following class represents the minimum amount of code required to present a frame with a menu bar and a toolbar:

[code]
import java.awt.BorderLayout;
import java.io.File;
import java.net.URL;

import javax.swing.*;

import com.sun.jaf.ui.ActionManager;
import com.sun.jaf.ui.UIFactory;

public class Demo {

public static void main(String[] args) {
if (args.length < 1) {
return;
}

// Parse xml actions file.
try {
URL url = null;
ActionManager manager = ActionManager.getInstance();

url = Demo.class.getResource(args[0]);
if (url == null) {
url = new File(args[0]).toURL();
}
manager.loadActions(url);

} catch (Exception ex) {
System.out.println("ERROR: " + ex.getMessage());
return;
}

// Build UI.
UIFactory factory = UIFactory.getInstance();

JFrame frame = new JFrame(args[0]);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JMenuBar menubar = factory.createMenuBar("main-menu");
if (menubar != null) {
frame.setJMenuBar(menubar);
}

JToolBar toolbar = factory.createToolBar("main-toolbar");
if (toolbar != null) {
frame.getContentPane().add(toolbar, BorderLayout.NORTH);
}

frame.pack();
frame.setVisible(true);
}
}
[/code]

Compile Demo.java with xml-actions.jar in your classpath.

Run the actions-demo.xml with the following command:

[code]
$ java -cp xml-actions.jar:jlfgr-1_0.jar:. Demo action-demo.xml
[/code]

You should get a menu and a toolbar in a frame.

Now go into the main menu and create lists of lists to get a multi level hierarchical menu. The minimum requirement is that all action/action-list elements should have an id. As an non-sensical example, copy the "file-menu" up to the "empty" element and paste it a few times. Then close the action-list elements. For example:

[code]

































...
[/code]

When you run the configuration, you will get a warning about duplicate ids but the demo should still run (make the "file-menu" ids unique to avoid this warning). Under the File menu, you should get a sub-menu which is nested 6 levels. Constructing a similarly nested menu system is tedious using the API.

Personally, I find this framework to be a time saver. If you don't find that it will suite your needs then you don't have to use it. This will not be part of the core Swing APIs.

michaelbushe
Offline
Joined: 2003-06-19

Can Easy Actions be made an open source project? I've got lots of extensions I'd like to add! :-)

Michael

Mark Davidson
Offline
Joined: 2006-02-17

> Can Easy Actions be made an open source project?
> I've got lots of extensions I'd like to add! :-)
>
> Michael

Hi Michael,

The Actions framework is part of the JDNC project and we are considering starting it as the first component to open source. We've extended it a lot since the first article to include some declarative action semantics.

Didn't I meet you at JavaOne? Desktop pod? If that was you then I demonstated some of the action semantics to you.

--Mark

kleopatra
Offline
Joined: 2003-06-11

Nice article :-)

What's missing (or maybe I just overlooked it) is support to handle enabling/disabling of actions. Any suggestions where to do it and how to automat it?

Greetings
Jeanette

augusto
Offline
Joined: 2003-06-11

Jeannete;

It's in the javadocs of action manager.

http://www.javadesktop.org/articles/actions/api/com/sun/jaf/ui/ActionMan...

-------------------

ActionManager manager = ActionManager.getInstance();
// Load an action-set XML document

manager.loadActions(new URL("my-actions.xml));
// Register a callback for a particular Action

manager.registerCallback("new-action", actionHandler, "handleNewCommand");

[b]
// Change the state of the action:
manager.setEnabled("new-action", newState);
[/b]

zander
Offline
Joined: 2003-06-13

The framework is missing some features you might want to ponder over..
The XML proposal states that the GUI name and mnemonic are in that external file; this makes it almost impossible to translate it using resource bundles.

seperators?

defaults -- you don't want to specify 'save' for each application again, since then you will end up with different icons etc.

merging -- an application framework can have a set of defaults in the file menu and a pre-defined place where your file-menu entries are placed. This means you can have 2 files creating 1 menu.

What happens when I don't have an action-callback registered? It should mean that no GUI entry is created if you want to make this extendable :)

All these ideas are taken from the way KDE does things; as a wise man ones said: better to skillfully steal then to badly-create.

Mark Davidson
Offline
Joined: 2006-02-17

> The framework is missing some features you might want
> to ponder over..
> The XML proposal states that the GUI name and
> mnemonic are in that external file; this makes it
> almost impossible to translate it using resource
> bundles.

I agree. I suppose that a more i18n friendly architecture would use the action attributes in the xml "resource" file as keys into a resource file. That additional plumbing is left as an exercise to the reader.

In the meantime, you could provide multiple xml documents which represent other locales. You can append them with a locale id and retrieve them based on on the current Java localization support.

>
> seperators?

All paths represent URL/URIs so they should be platform independent.

>
> defaults -- you don't want to specify 'save' for each
> application again, since then you will end up with
> different icons etc.
>
> merging -- an application framework can have a set of
> defaults in the file menu and a pre-defined place
> where your file-menu entries are placed. This means
> you can have 2 files creating 1 menu.

There are already provisions for this using XML nomemclature. When I origininally developed the article, the actions-demo.xml file was broken into two file: one with core actions and action layouts and the other file was application specific.

The "core" actions looked like this:
[code]

name="File"
mnemonic="F"
desc="File Operations"/>

name="New"
mnemonic="N"
smicon="/toolbarButtonGraphics/general/New16.gif"
icon="/toolbarButtonGraphics/general/New24.gif"
accel="control N"
desc="Create a new object"/>
[/code]
And the "application" xml would include the core xml as a general entity (sort of like an include file). You can build your application specific elements by referencing the id tags in the core file:
[code]

ENTITY core-actions SYSTEM "demo/resources/actions-core.xml"
]>

&core-actions;



....
[/code]
You can create default actions and action-lists and share them across applications. To maintain a consistent set of mnemonics, accels, descriptions and icons. Furthermore, you can overload the attributes in your application xml if you want to resolve menu mnemonic conflicts or customize the attributes for a specific application:
[code]

[/code]
In this example, the desc has been changed. One limitation about this approach is that the default ActionManager is a singleton and maintains a single list of Actions. When the description of the action changes for an id, then all instances of the action will change. The workaround is to define a new ActionManager for a different context.

>
> What happens when I don't have an action-callback
> registered? It should mean that no GUI entry is
> created if you want to make this extendable :)

You describe the first: if an Action doesn't have a registered callback then it shouldn't have a corresponding UI component. In order for that to work correctly, the action registration should take place after the actions xml document has been parsed but before the UI has been constructed. The ActionManager can keep track of the action/callback bindings so it could return action-lists that don't contain unregistered actions to the UIFactory.

The second issue is that registered actions that do not have a corresponding reference in an action-list should not be created. This is probably an implementation issue in JDNC since we want to have a generic framework which would support printing and other file operations. If you dont' want these features (like printing) then the framework should not have to create the actions and the rest of it to support this.

zander
Offline
Joined: 2003-06-13

> > The XML proposal states that the GUI name and
> > mnemonic are in that external file; this makes it
> > almost impossible to translate it using resource
> > bundles.
>
> I agree. I suppose that a more i18n friendly
> architecture would use the action attributes in the
> xml "resource" file as keys into a resource file.

That won't make the nicest of translations, since a translator will not appriciate translating 'file_save' to 'Opslaan" very much. But since there is not a standard i18n implementation, yes this is a solution.

> > seperators?
>
> All paths represent URL/URIs so they should be
> platform independent.

Hihi, I meant the graphical ones. The one you find between the open and the quit menu entry. I.e. a horizontal line.

> > merging -- an application framework can have a set of
> > defaults in the file menu and a pre-defined place
> > where your file-menu entries are placed. This means
> > you can have 2 files creating 1 menu.
>
> There are already provisions for this using XML
> nomemclature. When I origininally developed the
> article, the actions-demo.xml file was broken into
> two file: one with core actions and action layouts
> and the other file was application specific.

The solution I wrote a couple of months back had the thing you put in the first XML file in source code; this solves the problem of i18n in the same way the rest of your app does that.
This also solves things like defaults; you just hard code the stuff for 'save' and 'quit' in your singleton to be sure every application reuses that.

Consider these:
[code]
actionFactory.addSpecialAction("file_save", this, "fileSaveSlot");
actionFactory.addAction("file_saveas", targetObject, "targetMethod", i18n("Save As..."),"toolbarButtonGraphics.general.SaveAs");
[/code]
Two actions that are called from my code to replace what you have in the XML.

> One limitation about this approach is that the default
> ActionManager is a singleton and maintains a single
> list of Actions.
Why would you want that? At least make it a token-based singleton so you can have one per top-level-window.

> > What happens when I don't have an action-callback
> > registered? It should mean that no GUI entry is
> > created if you want to make this extendable :)
>
> You describe the first: if an Action doesn't have a
> registered callback then it shouldn't have a
> corresponding UI component. In order for that to work
> correctly, the action registration should take place
> after the actions xml document has been parsed but
> before the UI has been constructed.

Thats implemetation specific; if would not be too hard to allow registration to preceed the reading of the XML.
Then again; its probably just as easy to make the actionManager have a 'getInstance' method that takes the xml file as argument, circumventing this whole issue.

> The ActionManager
> can keep track of the action/callback bindings so it
> could return action-lists that don't contain
> unregistered actions to the UIFactory.
Right.

> The second issue is that registered actions that do
> not have a corresponding reference in an action-list
> should not be created. This is probably an
> implementation issue in JDNC since we want to have a
> generic framework which would support printing and
> other file operations. If you dont' want these
> features (like printing) then the framework should
> not have to create the actions and the rest of it to
> support this.
I don't understand your pointer to the printing things; if a menu-entry is not specified in the XML, then its not generated. This confuses me..

gerald_bauer
Offline
Joined: 2006-02-17

Hi,

I have written up a story about Mark's article titled "Roll-Your-Own Mini XUL Motor For Swing".

Read the full story @ http://sourceforge.net/mailarchive/forum.php?thread_id=2559388&forum_id=...

Here's the XUL News Wire story kick off:

[i]Mark Davidson wrote a tech paper titled "An Easy Architecture for Managing Actions: Simplifying the Creation of Tool Bars and Menus" that shows you how to reinvent the toothbrush by rolling your own mini XUL motor using the Swing UI toolkit.

Mark kicks off his XUL testimonial as follows:
[/i]

Enjoy.

- Gerald

PS: To find out more about XUL (XML UI Language), check out the XUL Alliance site @ http://xul.sourceforge.net sporting more than a dozen free, open-source XUL motors/browser/runtimes for Java such as XWT, Luxor, Swix, Thinlet, JellySWT, and many more.

Anonymous

It's a great reading.

When I understand that right, I could make xml configurations for different users, lets say depending on their experience level which are retrieved from a server when the application starts, sounds great!

augusto
Offline
Joined: 2003-06-11

This is great stuff !

I created a similar system, but with resource bundles and it's not XML oriented. For example a toolbar would look like this;

MainApplication.Toolbar.layout=SaveAction OpenAction | PrintAction
MainApplication.SaveAction.type=invokeMethod
MainApplication.SaveAction.method=doSave()

etc.

One thing I can do in mine, which I don't know this arch lets me, is to "register" a component in some context, and if the named component is included in the toolbar's layout, it is added. This is good for example in a JSpinner or a JCombobox which resides in the toolbar. Can this be done with this architecture.

Also, what is the license for this jar file?

Thanks.

Mark Davidson
Offline
Joined: 2006-02-17

I'm glad you enjoyed the article and the architecture. I hope find it to be useful.

>
> One thing I can do in mine, which I don't know this
> arch lets me, is to "register" a component in some
> context, and if the named component is included in
> the toolbar's layout, it is added. This is good for
> example in a JSpinner or a JCombobox which resides in
> the toolbar. Can this be done with this
> architecture.

This action architecture is much more generic than that. The specification of an action-list element represents a list of actions. You can create hierarchical action containers (like multi-level menus) by creating lists of lists. The actual action container that will be created is dictated by passing the action-list to the factory method on the UIFactory. You can subclass the UIFactory class and overload the configure methods to customized the components.

Currently, only buttons, toggle buttons and grouped toggle buttons are supported in the toolbar (and the analogous menu components within a menu). We currently don't support combo boxes or any other components in the toolbar. The javax.swing.Action model doesn't really apply to these other components. I would suggest that you can provide customization to the toolbar yourself by adding these components to the toolbar returned from the UIFactory.

The Actions architecture is still evolving. The current version in JDNC allows for the specification of a callback registration mechanism (that creates a dynamic proxy listener) and support for calling http POST on urls.

>
> Also, what is the license for this jar file

The terms of the BSD+ license is outlined in the header of each source file. You can redistribute the jar file but this is not a Sun supported product - other than responses in this forum ;-)

augusto
Offline
Joined: 2003-06-11

> I would suggest that you can provide customization to the toolbar yourself by adding these components to the toolbar returned from the UIFactory.

I see, I understand you want to keep it action oriented, which is good, but I'll have to find a way to add other types of UI components, plus customized components. That's why i would pass a list of named components to my equivalent of the factory.

Not only that, but what if you want to pass a customized menu? For example, I have a menu from the menu bar that dynamically updates its contents before being popped up each time. In this case, I would need to either;

1) Instantiate it myself and somehow register
2) Have an architecture where you give it a tag to include a component by classname, and the factory instantiates and adds it.

I'll see how I can add this after the factory returns, the downside of this is I don't want to append stuff to the toolbar so i would like the order of components be determined by the xml config file.

So, what I need is something extra for non Action items that can plug in to this nice architecture, since it's not too uncommon to have non action components in a toolbar, or customized menus in a menubar (or popup window).

megadix
Offline
Joined: 2003-09-03

I was about to develop something really similar, but you did it before me ! I must admit that this fits really well with my idea of action managing...cool job guys !

cat
Offline
Joined: 2003-06-14

For a project of mine I have developed a framework more complex by also involving generic UI elements (kind of like the XUL or UIML) some years ago (as early as 2000-2001 !:)
And I have brought a modularization concept kind of like the one from the SwingSuite (that some of you have also contributed if I remember right?) into another major Java project (so that the individual teams would stick to common patterns and interfaces rather then each reinventing the wheel and creating a big mess ;-)

However, that generic action model in your demo app is also a great thing and I would like to see it adopted somehow (maybe even like JNLP which gets used and accepted here and there even outside Sun...) and will definetely try to use it where I can (in future projects or my beans and own projects)

I wish, the app would in some portions WORK actually, at least some actions like the EXIT action ?;)
Or is that a BUG ???

Mark Davidson
Offline
Joined: 2006-02-17

>
> I wish, the app would in some portions WORK actually,
> at least some actions like the EXIT action ?;)
> Or is that a BUG ???

I had Java Web Start deployment in mind when I developed the demo. I wanted to avoid all operations which would require signing the jar file to step outside of the Java security sandbox - which is why the file open/save, exit and clipboard are disabled.