< prev index next >

src/java.desktop/share/classes/java/beans/EventHandler.java

Print this page

        

*** 34,119 **** import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; /** ! * The <code>EventHandler</code> class provides * support for dynamically generating event listeners whose methods * execute a simple statement involving an incoming event object * and a target object. * <p> ! * The <code>EventHandler</code> class is intended to be used by interactive tools, such as * application builders, that allow developers to make connections between * beans. Typically connections are made from a user interface bean * (the event <em>source</em>) * to an application logic bean (the <em>target</em>). The most effective * connections of this kind isolate the application logic from the user ! * interface. For example, the <code>EventHandler</code> for a ! * connection from a <code>JCheckBox</code> to a method * that accepts a boolean value can deal with extracting the state * of the check box and passing it directly to the method so that * the method is isolated from the user interface layer. * <p> * Inner classes are another, more general way to handle events from ! * user interfaces. The <code>EventHandler</code> class * handles only a subset of what is possible using inner ! * classes. However, <code>EventHandler</code> works better * with the long-term persistence scheme than inner classes. ! * Also, using <code>EventHandler</code> in large applications in * which the same interface is implemented many times can * reduce the disk and memory footprint of the application. * <p> ! * The reason that listeners created with <code>EventHandler</code> * have such a small ! * footprint is that the <code>Proxy</code> class, on which ! * the <code>EventHandler</code> relies, shares implementations * of identical * interfaces. For example, if you use ! * the <code>EventHandler</code> <code>create</code> methods to make ! * all the <code>ActionListener</code>s in an application, * all the action listeners will be instances of a single class ! * (one created by the <code>Proxy</code> class). * In general, listeners based on ! * the <code>Proxy</code> class require one listener class * to be created per <em>listener type</em> (interface), * whereas the inner class * approach requires one class to be created per <em>listener</em> * (object that implements the interface). * * <p> ! * You don't generally deal directly with <code>EventHandler</code> * instances. ! * Instead, you use one of the <code>EventHandler</code> ! * <code>create</code> methods to create * an object that implements a given listener interface. ! * This listener object uses an <code>EventHandler</code> object * behind the scenes to encapsulate information about the * event, the object to be sent a message when the event occurs, * the message (method) to be sent, and any argument * to the method. * The following section gives examples of how to create listener ! * objects using the <code>create</code> methods. * * <h2>Examples of Using EventHandler</h2> * ! * The simplest use of <code>EventHandler</code> is to install * a listener that calls a method on the target object with no arguments. ! * In the following example we create an <code>ActionListener</code> ! * that invokes the <code>toFront</code> method on an instance ! * of <code>javax.swing.JFrame</code>. * * <blockquote> *<pre> *myButton.addActionListener( * (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront")); *</pre> * </blockquote> * ! * When <code>myButton</code> is pressed, the statement ! * <code>frame.toFront()</code> will be executed. One could get * the same effect, with some additional compile-time type safety, ! * by defining a new implementation of the <code>ActionListener</code> * interface and adding an instance of it to the button: * * <blockquote> *<pre> //Equivalent code using an inner class instead of EventHandler. --- 34,119 ---- import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; /** ! * The {@code EventHandler} class provides * support for dynamically generating event listeners whose methods * execute a simple statement involving an incoming event object * and a target object. * <p> ! * The {@code EventHandler} class is intended to be used by interactive tools, such as * application builders, that allow developers to make connections between * beans. Typically connections are made from a user interface bean * (the event <em>source</em>) * to an application logic bean (the <em>target</em>). The most effective * connections of this kind isolate the application logic from the user ! * interface. For example, the {@code EventHandler} for a ! * connection from a {@code JCheckBox} to a method * that accepts a boolean value can deal with extracting the state * of the check box and passing it directly to the method so that * the method is isolated from the user interface layer. * <p> * Inner classes are another, more general way to handle events from ! * user interfaces. The {@code EventHandler} class * handles only a subset of what is possible using inner ! * classes. However, {@code EventHandler} works better * with the long-term persistence scheme than inner classes. ! * Also, using {@code EventHandler} in large applications in * which the same interface is implemented many times can * reduce the disk and memory footprint of the application. * <p> ! * The reason that listeners created with {@code EventHandler} * have such a small ! * footprint is that the {@code Proxy} class, on which ! * the {@code EventHandler} relies, shares implementations * of identical * interfaces. For example, if you use ! * the {@code EventHandler create} methods to make ! * all the {@code ActionListener}s in an application, * all the action listeners will be instances of a single class ! * (one created by the {@code Proxy} class). * In general, listeners based on ! * the {@code Proxy} class require one listener class * to be created per <em>listener type</em> (interface), * whereas the inner class * approach requires one class to be created per <em>listener</em> * (object that implements the interface). * * <p> ! * You don't generally deal directly with {@code EventHandler} * instances. ! * Instead, you use one of the {@code EventHandler} ! * {@code create} methods to create * an object that implements a given listener interface. ! * This listener object uses an {@code EventHandler} object * behind the scenes to encapsulate information about the * event, the object to be sent a message when the event occurs, * the message (method) to be sent, and any argument * to the method. * The following section gives examples of how to create listener ! * objects using the {@code create} methods. * * <h2>Examples of Using EventHandler</h2> * ! * The simplest use of {@code EventHandler} is to install * a listener that calls a method on the target object with no arguments. ! * In the following example we create an {@code ActionListener} ! * that invokes the {@code toFront} method on an instance ! * of {@code javax.swing.JFrame}. * * <blockquote> *<pre> *myButton.addActionListener( * (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront")); *</pre> * </blockquote> * ! * When {@code myButton} is pressed, the statement ! * {@code frame.toFront()} will be executed. One could get * the same effect, with some additional compile-time type safety, ! * by defining a new implementation of the {@code ActionListener} * interface and adding an instance of it to the button: * * <blockquote> *<pre> //Equivalent code using an inner class instead of EventHandler.
*** 123,138 **** * } *}); *</pre> * </blockquote> * ! * The next simplest use of <code>EventHandler</code> is * to extract a property value from the first argument * of the method in the listener interface (typically an event object) * and use it to set the value of a property in the target object. ! * In the following example we create an <code>ActionListener</code> that ! * sets the <code>nextFocusableComponent</code> property of the target * (myButton) object to the value of the "source" property of the event. * * <blockquote> *<pre> *EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source") --- 123,138 ---- * } *}); *</pre> * </blockquote> * ! * The next simplest use of {@code EventHandler} is * to extract a property value from the first argument * of the method in the listener interface (typically an event object) * and use it to set the value of a property in the target object. ! * In the following example we create an {@code ActionListener} that ! * sets the {@code nextFocusableComponent} property of the target * (myButton) object to the value of the "source" property of the event. * * <blockquote> *<pre> *EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
*** 150,162 **** * } *} *</pre> * </blockquote> * ! * It's also possible to create an <code>EventHandler</code> that * just passes the incoming event object to the target's action. ! * If the fourth <code>EventHandler.create</code> argument is * an empty string, then the event is just passed along: * * <blockquote> *<pre> *EventHandler.create(ActionListener.class, target, "doActionEvent", "") --- 150,162 ---- * } *} *</pre> * </blockquote> * ! * It's also possible to create an {@code EventHandler} that * just passes the incoming event object to the target's action. ! * If the fourth {@code EventHandler.create} argument is * an empty string, then the event is just passed along: * * <blockquote> *<pre> *EventHandler.create(ActionListener.class, target, "doActionEvent", "")
*** 174,188 **** * } *} *</pre> * </blockquote> * ! * Probably the most common use of <code>EventHandler</code> * is to extract a property value from the * <em>source</em> of the event object and set this value as * the value of a property of the target object. ! * In the following example we create an <code>ActionListener</code> that * sets the "label" property of the target * object to the value of the "text" property of the * source (the value of the "source" property) of the event. * * <blockquote> --- 174,188 ---- * } *} *</pre> * </blockquote> * ! * Probably the most common use of {@code EventHandler} * is to extract a property value from the * <em>source</em> of the event object and set this value as * the value of a property of the target object. ! * In the following example we create an {@code ActionListener} that * sets the "label" property of the target * object to the value of the "text" property of the * source (the value of the "source" property) of the event. * * <blockquote>
*** 248,268 **** * target.getA().setB(e.getC().isD()); * } *} *</pre> * <p> ! * As <code>EventHandler</code> ultimately relies on reflection to invoke * a method we recommend against targeting an overloaded method. For example, ! * if the target is an instance of the class <code>MyTarget</code> which is * defined as: * <pre> * public class MyTarget { * public void doIt(String); * public void doIt(Object); * } * </pre> ! * Then the method <code>doIt</code> is overloaded. EventHandler will invoke * the method that is appropriate based on the source. If the source is * null, then either method is appropriate and the one that is invoked is * undefined. For that reason we recommend against targeting overloaded * methods. * --- 248,268 ---- * target.getA().setB(e.getC().isD()); * } *} *</pre> * <p> ! * As {@code EventHandler} ultimately relies on reflection to invoke * a method we recommend against targeting an overloaded method. For example, ! * if the target is an instance of the class {@code MyTarget} which is * defined as: * <pre> * public class MyTarget { * public void doIt(String); * public void doIt(Object); * } * </pre> ! * Then the method {@code doIt} is overloaded. EventHandler will invoke * the method that is appropriate based on the source. If the source is * null, then either method is appropriate and the one that is invoked is * undefined. For that reason we recommend against targeting overloaded * methods. *
*** 282,307 **** private final String eventPropertyName; private final String listenerMethodName; private final AccessControlContext acc = AccessController.getContext(); /** ! * Creates a new <code>EventHandler</code> object; ! * you generally use one of the <code>create</code> methods * instead of invoking this constructor directly. Refer to * {@link java.beans.EventHandler#create(Class, Object, String, String) * the general version of create} for a complete description of ! * the <code>eventPropertyName</code> and <code>listenerMethodName</code> * parameter. * * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on * the target * @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event * @param listenerMethodName the name of the method in the listener interface that should trigger the action * ! * @throws NullPointerException if <code>target</code> is null ! * @throws NullPointerException if <code>action</code> is null * * @see EventHandler * @see #create(Class, Object, String, String, String) * @see #getTarget * @see #getAction --- 282,307 ---- private final String eventPropertyName; private final String listenerMethodName; private final AccessControlContext acc = AccessController.getContext(); /** ! * Creates a new {@code EventHandler} object; ! * you generally use one of the {@code create} methods * instead of invoking this constructor directly. Refer to * {@link java.beans.EventHandler#create(Class, Object, String, String) * the general version of create} for a complete description of ! * the {@code eventPropertyName} and {@code listenerMethodName} * parameter. * * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on * the target * @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event * @param listenerMethodName the name of the method in the listener interface that should trigger the action * ! * @throws NullPointerException if {@code target} is null ! * @throws NullPointerException if {@code action} is null * * @see EventHandler * @see #create(Class, Object, String, String, String) * @see #getTarget * @see #getAction
*** 357,367 **** return eventPropertyName; } /** * Returns the name of the method that will trigger the action. ! * A return value of <code>null</code> signifies that all methods in the * listener interface trigger the action. * * @return the name of the method that will trigger the action * * @see #EventHandler(Object, String, String, String) --- 357,367 ---- return eventPropertyName; } /** * Returns the name of the method that will trigger the action. ! * A return value of {@code null} signifies that all methods in the * listener interface trigger the action. * * @return the name of the method that will trigger the action * * @see #EventHandler(Object, String, String, String)
*** 410,420 **** } /** * Extract the appropriate property value from the event and * pass it to the action associated with ! * this <code>EventHandler</code>. * * @param proxy the proxy object * @param method the method in the listener interface * @return the result of applying the action to the target * --- 410,420 ---- } /** * Extract the appropriate property value from the event and * pass it to the action associated with ! * this {@code EventHandler}. * * @param proxy the proxy object * @param method the method in the listener interface * @return the result of applying the action to the target *
*** 493,515 **** } return null; } /** ! * Creates an implementation of <code>listenerInterface</code> in which * <em>all</em> of the methods in the listener interface apply ! * the handler's <code>action</code> to the <code>target</code>. This * method is implemented by calling the other, more general, ! * implementation of the <code>create</code> method with both ! * the <code>eventPropertyName</code> and the <code>listenerMethodName</code> ! * taking the value <code>null</code>. Refer to * {@link java.beans.EventHandler#create(Class, Object, String, String) * the general version of create} for a complete description of ! * the <code>action</code> parameter. * <p> ! * To create an <code>ActionListener</code> that shows a ! * <code>JDialog</code> with <code>dialog.show()</code>, * one can write: * *<blockquote> *<pre> *EventHandler.create(ActionListener.class, dialog, "show") --- 493,515 ---- } return null; } /** ! * Creates an implementation of {@code listenerInterface} in which * <em>all</em> of the methods in the listener interface apply ! * the handler's {@code action} to the {@code target}. This * method is implemented by calling the other, more general, ! * implementation of the {@code create} method with both ! * the {@code eventPropertyName} and the {@code listenerMethodName} ! * taking the value {@code null}. Refer to * {@link java.beans.EventHandler#create(Class, Object, String, String) * the general version of create} for a complete description of ! * the {@code action} parameter. * <p> ! * To create an {@code ActionListener} that shows a ! * {@code JDialog} with {@code dialog.show()}, * one can write: * *<blockquote> *<pre> *EventHandler.create(ActionListener.class, dialog, "show")
*** 519,533 **** * @param <T> the type to create * @param listenerInterface the listener interface to create a proxy for * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on * the target ! * @return an object that implements <code>listenerInterface</code> * ! * @throws NullPointerException if <code>listenerInterface</code> is null ! * @throws NullPointerException if <code>target</code> is null ! * @throws NullPointerException if <code>action</code> is null * * @see #create(Class, Object, String, String) */ public static <T> T create(Class<T> listenerInterface, Object target, String action) --- 519,533 ---- * @param <T> the type to create * @param listenerInterface the listener interface to create a proxy for * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on * the target ! * @return an object that implements {@code listenerInterface} * ! * @throws NullPointerException if {@code listenerInterface} is null ! * @throws NullPointerException if {@code target} is null ! * @throws NullPointerException if {@code action} is null * * @see #create(Class, Object, String, String) */ public static <T> T create(Class<T> listenerInterface, Object target, String action)
*** 535,559 **** return create(listenerInterface, target, action, null, null); } /** /** ! * Creates an implementation of <code>listenerInterface</code> in which * <em>all</em> of the methods pass the value of the event ! * expression, <code>eventPropertyName</code>, to the final method in the ! * statement, <code>action</code>, which is applied to the <code>target</code>. * This method is implemented by calling the ! * more general, implementation of the <code>create</code> method with ! * the <code>listenerMethodName</code> taking the value <code>null</code>. * Refer to * {@link java.beans.EventHandler#create(Class, Object, String, String) * the general version of create} for a complete description of ! * the <code>action</code> and <code>eventPropertyName</code> parameters. * <p> ! * To create an <code>ActionListener</code> that sets the ! * the text of a <code>JLabel</code> to the text value of ! * the <code>JTextField</code> source of the incoming event, * you can use the following code: * *<blockquote> *<pre> *EventHandler.create(ActionListener.class, label, "text", "source.text"); --- 535,559 ---- return create(listenerInterface, target, action, null, null); } /** /** ! * Creates an implementation of {@code listenerInterface} in which * <em>all</em> of the methods pass the value of the event ! * expression, {@code eventPropertyName}, to the final method in the ! * statement, {@code action}, which is applied to the {@code target}. * This method is implemented by calling the ! * more general, implementation of the {@code create} method with ! * the {@code listenerMethodName} taking the value {@code null}. * Refer to * {@link java.beans.EventHandler#create(Class, Object, String, String) * the general version of create} for a complete description of ! * the {@code action} and {@code eventPropertyName} parameters. * <p> ! * To create an {@code ActionListener} that sets the ! * the text of a {@code JLabel} to the text value of ! * the {@code JTextField} source of the incoming event, * you can use the following code: * *<blockquote> *<pre> *EventHandler.create(ActionListener.class, label, "text", "source.text");
*** 577,591 **** * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on * the target * @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event * ! * @return an object that implements <code>listenerInterface</code> * ! * @throws NullPointerException if <code>listenerInterface</code> is null ! * @throws NullPointerException if <code>target</code> is null ! * @throws NullPointerException if <code>action</code> is null * * @see #create(Class, Object, String, String, String) */ public static <T> T create(Class<T> listenerInterface, Object target, String action, --- 577,591 ---- * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on * the target * @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event * ! * @return an object that implements {@code listenerInterface} * ! * @throws NullPointerException if {@code listenerInterface} is null ! * @throws NullPointerException if {@code target} is null ! * @throws NullPointerException if {@code action} is null * * @see #create(Class, Object, String, String, String) */ public static <T> T create(Class<T> listenerInterface, Object target, String action,
*** 593,657 **** { return create(listenerInterface, target, action, eventPropertyName, null); } /** ! * Creates an implementation of <code>listenerInterface</code> in which ! * the method named <code>listenerMethodName</code> ! * passes the value of the event expression, <code>eventPropertyName</code>, ! * to the final method in the statement, <code>action</code>, which ! * is applied to the <code>target</code>. All of the other listener * methods do nothing. * <p> ! * The <code>eventPropertyName</code> string is used to extract a value * from the incoming event object that is passed to the target * method. The common case is the target method takes no arguments, in * which case a value of null should be used for the ! * <code>eventPropertyName</code>. Alternatively if you want * the incoming event object passed directly to the target method use * the empty string. ! * The format of the <code>eventPropertyName</code> string is a sequence of * methods or properties where each method or * property is applied to the value returned by the preceding method * starting from the incoming event object. ! * The syntax is: <code>propertyName{.propertyName}*</code> ! * where <code>propertyName</code> matches a method or ! * property. For example, to extract the <code>point</code> ! * property from a <code>MouseEvent</code>, you could use either ! * <code>"point"</code> or <code>"getPoint"</code> as the ! * <code>eventPropertyName</code>. To extract the "text" property from ! * a <code>MouseEvent</code> with a <code>JLabel</code> source use any ! * of the following as <code>eventPropertyName</code>: ! * <code>"source.text"</code>, ! * <code>"getSource.text"</code> <code>"getSource.getText"</code> or ! * <code>"source.getText"</code>. If a method can not be found, or an * exception is generated as part of invoking a method a ! * <code>RuntimeException</code> will be thrown at dispatch time. For * example, if the incoming event object is null, and ! * <code>eventPropertyName</code> is non-null and not empty, a ! * <code>RuntimeException</code> will be thrown. * <p> ! * The <code>action</code> argument is of the same format as the ! * <code>eventPropertyName</code> argument where the last property name * identifies either a method name or writable property. * <p> ! * If the <code>listenerMethodName</code> is <code>null</code> ! * <em>all</em> methods in the interface trigger the <code>action</code> to be ! * executed on the <code>target</code>. ! * <p> ! * For example, to create a <code>MouseListener</code> that sets the target ! * object's <code>origin</code> property to the incoming <code>MouseEvent</code>'s ! * location (that's the value of <code>mouseEvent.getPoint()</code>) each * time a mouse button is pressed, one would write: *<blockquote> *<pre> *EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed"); *</pre> *</blockquote> * ! * This is comparable to writing a <code>MouseListener</code> in which all ! * of the methods except <code>mousePressed</code> are no-ops: * *<blockquote> *<pre> //Equivalent code using an inner class instead of EventHandler. *new MouseAdapter() { --- 593,657 ---- { return create(listenerInterface, target, action, eventPropertyName, null); } /** ! * Creates an implementation of {@code listenerInterface} in which ! * the method named {@code listenerMethodName} ! * passes the value of the event expression, {@code eventPropertyName}, ! * to the final method in the statement, {@code action}, which ! * is applied to the {@code target}. All of the other listener * methods do nothing. * <p> ! * The {@code eventPropertyName} string is used to extract a value * from the incoming event object that is passed to the target * method. The common case is the target method takes no arguments, in * which case a value of null should be used for the ! * {@code eventPropertyName}. Alternatively if you want * the incoming event object passed directly to the target method use * the empty string. ! * The format of the {@code eventPropertyName} string is a sequence of * methods or properties where each method or * property is applied to the value returned by the preceding method * starting from the incoming event object. ! * The syntax is: {@code propertyName{.propertyName}*} ! * where {@code propertyName} matches a method or ! * property. For example, to extract the {@code point} ! * property from a {@code MouseEvent}, you could use either ! * {@code "point"} or {@code "getPoint"} as the ! * {@code eventPropertyName}. To extract the "text" property from ! * a {@code MouseEvent} with a {@code JLabel} source use any ! * of the following as {@code eventPropertyName}: ! * {@code "source.text"}, ! * {@code "getSource.text" "getSource.getText"} or ! * {@code "source.getText"}. If a method can not be found, or an * exception is generated as part of invoking a method a ! * {@code RuntimeException} will be thrown at dispatch time. For * example, if the incoming event object is null, and ! * {@code eventPropertyName} is non-null and not empty, a ! * {@code RuntimeException} will be thrown. * <p> ! * The {@code action} argument is of the same format as the ! * {@code eventPropertyName} argument where the last property name * identifies either a method name or writable property. * <p> ! * If the {@code listenerMethodName} is {@code null} ! * <em>all</em> methods in the interface trigger the {@code action} to be ! * executed on the {@code target}. ! * <p> ! * For example, to create a {@code MouseListener} that sets the target ! * object's {@code origin} property to the incoming {@code MouseEvent}'s ! * location (that's the value of {@code mouseEvent.getPoint()}) each * time a mouse button is pressed, one would write: *<blockquote> *<pre> *EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed"); *</pre> *</blockquote> * ! * This is comparable to writing a {@code MouseListener} in which all ! * of the methods except {@code mousePressed} are no-ops: * *<blockquote> *<pre> //Equivalent code using an inner class instead of EventHandler. *new MouseAdapter() {
*** 668,682 **** * @param action the name of a (possibly qualified) property or method on * the target * @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event * @param listenerMethodName the name of the method in the listener interface that should trigger the action * ! * @return an object that implements <code>listenerInterface</code> * ! * @throws NullPointerException if <code>listenerInterface</code> is null ! * @throws NullPointerException if <code>target</code> is null ! * @throws NullPointerException if <code>action</code> is null * * @see EventHandler */ public static <T> T create(Class<T> listenerInterface, Object target, String action, --- 668,682 ---- * @param action the name of a (possibly qualified) property or method on * the target * @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event * @param listenerMethodName the name of the method in the listener interface that should trigger the action * ! * @return an object that implements {@code listenerInterface} * ! * @throws NullPointerException if {@code listenerInterface} is null ! * @throws NullPointerException if {@code target} is null ! * @throws NullPointerException if {@code action} is null * * @see EventHandler */ public static <T> T create(Class<T> listenerInterface, Object target, String action,
< prev index next >