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 }