1 /*
   2  * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.event;
  27 
  28 import sun.awt.AppContext;
  29 import sun.awt.SunToolkit;
  30 
  31 import java.awt.*;
  32 
  33 /**
  34  * A low-level event which indicates that a Component has gained or lost the
  35  * input focus. This low-level event is generated by a Component (such as a
  36  * TextField). The event is passed to every {@code FocusListener} or
  37  * {@code FocusAdapter} object which registered to receive such events
  38  * using the Component's {@code addFocusListener} method. ({@code 
  39  * FocusAdapter} objects implement the {@code FocusListener}
  40  * interface.) Each such listener object gets this {@code FocusEvent} when
  41  * the event occurs.
  42  * <p>
  43  * There are two levels of focus events: permanent and temporary. Permanent
  44  * focus change events occur when focus is directly moved from one Component to
  45  * another, such as through a call to requestFocus() or as the user uses the
  46  * TAB key to traverse Components. Temporary focus change events occur when
  47  * focus is temporarily lost for a Component as the indirect result of another
  48  * operation, such as Window deactivation or a Scrollbar drag. In this case,
  49  * the original focus state will automatically be restored once that operation
  50  * is finished, or, for the case of Window deactivation, when the Window is
  51  * reactivated. Both permanent and temporary focus events are delivered using
  52  * the FOCUS_GAINED and FOCUS_LOST event ids; the level may be distinguished in
  53  * the event using the isTemporary() method.
  54  * <p>
  55  * Every {@code FocusEvent} records its cause - the reason why this event was generated.
  56  * The cause is assigned during the focus event creation and may be retrieved by
  57  * calling {@link #getCause}.
  58  * <p>
  59  * An unspecified behavior will be caused if the {@code id} parameter
  60  * of any particular {@code FocusEvent} instance is not
  61  * in the range from {@code FOCUS_FIRST} to {@code FOCUS_LAST}.
  62  *
  63  * @see FocusAdapter
  64  * @see FocusListener
  65  * @see <a href="http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html">Tutorial: Writing a Focus Listener</a>
  66  *
  67  * @author Carl Quinn
  68  * @author Amy Fowler
  69  * @since 1.1
  70  */
  71 public class FocusEvent extends ComponentEvent {
  72 
  73     /**
  74      * This enum represents the cause of a {@code FocusEvent}- the reason why it  occurred.
  75      * Possible reasons include mouse events, keyboard focus traversal, window activation.
  76      * If no cause is provided then the reason is {@code UNKNOWN}.
  77      *
  78      * @since 1.9
  79      */
  80     public enum Cause {
  81         /**
  82          * The default value.
  83          */
  84         UNKNOWN,
  85         /**
  86          * An activating mouse event.
  87          */
  88         MOUSE_EVENT,
  89         /**
  90          * A focus traversal action with unspecified direction.
  91          */
  92         TRAVERSAL,
  93         /**
  94          * An up-cycle focus traversal action.
  95          */
  96         TRAVERSAL_UP,
  97         /**
  98          * A down-cycle focus traversal action.
  99          */
 100         TRAVERSAL_DOWN,
 101         /**
 102          * A forward focus traversal action.
 103          */
 104         TRAVERSAL_FORWARD,
 105         /**
 106          * A backward focus traversal action.
 107          */
 108         TRAVERSAL_BACKWARD,
 109         /**
 110          * Restoring focus after a focus request has been rejected.
 111          */
 112         ROLLBACK,
 113         /**
 114          * A system action causing an unexpected focus change.
 115          */
 116         UNEXPECTED,
 117         /**
 118          * An activation of a toplevel window.
 119          */
 120         ACTIVATION,
 121         /**
 122          * Clearing global focus owner.
 123          */
 124         CLEAR_GLOBAL_FOCUS_OWNER
 125     }
 126     
 127     /**
 128      * The first number in the range of ids used for focus events.
 129      */
 130     public static final int FOCUS_FIRST         = 1004;
 131 
 132     /**
 133      * The last number in the range of ids used for focus events.
 134      */
 135     public static final int FOCUS_LAST          = 1005;
 136 
 137     /**
 138      * This event indicates that the Component is now the focus owner.
 139      */
 140     public static final int FOCUS_GAINED = FOCUS_FIRST; //Event.GOT_FOCUS
 141 
 142     /**
 143      * This event indicates that the Component is no longer the focus owner.
 144      */
 145     public static final int FOCUS_LOST = 1 + FOCUS_FIRST; //Event.LOST_FOCUS
 146 
 147     private final Cause cause;
 148 
 149     /**
 150      * A focus event can have two different levels, permanent and temporary.
 151      * It will be set to true if some operation takes away the focus
 152      * temporarily and intends on getting it back once the event is completed.
 153      * Otherwise it will be set to false.
 154      *
 155      * @serial
 156      * @see #isTemporary
 157      */
 158     boolean temporary;
 159 
 160     /**
 161      * The other Component involved in this focus change. For a FOCUS_GAINED
 162      * event, this is the Component that lost focus. For a FOCUS_LOST event,
 163      * this is the Component that gained focus. If this focus change occurs
 164      * with a native application, a Java application in a different VM, or with
 165      * no other Component, then the opposite Component is null.
 166      *
 167      * @see #getOppositeComponent
 168      * @since 1.4
 169      */
 170     transient Component opposite;
 171 
 172     /*
 173      * JDK 1.1 serialVersionUID
 174      */
 175     private static final long serialVersionUID = 523753786457416396L;
 176 
 177     /**
 178      * Constructs a {@code FocusEvent} object with the
 179      * specified temporary state and opposite {@code Component} and the
 180      * {@code Cause.UNKNOWN} cause.
 181      * The opposite {@code Component} is the other
 182      * {@code Component} involved in this focus change.
 183      * For a {@code FOCUS_GAINED} event, this is the
 184      * {@code Component} that lost focus. For a
 185      * {@code FOCUS_LOST} event, this is the {@code Component}
 186      * that gained focus. If this focus change occurs with a native
 187      * application, with a Java application in a different VM,
 188      * or with no other {@code Component}, then the opposite
 189      * {@code Component} is {@code null}.
 190      * <p> This method throws an
 191      * {@code IllegalArgumentException} if {@code source}
 192      * is {@code null}.
 193      *
 194      * @param source     The {@code Component} that originated the event
 195      * @param id         An integer indicating the type of event.
 196      *                     For information on allowable values, see
 197      *                     the class description for {@link FocusEvent}
 198      * @param temporary  Equals {@code true} if the focus change is temporary;
 199      *                   {@code false} otherwise
 200      * @param opposite   The other Component involved in the focus change,
 201      *                   or {@code null}
 202      * @throws IllegalArgumentException if {@code source} equals {@code null}
 203      * @see #getSource()
 204      * @see #getID()
 205      * @see #isTemporary()
 206      * @see #getOppositeComponent()
 207      * @see Cause#UNKNOWN
 208      * @since 1.4
 209      */
 210     public FocusEvent(Component source, int id, boolean temporary,
 211                       Component opposite) {
 212         this(source, id, temporary, opposite, Cause.UNKNOWN);
 213     }
 214 
 215     /**
 216      * Constructs a {@code FocusEvent} object with the
 217      * specified temporary state, opposite {@code Component} and the cause.
 218      * The opposite {@code Component} is the other
 219      * {@code Component} involved in this focus change.
 220      * For a {@code FOCUS_GAINED} event, this is the
 221      * {@code Component} that lost focus. For a
 222      * {@code FOCUS_LOST} event, this is the {@code Component}
 223      * that gained focus. If this focus change occurs with a native
 224      * application, with a Java application in a different VM,
 225      * or with no other {@code Component}, then the opposite
 226      * {@code Component} is {@code null}.
 227      * <p> This method throws an
 228      * {@code IllegalArgumentException} if {@code source}
 229      * is {@code null}.
 230      *
 231      * @param source    The {@code Component} that originated the event
 232      * @param id        An integer indicating the type of event.
 233      *                  For information on allowable values, see
 234      *                  the class description for {@link FocusEvent}
 235      * @param temporary Equals {@code true} if the focus change is temporary;
 236      *                  {@code false} otherwise
 237      * @param opposite  The other Component involved in the focus change,
 238      *                  or {@code null}
 239      * @param cause     The focus event cause.
 240      * @throws IllegalArgumentException if {@code source} equals {@code null}
 241      *                                  or if {@code cause} equals {@code null}
 242      * @see #getSource()
 243      * @see #getID()
 244      * @see #isTemporary()
 245      * @see #getOppositeComponent()
 246      * @see Cause
 247      * @since 1.9
 248      */
 249     public FocusEvent(Component source, int id, boolean temporary,
 250                       Component opposite, Cause cause) {
 251         super(source, id);
 252         if (source == null)
 253             throw new IllegalArgumentException("null cause");
 254         this.temporary = temporary;
 255         this.opposite = opposite;
 256         this.cause = cause;
 257     }
 258 
 259     /**
 260      * Constructs a {@code FocusEvent} object and identifies
 261      * whether or not the change is temporary.
 262      * <p> This method throws an
 263      * {@code IllegalArgumentException} if {@code source}
 264      * is {@code null}.
 265      *
 266      * @param source    The {@code Component} that originated the event
 267      * @param id        An integer indicating the type of event.
 268      *                     For information on allowable values, see
 269      *                     the class description for {@link FocusEvent}
 270      * @param temporary Equals {@code true} if the focus change is temporary;
 271      *                  {@code false} otherwise
 272      * @throws IllegalArgumentException if {@code source} equals {@code null}
 273      * @see #getSource()
 274      * @see #getID()
 275      * @see #isTemporary()
 276      */
 277     public FocusEvent(Component source, int id, boolean temporary) {
 278         this(source, id, temporary, null);
 279     }
 280 
 281     /**
 282      * Constructs a {@code FocusEvent} object and identifies it
 283      * as a permanent change in focus.
 284      * <p> This method throws an
 285      * {@code IllegalArgumentException} if {@code source}
 286      * is {@code null}.
 287      *
 288      * @param source    The {@code Component} that originated the event
 289      * @param id        An integer indicating the type of event.
 290      *                     For information on allowable values, see
 291      *                     the class description for {@link FocusEvent}
 292      * @throws IllegalArgumentException if {@code source} equals {@code null}
 293      * @see #getSource()
 294      * @see #getID()
 295      */
 296     public FocusEvent(Component source, int id) {
 297         this(source, id, false);
 298     }
 299 
 300     /**
 301      * Identifies the focus change event as temporary or permanent.
 302      *
 303      * @return {@code true} if the focus change is temporary;
 304      *         {@code false} otherwise
 305      */
 306     public boolean isTemporary() {
 307         return temporary;
 308     }
 309 
 310     /**
 311      * Returns the other Component involved in this focus change. For a
 312      * FOCUS_GAINED event, this is the Component that lost focus. For a
 313      * FOCUS_LOST event, this is the Component that gained focus. If this
 314      * focus change occurs with a native application, with a Java application
 315      * in a different VM or context, or with no other Component, then null is
 316      * returned.
 317      *
 318      * @return the other Component involved in the focus change, or null
 319      * @since 1.4
 320      */
 321     public Component getOppositeComponent() {
 322         if (opposite == null) {
 323             return null;
 324         }
 325 
 326         return (SunToolkit.targetToAppContext(opposite) ==
 327                 AppContext.getAppContext())
 328             ? opposite
 329             : null;
 330     }
 331 
 332     /**
 333      * Returns a parameter string identifying this event.
 334      * This method is useful for event-logging and for debugging.
 335      *
 336      * @return a string identifying the event and its attributes
 337      */
 338     public String paramString() {
 339         String typeStr;
 340         switch(id) {
 341           case FOCUS_GAINED:
 342               typeStr = "FOCUS_GAINED";
 343               break;
 344           case FOCUS_LOST:
 345               typeStr = "FOCUS_LOST";
 346               break;
 347           default:
 348               typeStr = "unknown type";
 349         }
 350         return typeStr + (temporary ? ",temporary" : ",permanent") +
 351             ",opposite=" + getOppositeComponent() + ",cause=" + getCause();
 352     }
 353 
 354     /**
 355      * Returns the event cause.
 356      *
 357      * @return one of {@link Cause} values
 358      * @since 1.9
 359      */
 360     public Cause getCause() {
 361         return cause;
 362     }
 363 }