Frank,
Thanks or your input, this is really appreciated and I would wish we had more contributions like this. Please send me your code and I will integrate it in the next or a following releases.

I would like to keep the custom attribute tags (like class, factorymethod, etc.) to an absolute minimum.

Maybe a single attribute name like "instance" would do. I.e.
   <tagname=".." attr=".." instance="mypack.myclass"/>
and getInstance() is used if this this method exists otherwise the default constructor is called.

Wolf


Frank Mei�ner wrote:

Hello Wolf,

I understand it the way you explained it.

A couple of month ago I worked on an application heavliy using Action objects. Some actions did have their own status, e.g. linked with some JTree or the like. First, we had a lot of attributes, some anonymous inner classes, some external classes. Then we decided to create the menu items, toolbar buttons and the like from a Collection holding Action items. These actions could merely act on themself: they registered on some event notifier (to get notified if the user clicks on a table row, a tree item, ...). If the action was invoked, it was able to handle all of the business logic on themself. These actions where not lightweight, they did not only forward their wish to some object which does the work. They kept the business logic for themself, where it belonged.

E.g. the action PayBookings registered itself on a JTable containing a list of bookigs. If the user selects at least one, the action enables itself. If the user clicks on the button (menu item, ...) which is associated with the action, it collects the selected bookings, wraps them in some even object and fires the event. Done. No further action was necessary. This approach enabled us to keep the business logic very concentrated in the actions. These actions where reasonable small, easy to understand and to maintain. If we had to keep all the methods in some outer class (actually, this was our first approach), this outer class would grow beyond maintainabilty. The outer class was about 3500 lines of code when we switched to the action-approach -- and nobody liked to touch it :-(. Then it was about 500 lines of code because we removed nearly all code to Action classes... Now it is easy to remove or add new actions and to get rid of unused functions -- even without the help of some sophisticated IDE.

So, the nested class approach works good for some smaller designs. If you want code isolation or have a lot of actions with sophisticated busines logic (maybe likely to change), this may not work very well.

Swixml would enable the design to get completly rid of creating the action objects on ourself. Of course, some thinking has to be done for the init of the actions...

Let me show the code I wrote recently with the "unimproved" swixml:

public class SwixmlTest extends SwingEngine {
public test1Action = new Test1Action();
public test2Action = new Test2Action();
public test3Action = new Test3Action();
public test4Action = new Test4Action();
public test5Action = new Test5Action();
public test6Action = new Test6Action();
public test7Action = new Test7Action();
public test8Action = new Test8Action();
public test9Action = new Test9Action();
public test10Action = new Test10Action();
public test11Action = new Test11Action();
public test12Action = new Test12Action();
public test13Action = new Test13Action();
public test14Action = new Test14Action();

private SwixmlTest() {
  try {

  render(SwixmlTest.class.getResource(
    "/xml/swixml-test.xml")).setVisible(true);
...

I do not know which actions are actually used in swixml-test.xml -- and I do not care. So, why should I create the variables and not let swixml create exactly the actions I mention in the xml? You easily see the code above is reduced to this:

private SwixmlTest() {
  try {

  render(SwixmlTest.class.getResource(
    "/xml/swixml-test.xml")).setVisible(true);
...


I hope I shed some light on the topic. And I hope I showed I'm no swing-newbie ;-)

Frank

Wolf Paulus wrote:

Frank,
While there is nothing wrong with your approach, there was a particular reason why we did it differently. I guess the missing documentation is to blame. However, let me try to explain how we pictures the link between the GUI Widgets and the actual evenbthandlers.

All the SwiXml Tags representing Swing objects that inherit from Abstract Button (like JButton, JMenuItem, JCheckBox, etc.) accept the ActionCommand and the Action attribute.

When the Action attribute is used, the following will happen with the example for instance:


XML Code:
..
<button Text="Click" Action="Handle_Click"/>
<button id="btn2" Text="2nd Button"/>

..
Java Code:
..
public class HelloWorld extends WindowAdapter {
 private SwingEngine swix = new SwingEngine( this );  // *1*
 public JButton btn2;  // *2*

 public Action Handle_Click= new AbstractAction() {
public void actionPerformed(ActionEvent e) { System.out.println( "Click was pressed" );
        btn2.setEnable(false); //*3*
     }
   }

 private HelloWorld() {
   try {
     swix.render( "xml/HelloWorld.xml" ).setVisible( true );
   } catch (Exception e) {
     e.printStackTrace();
   }
 }

 public static void main(String[] args) {
   new HelloWorld();
 }
}

The button Tag triggers the instatiation of a JButton object. Then after the parsing and instantiation work of the whole XML document is done, EventHandlers, (in our case the _public_ Action Handle_Click is linked with the Button.

The Button does not need an ID if you don't need to refer to it later.
The example has another button (//*2*) that we want to disable if the 1st button was clicked. Therefore this button needs an ID.

If there is a _public_ Button in the class of the object that was passed into the SwingEngine at construction time (//*1*) and the button's name matches the tag's then this button gets initialized automatically during parsing as well. If you need to make your members private you will have to use the SwingEngine's find method to init those yourself.

Now here comes the benefit of during it this way. Swing programmers are used to use inner classes. The Action class used in this example is an inner class, allowing easy access to the outer class members and methods. See how easy it is to disable the 2nd button in the event handler.


When you want to use the alternative (built in) way hook up your event handlers, you need to use the ActionCommand attribute. This requires a little more java code to write but in certain situations this might be preferable over the Action attr. way. Check the sample code at http://www.swixml.org/samples/index.html for details.

Wolf








Frank Mei�ner wrote:

Hello again,

Ok, because I needed the features I mentioned, I added them for myself. Now I'm able to write swigxml-code like this:

...
<menuitem id="mi_exit" InitClass="test.actions.ExitAction" FactoryMethod="getInstance"/>
...
<button enabled="true" InitClass="test.actions.ExitAction" FactoryMethod="getInstance"/>
...

All these objects use the same instance of ExitAction. If no ExitAction is used at all, no object of this type is created (of course...).

So, this code moves swigxml a bit more to the business-logic part of the code. It allows you to switch some (maybe expensive) parts of your gui on and of. Especially if the components do create without further arguments you do not have to take care on them. Just implement them, test if they work correctly and leave it to someone else to decide if he/she wants to see them.

On the original swigxml you have to take care on the creation of the actions for yourself. You have to (correct me if I'm wrong) assign an id to every button or menu item in the xml. Then you have to write code which iterates over all of the id's you defined. If one is used (e.g. the component by getIdMap().get(id) returned a value != null), you have to create the appropriate Action and assign it to the {button, menu item, ...}. Of course, one might use a clever String for the id (like "1.test.actions.ExitAction<getInstance>") but this is not as clever as to provide the factory method :)

Just tell me what you think of it...

Frank


_______________________________________________
Forum mailing list
[email protected]
http://mars.lunarpages.com/mailman/listinfo/forum_carlsbadcubes.com






_______________________________________________
Forum mailing list
[email protected]
http://mars.lunarpages.com/mailman/listinfo/forum_carlsbadcubes.com





_______________________________________________
Forum mailing list
[email protected]
http://mars.lunarpages.com/mailman/listinfo/forum_carlsbadcubes.com






Reply via email to