I don't think that will do what is required.

What is needed is to be able to register a single ActionListener for a
container
that will receive ActionEvents from any Swing component in that container
that
can generate such an event, which would be:

- any AbstractButton (which includes JMenuItem)
- a JComboBox
- a JTextField
(and maybe others that have slipped my mind right now).

Neither the original nor the new setActionListener() do this, because they
check only
for the button cases and hence leave out JComboBox and JTextField.

The second issue is that the old code (and, as far as I can tell, the new
code) descends
too far. When it meets a JComboBox, it doesn't register a listener, but it
WILL look
inside it and find the JButton that HAPPENS to be there. This is wrong
because:

1. The JButton is not strictly part of the UI - its is an artifact of the
LAF implementation
   of JComboBox (and there is nothing to say that a given UI will use an
actual button for this).

2. The "phantom" button generates an event when the user opens the combo
popup - which is
   too early to be useful as an indicator of the combo box selection having
changed. In addition,
   of course, the button does not have an actionCommand for demux purposes.

In summary, I don't think the new version is any closer to meeting the
requirements than
the original.

Maybe setActionListener() was intended only to handle buttons/menu items.
That would be a shame,
because it rules out creating a single way to handle all action events
within a framework by
binding handlers to actionCommands rather than requiring application code to
directly add listeners
to each control.

Regards
Kim Topley


-----Original Message-----
From: Wolf Paulus [mailto:[EMAIL PROTECTED]
Sent: 25 June 2003 00:33
To: Forum@carlsbadcubes.com
Subject: Re: [Forum] setActionListener problems


Kim,
Thanks for your input. Please try this version of the SwingEngine's
setActionListener(..) method.
Let me know if it work any better for you.

Thanks
    Wolf

  /**
   * Recursively Sets an ActionListener
   * <pre>
   *  Backtracking algorithm:
   *    if al was set for a child component, its not being set for its
parent
   * </pre>.
   * @param c <code>Component</code> start component
   * @param al <code>ActionListener</code>
   */
  public boolean setActionListener( final Component c, final ActionListener
al ) {
    boolean b = false;
    if (c != null) {
      if (Container.class.isAssignableFrom( c.getClass() )) {
        final Component[] s = ( (Container) c ).getComponents();
        for (int i = 0; i < s.length; i++) {
          b = b | setActionListener( s[ i ], al );
        }
      }
      if (!b) {
        if (AbstractButton.class.isAssignableFrom( c.getClass() )) {
          ( (AbstractButton) c ).addActionListener( al );
          b = true;
        } else if (JMenu.class.isAssignableFrom( c.getClass() )) {
          final JMenu m = (JMenu) c;
          final int k = m.getItemCount();
          for (int i = 0; i < k; i++) {
            b = b | setActionListener( m.getItem( i ), al );
          }
        }
      }
    }
    return b;
  }

----- Original Message ----- 
From: "Topley, Kim" <[EMAIL PROTECTED]>
To: <Forum@carlsbadcubes.com>
Sent: Thursday, June 19, 2003 2:38 AM
Subject: [Forum] setActionListener problems


> Suppose I have a panel that contains a combo box and numerous other items
> and that
> I choose to handle events by calling setActionListener on the panel.
Suppose
> also that I
> have no alternative but to do this (because it is not possible for me to
use
> the Action attribute
> on the <combobox> tag and directly register an ActionListener on the combo
> box).
>
> Given these circumstances, I want to be able to handle the event generated
> when the combo
> selection changes, based on the ActionCommand attribute of the <combobox>
> tag. With the
> current implementation of setActionListener, this is not possible because:
>
> 1. setActionListener does not reqister an ActionListener on a JComboBox
> 2. setActionListener descends into the JComboBox and registers a listener
on
>     the JButton that it happens to contain. This means I get an event from
a
> component
>     that I know nothing about (and might, in other LAFs, not be there).
> Moreover, the event
>     happens when the combo popup opens, not when the selection is changed.
>
> As far as I can see, the implementation of setActionListener has a couple
of
> bugs in it.
> It looks to me like the following code would work better, where the
changes
> are marked
> "XX:"
>
> public void setActionListener( final Component c, final ActionListener
al )
> {
>   if (c != null) {
>     if (c instanceof AbstractButton) {
>       ((AbstractButton) c).addActionListener( al );
>       return;   // <--- XX: do not descend into this component
>     } else if (c instanceof JComboBox) { // <-- XX: start of new code
>       ((JComboBox)c).addActionListener(al);
>       return;   // <--- XX: do not descend into this component
>     }  // <-- XX: end of new code
>
>     if (c instanceof JMenu) {
>       final JMenu m = (JMenu) c;
>       final int k = m.getItemCount();
>       for (int i = 0; i < k; i++) {
>         setActionListener( m.getItem( i ), al );
>       }
>     } else if (c instanceof Container) {
>       final Component[] s = ((Container) c).getComponents();
>       for (int i = 0; i < s.length; i++) {
>         setActionListener( s[i], al );
>       }
>     }
> }
>
> Perhaps consideration should also be given to handling text fields in this
> method
> as well, since they also generate ActionEvents. Once this is done, the
> developer can
> handle all tags that have the ActionCommand attribute in a uniform manner.
>
> Regards
> Kim Topley
>
>
>
> _______________________________________________
> Forum mailing list
> Forum@carlsbadcubes.com
> http://mars.lunarpages.com/mailman/listinfo/forum_carlsbadcubes.com
>
>


_______________________________________________
Forum mailing list
Forum@carlsbadcubes.com
http://mars.lunarpages.com/mailman/listinfo/forum_carlsbadcubes.com

Reply via email to