Steve,

thanks for your input - and sorry I'm so late in coming back to it. 

> Here's my two cents worth:
> - If the change you suggest is made, some care would
> need to be taken to make sure that rollover behavior
> wasn't impacted.  Wouldn't this look an awful lot like
> a rollover behavior?

Maybe I was a bit inprecise in my description of the workaround: I don't
want to _add_ any focusrequests, just reverse the order of calls. So
whenever there is the sequence in the original
buttonlistener/basicbuttonui:

        if (!model.isArmed()) {
                // button not armed, should be
                model.setArmed(true);
        }
        model.setPressed(true);
        if (!b.hasFocus()) {
                b.requestFocus();
        }

I would change that to:

        if (!b.hasFocus()) {
                b.requestFocus();
        }
        if (!b.hasFocus()) return;
        if (!model.isArmed()) {
                // button not armed, should be
                model.setArmed(true);
        }
        model.setPressed(true);

Nothing in general focus handling will be changed, so I don't expect any
unconsistant behaviour with rollover, armed....

And it will solve the validation trouble for nearly any szenario (except
default button handling - but as that is unique per form it might
require special handling anyway).

The obvious drawback is that the change is required in all kinds of
buttons... (Swing Team - any volunteers?)

[snip]

> - The problem, like most problems with GUI focus
> management, stems from a difference in what is the
> correct behavior for keyboard navigation versus mouse.
> During keyboard navigation the button receives the
> focus when tabbing to it, before it can be pressed and
> indicates it has the focus.  But during mouse
> navigation the user sees the mouse pointer which, to
> the user, reflects their intent as surely as if they
> had tabbed to the button.

That's exactly my point: tabbing from a textfield with invalid data is
inhibited by InputVerifier as should when clicking with the mouse...

I attach some sample code - if anybody want's to play with it. With
normal buttons and without error message from inputVerifier the actions
are always performed. With normal buttons and error message the action
is performed or not unpredictably. The appearance of the button after
pressed is "somehow" like rollover. With changed ui the action is never
performed (after mouse clicks that is - nothing done about
keys/default). 

Greetings
Jeanette
import javax.swing.*;
import javax.swing.event.*;

import java.awt.event.*;
import java.awt.*;

import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;

/** 
 */
public class TestIPInput {

    protected JFrame frame ;
    //protected JIPInput ipInput;
    protected JTextField outField;


    public TestIPInput() {
        frame = new JFrame("TestIPInput");
        frame.addWindowListener(new WindowAdapter() {
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }
                }
                );
        frame.getContentPane().add(getMainPanel());
        frame.getContentPane().add(getButtonPanel(), BorderLayout.SOUTH);
        frame.pack();
        frame.show();
    }

    //---------------------------helper

    protected void doMessage() {
  //      Messenger.showWarning(outField, 1);
    }

    protected JComponent getMainPanel() {
        JPanel panel = new JPanel();
        //      panel.setLayout(new BorderLayout());
        //      ipInput = new JIPInput();
        //      panel.add(ipInput);
        outField = new JTextField(10);
        outField.setInputVerifier(new InputVerifier() {
                    public boolean verify(JComponent comp) {
                        JTextField field = (JTextField) comp;
                        String text = field.getText();
                        return text.length() > 3;
                    }

             /*       public boolean shouldYieldFocus(
                            final JComponent comp) {
                        boolean valid = super.shouldYieldFocus(comp);
                        if (!valid) {
                            JOptionPane.showMessageDialog(comp, "Verifier: Invalid 
input! \n",
                                    null, JOptionPane.ERROR_MESSAGE);
                            ((JTextField) comp).selectAll();
                        }
                        return valid;
                    }
               */
                }
                );
        panel.add(outField);
        return panel;
    }

    protected JComponent getButtonPanel() {
        JPanel panel = new JPanel();
        JButton button = new JButton("save");
        button.setMnemonic('s');
        button.setUI(new MyButtonUI());
        frame.getRootPane().setDefaultButton(button);
        ActionListener action = new ActionListener() {
                    public void actionPerformed(ActionEvent event) {
                        System.out.println("save performed");
                      //  doMessage();
                    }
                };
        button.addActionListener(action);
        panel.add(button);
        button = new JButton("cancel");
        action = new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("cancel action");
                    }
                };
        button.addActionListener(action);
        button.setVerifyInputWhenFocusTarget(false);
        panel.add(button);
        return panel;
    }

    //---------------------------

        public class MyButtonUI extends MetalButtonUI {
                protected BasicButtonListener createButtonListener(AbstractButton b) {
                        return new MyButtonListener(b);
                }
        }

    public class MyButtonListener extends BasicButtonListener {

                public MyButtonListener(AbstractButton b) {
                        super(b);
                }
        public void mousePressed(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e)) {
                AbstractButton b = (AbstractButton) e.getSource();
                if (b.contains(e.getX(), e.getY())) {
                    ButtonModel model = b.getModel();
                    if (!model.isEnabled()) {
                        // Disabled buttons ignore all input...
                        return;
                    }
                    if (!b.hasFocus()) {
                        b.requestFocus();
                    }
                    System.out.println("has focus" + b.hasFocus());
                    if (!b.hasFocus()) return;
                    
                    if (!model.isArmed()) {
                        // button not armed, should be
                        model.setArmed(true);
                    }
                    model.setPressed(true);
                }
            }
        }
        
     }
        

//--------------main

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

Reply via email to