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 56 * generated. The cause is assigned during the focus event creation and may be 57 * retrieved by 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 75 * occurred. Possible reasons include mouse events, keyboard focus 76 * traversal, window activation. 77 * If no cause is provided then the reason is {@code UNKNOWN}. 78 * 79 * @since 1.9 80 */ 81 public enum Cause { 82 /** 83 * The default value. 84 */ 85 UNKNOWN, 86 /** 87 * An activating mouse event. 88 */ 89 MOUSE_EVENT, 90 /** 91 * A focus traversal action with unspecified direction. 92 */ 93 TRAVERSAL, 94 /** 95 * An up-cycle focus traversal action. 96 */ 97 TRAVERSAL_UP, 98 /** 99 * A down-cycle focus traversal action. 100 */ 101 TRAVERSAL_DOWN, 102 /** 103 * A forward focus traversal action. 104 */ 105 TRAVERSAL_FORWARD, 106 /** 107 * A backward focus traversal action. 108 */ 109 TRAVERSAL_BACKWARD, 110 /** 111 * Restoring focus after a focus request has been rejected. 112 */ 113 ROLLBACK, 114 /** 115 * A system action causing an unexpected focus change. 116 */ 117 UNEXPECTED, 118 /** 119 * An activation of a toplevel window. 120 */ 121 ACTIVATION, 122 /** 123 * Clearing global focus owner. 124 */ 125 CLEAR_GLOBAL_FOCUS_OWNER 126 } 127 128 /** 129 * The first number in the range of ids used for focus events. 130 */ 131 public static final int FOCUS_FIRST = 1004; 132 133 /** 134 * The last number in the range of ids used for focus events. 135 */ 136 public static final int FOCUS_LAST = 1005; 137 138 /** 139 * This event indicates that the Component is now the focus owner. 140 */ 141 public static final int FOCUS_GAINED = FOCUS_FIRST; //Event.GOT_FOCUS 142 143 /** 144 * This event indicates that the Component is no longer the focus owner. 145 */ 146 public static final int FOCUS_LOST = 1 + FOCUS_FIRST; //Event.LOST_FOCUS 147 148 private final Cause cause; 149 150 /** 151 * A focus event can have two different levels, permanent and temporary. 152 * It will be set to true if some operation takes away the focus 153 * temporarily and intends on getting it back once the event is completed. 154 * Otherwise it will be set to false. 155 * 156 * @serial 157 * @see #isTemporary 158 */ 159 boolean temporary; 160 161 /** 162 * The other Component involved in this focus change. For a FOCUS_GAINED 163 * event, this is the Component that lost focus. For a FOCUS_LOST event, 164 * this is the Component that gained focus. If this focus change occurs 165 * with a native application, a Java application in a different VM, or with 166 * no other Component, then the opposite Component is null. 167 * 168 * @see #getOppositeComponent 169 * @since 1.4 170 */ 171 transient Component opposite; 172 173 /* 174 * JDK 1.9 serialVersionUID 175 */ 176 private static final long serialVersionUID = 523753786457416397L; 177 178 /** 179 * Constructs a {@code FocusEvent} object with the 180 * specified temporary state and opposite {@code Component} and the 181 * {@code Cause.UNKNOWN} cause. 182 * The opposite {@code Component} is the other 183 * {@code Component} involved in this focus change. 184 * For a {@code FOCUS_GAINED} event, this is the 185 * {@code Component} that lost focus. For a 186 * {@code FOCUS_LOST} event, this is the {@code Component} 187 * that gained focus. If this focus change occurs with a native 188 * application, with a Java application in a different VM, 189 * or with no other {@code Component}, then the opposite 190 * {@code Component} is {@code null}. 191 * <p> This method throws an 192 * {@code IllegalArgumentException} if {@code source} 193 * is {@code null}. 194 * 195 * @param source The {@code Component} that originated the event 196 * @param id An integer indicating the type of event. 197 * For information on allowable values, see 198 * the class description for {@link FocusEvent} 199 * @param temporary Equals {@code true} if the focus change is temporary; 200 * {@code false} otherwise 201 * @param opposite The other Component involved in the focus change, 202 * or {@code null} 203 * @throws IllegalArgumentException if {@code source} equals {@code null} 204 * @see #getSource() 205 * @see #getID() 206 * @see #isTemporary() 207 * @see #getOppositeComponent() 208 * @see Cause#UNKNOWN 209 * @since 1.4 210 */ 211 public FocusEvent(Component source, int id, boolean temporary, 212 Component opposite) { 213 this(source, id, temporary, opposite, Cause.UNKNOWN); 214 } 215 216 /** 217 * Constructs a {@code FocusEvent} object with the 218 * specified temporary state, opposite {@code Component} and the cause. 219 * The opposite {@code Component} is the other 220 * {@code Component} involved in this focus change. 221 * For a {@code FOCUS_GAINED} event, this is the 222 * {@code Component} that lost focus. For a 223 * {@code FOCUS_LOST} event, this is the {@code Component} 224 * that gained focus. If this focus change occurs with a native 225 * application, with a Java application in a different VM, 226 * or with no other {@code Component}, then the opposite 227 * {@code Component} is {@code null}. 228 * <p> This method throws an 229 * {@code IllegalArgumentException} if {@code source} or {@code cause} 230 * is {@code null}. 231 * 232 * @param source The {@code Component} that originated the event 233 * @param id An integer indicating the type of event. 234 * For information on allowable values, see 235 * the class description for {@link FocusEvent} 236 * @param temporary Equals {@code true} if the focus change is temporary; 237 * {@code false} otherwise 238 * @param opposite The other Component involved in the focus change, 239 * or {@code null} 240 * @param cause The focus event cause. 241 * @throws IllegalArgumentException if {@code source} equals {@code null} 242 * or if {@code cause} equals {@code null} 243 * @see #getSource() 244 * @see #getID() 245 * @see #isTemporary() 246 * @see #getOppositeComponent() 247 * @see Cause 248 * @since 1.9 249 */ 250 public FocusEvent(Component source, int id, boolean temporary, 251 Component opposite, Cause cause) { 252 super(source, id); 253 if (cause == null) { 254 throw new IllegalArgumentException("null cause"); 255 } 256 this.temporary = temporary; 257 this.opposite = opposite; 258 this.cause = cause; 259 } 260 261 /** 262 * Constructs a {@code FocusEvent} object and identifies 263 * whether or not the change is temporary. 264 * <p> This method throws an 265 * {@code IllegalArgumentException} if {@code source} 266 * is {@code null}. 267 * 268 * @param source The {@code Component} that originated the event 269 * @param id An integer indicating the type of event. 270 * For information on allowable values, see 271 * the class description for {@link FocusEvent} 272 * @param temporary Equals {@code true} if the focus change is temporary; 273 * {@code false} otherwise 274 * @throws IllegalArgumentException if {@code source} equals {@code null} 275 * @see #getSource() 276 * @see #getID() 277 * @see #isTemporary() 278 */ 279 public FocusEvent(Component source, int id, boolean temporary) { 280 this(source, id, temporary, null); 281 } 282 283 /** 284 * Constructs a {@code FocusEvent} object and identifies it 285 * as a permanent change in focus. 286 * <p> This method throws an 287 * {@code IllegalArgumentException} if {@code source} 288 * is {@code null}. 289 * 290 * @param source The {@code Component} that originated the event 291 * @param id An integer indicating the type of event. 292 * For information on allowable values, see 293 * the class description for {@link FocusEvent} 294 * @throws IllegalArgumentException if {@code source} equals {@code null} 295 * @see #getSource() 296 * @see #getID() 297 */ 298 public FocusEvent(Component source, int id) { 299 this(source, id, false); 300 } 301 302 /** 303 * Identifies the focus change event as temporary or permanent. 304 * 305 * @return {@code true} if the focus change is temporary; 306 * {@code false} otherwise 307 */ 308 public boolean isTemporary() { 309 return temporary; 310 } 311 312 /** 313 * Returns the other Component involved in this focus change. For a 314 * FOCUS_GAINED event, this is the Component that lost focus. For a 315 * FOCUS_LOST event, this is the Component that gained focus. If this 316 * focus change occurs with a native application, with a Java application 317 * in a different VM or context, or with no other Component, then null is 318 * returned. 319 * 320 * @return the other Component involved in the focus change, or null 321 * @since 1.4 322 */ 323 public Component getOppositeComponent() { 324 if (opposite == null) { 325 return null; 326 } 327 328 return (SunToolkit.targetToAppContext(opposite) == 329 AppContext.getAppContext()) 330 ? opposite 331 : null; 332 } 333 334 /** 335 * Returns a parameter string identifying this event. 336 * This method is useful for event-logging and for debugging. 337 * 338 * @return a string identifying the event and its attributes 339 */ 340 public String paramString() { 341 String typeStr; 342 switch(id) { 343 case FOCUS_GAINED: 344 typeStr = "FOCUS_GAINED"; 345 break; 346 case FOCUS_LOST: 347 typeStr = "FOCUS_LOST"; 348 break; 349 default: 350 typeStr = "unknown type"; 351 } 352 return typeStr + (temporary ? ",temporary" : ",permanent") + 353 ",opposite=" + getOppositeComponent() + ",cause=" + getCause(); 354 } 355 356 /** 357 * Returns the event cause. 358 * 359 * @return one of {@link Cause} values 360 * @since 1.9 361 */ 362 public final Cause getCause() { 363 return cause; 364 } 365 }