1. /*
  2. * @(#)Container.java 1.267 04/05/18
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.io.PrintStream;
  9. import java.io.PrintWriter;
  10. import java.awt.peer.ContainerPeer;
  11. import java.awt.peer.ComponentPeer;
  12. import java.awt.peer.LightweightPeer;
  13. import sun.awt.PeerEvent;
  14. import java.awt.event.ComponentEvent;
  15. import java.awt.event.ContainerEvent;
  16. import java.awt.event.FocusEvent;
  17. import java.awt.event.HierarchyEvent;
  18. import java.awt.event.InputEvent;
  19. import java.awt.event.KeyEvent;
  20. import java.awt.event.MouseEvent;
  21. import java.awt.event.MouseWheelEvent;
  22. import java.awt.event.ContainerListener;
  23. import java.util.EventListener;
  24. import java.io.ObjectStreamField;
  25. import java.io.ObjectOutputStream;
  26. import java.io.ObjectInputStream;
  27. import java.io.IOException;
  28. import java.awt.event.AWTEventListener;
  29. import java.awt.event.WindowAdapter;
  30. import java.awt.event.WindowListener;
  31. import java.awt.event.WindowEvent;
  32. import java.awt.dnd.DropTarget;
  33. import java.util.HashSet;
  34. import java.util.LinkedList;
  35. import java.util.Set;
  36. import java.util.Iterator;
  37. import javax.accessibility.*;
  38. import java.beans.PropertyChangeListener;
  39. import javax.swing.JRootPane;
  40. import sun.awt.AppContext;
  41. import sun.awt.DebugHelper;
  42. import sun.awt.SunToolkit;
  43. import sun.awt.dnd.SunDropTargetEvent;
  44. /**
  45. * A generic Abstract Window Toolkit(AWT) container object is a component
  46. * that can contain other AWT components.
  47. * <p>
  48. * Components added to a container are tracked in a list. The order
  49. * of the list will define the components' front-to-back stacking order
  50. * within the container. If no index is specified when adding a
  51. * component to a container, it will be added to the end of the list
  52. * (and hence to the bottom of the stacking order).
  53. * <p>
  54. * <b>Note</b>: For details on the focus subsystem, see
  55. * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
  56. * How to Use the Focus Subsystem</a>,
  57. * a section in <em>The Java Tutorial</em>, and the
  58. * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
  59. * for more information.
  60. *
  61. * @version 1.267, 05/18/04
  62. * @author Arthur van Hoff
  63. * @author Sami Shaio
  64. * @see #add(java.awt.Component, int)
  65. * @see #getComponent(int)
  66. * @see LayoutManager
  67. * @since JDK1.0
  68. */
  69. public class Container extends Component {
  70. /**
  71. * The number of components in this container.
  72. * This value can be null.
  73. * @see #getComponent
  74. * @see #getComponents
  75. * @see #getComponentCount
  76. */
  77. int ncomponents;
  78. /**
  79. * The components in this container.
  80. * @see #add
  81. * @see #getComponents
  82. */
  83. Component component[] = new Component[0];
  84. /**
  85. * Layout manager for this container.
  86. * @see #doLayout
  87. * @see #setLayout
  88. * @see #getLayout
  89. */
  90. LayoutManager layoutMgr;
  91. /**
  92. * Event router for lightweight components. If this container
  93. * is native, this dispatcher takes care of forwarding and
  94. * retargeting the events to lightweight components contained
  95. * (if any).
  96. */
  97. private LightweightDispatcher dispatcher;
  98. /**
  99. * The focus traversal policy that will manage keyboard traversal of this
  100. * Container's children, if this Container is a focus cycle root. If the
  101. * value is null, this Container inherits its policy from its focus-cycle-
  102. * root ancestor. If all such ancestors of this Container have null
  103. * policies, then the current KeyboardFocusManager's default policy is
  104. * used. If the value is non-null, this policy will be inherited by all
  105. * focus-cycle-root children that have no keyboard-traversal policy of
  106. * their own (as will, recursively, their focus-cycle-root children).
  107. * <p>
  108. * If this Container is not a focus cycle root, the value will be
  109. * remembered, but will not be used or inherited by this or any other
  110. * Containers until this Container is made a focus cycle root.
  111. *
  112. * @see #setFocusTraversalPolicy
  113. * @see #getFocusTraversalPolicy
  114. * @since 1.4
  115. */
  116. private transient FocusTraversalPolicy focusTraversalPolicy;
  117. /**
  118. * Indicates whether this Component is the root of a focus traversal cycle.
  119. * Once focus enters a traversal cycle, typically it cannot leave it via
  120. * focus traversal unless one of the up- or down-cycle keys is pressed.
  121. * Normal traversal is limited to this Container, and all of this
  122. * Container's descendants that are not descendants of inferior focus cycle
  123. * roots.
  124. *
  125. * @see #setFocusCycleRoot
  126. * @see #isFocusCycleRoot
  127. * @since 1.4
  128. */
  129. private boolean focusCycleRoot = false;
  130. /**
  131. * Stores the value of focusTraversalPolicyProvider property.
  132. * @since 1.5
  133. * @see #setFocusTraversalPolicyProvider
  134. */
  135. private boolean focusTraversalPolicyProvider;
  136. // keeps track of the threads that are printing this component
  137. private transient Set printingThreads;
  138. // True if there is at least one thread that's printing this component
  139. private transient boolean printing = false;
  140. transient ContainerListener containerListener;
  141. /* HierarchyListener and HierarchyBoundsListener support */
  142. transient int listeningChildren;
  143. transient int listeningBoundsChildren;
  144. transient int descendantsCount;
  145. /**
  146. * JDK 1.1 serialVersionUID
  147. */
  148. private static final long serialVersionUID = 4613797578919906343L;
  149. private static final DebugHelper dbg = DebugHelper.create(Container.class);
  150. /**
  151. * A constant which toggles one of the controllable behaviors
  152. * of <code>getMouseEventTarget</code>. It is used to specify whether
  153. * the method can return the Container on which it is originally called
  154. * in case if none of its children are the current mouse event targets.
  155. *
  156. * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
  157. */
  158. static final boolean INCLUDE_SELF = true;
  159. /**
  160. * A constant which toggles one of the controllable behaviors
  161. * of <code>getMouseEventTarget</code>. It is used to specify whether
  162. * the method should search only lightweight components.
  163. *
  164. * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
  165. */
  166. static final boolean SEARCH_HEAVYWEIGHTS = true;
  167. /**
  168. * @serialField ncomponents int
  169. * The number of components in this container.
  170. * This value can be null.
  171. * @serialField component Component[]
  172. * The components in this container.
  173. * @serialField layoutMgr LayoutManager
  174. * Layout manager for this container.
  175. * @serialField dispatcher LightweightDispatcher
  176. * Event router for lightweight components. If this container
  177. * is native, this dispatcher takes care of forwarding and
  178. * retargeting the events to lightweight components contained
  179. * (if any).
  180. * @serialField maxSize Dimension
  181. * Maximum size of this Container.
  182. * @serialField focusCycleRoot boolean
  183. * Indicates whether this Component is the root of a focus traversal cycle.
  184. * Once focus enters a traversal cycle, typically it cannot leave it via
  185. * focus traversal unless one of the up- or down-cycle keys is pressed.
  186. * Normal traversal is limited to this Container, and all of this
  187. * Container's descendants that are not descendants of inferior focus cycle
  188. * roots.
  189. * @serialField containerSerializedDataVersion int
  190. * Container Serial Data Version.
  191. * @serialField focusTraversalPolicyProvider boolean
  192. * Stores the value of focusTraversalPolicyProvider property.
  193. */
  194. private static final ObjectStreamField[] serialPersistentFields = {
  195. new ObjectStreamField("ncomponents", Integer.TYPE),
  196. new ObjectStreamField("component", Component[].class),
  197. new ObjectStreamField("layoutMgr", LayoutManager.class),
  198. new ObjectStreamField("dispatcher", LightweightDispatcher.class),
  199. new ObjectStreamField("maxSize", Dimension.class),
  200. new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
  201. new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
  202. new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
  203. };
  204. static {
  205. /* ensure that the necessary native libraries are loaded */
  206. Toolkit.loadLibraries();
  207. if (!GraphicsEnvironment.isHeadless()) {
  208. initIDs();
  209. }
  210. }
  211. /**
  212. * Initialize JNI field and method IDs for fields that may be
  213. called from C.
  214. */
  215. private static native void initIDs();
  216. /**
  217. * Constructs a new Container. Containers can be extended directly,
  218. * but are lightweight in this case and must be contained by a parent
  219. * somewhere higher up in the component tree that is native.
  220. * (such as Frame for example).
  221. */
  222. public Container() {
  223. }
  224. void initializeFocusTraversalKeys() {
  225. focusTraversalKeys = new Set[4];
  226. }
  227. /**
  228. * Gets the number of components in this panel.
  229. * @return the number of components in this panel.
  230. * @see #getComponent
  231. * @since JDK1.1
  232. */
  233. public int getComponentCount() {
  234. return countComponents();
  235. }
  236. /**
  237. * @deprecated As of JDK version 1.1,
  238. * replaced by getComponentCount().
  239. */
  240. @Deprecated
  241. public int countComponents() {
  242. return ncomponents;
  243. }
  244. /**
  245. * Gets the nth component in this container.
  246. * @param n the index of the component to get.
  247. * @return the n<sup>th</sup> component in this container.
  248. * @exception ArrayIndexOutOfBoundsException
  249. * if the n<sup>th</sup> value does not exist.
  250. */
  251. public Component getComponent(int n) {
  252. synchronized (getTreeLock()) {
  253. if ((n < 0) || (n >= ncomponents)) {
  254. throw new ArrayIndexOutOfBoundsException("No such child: " + n);
  255. }
  256. return component[n];
  257. }
  258. }
  259. /**
  260. * Gets all the components in this container.
  261. * @return an array of all the components in this container.
  262. */
  263. public Component[] getComponents() {
  264. return getComponents_NoClientCode();
  265. }
  266. // NOTE: This method may be called by privileged threads.
  267. // This functionality is implemented in a package-private method
  268. // to insure that it cannot be overridden by client subclasses.
  269. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  270. final Component[] getComponents_NoClientCode() {
  271. synchronized (getTreeLock()) {
  272. Component list[] = new Component[ncomponents];
  273. System.arraycopy(component, 0, list, 0, ncomponents);
  274. return list;
  275. }
  276. } // getComponents_NoClientCode()
  277. /**
  278. * Determines the insets of this container, which indicate the size
  279. * of the container's border.
  280. * <p>
  281. * A <code>Frame</code> object, for example, has a top inset that
  282. * corresponds to the height of the frame's title bar.
  283. * @return the insets of this container.
  284. * @see Insets
  285. * @see LayoutManager
  286. * @since JDK1.1
  287. */
  288. public Insets getInsets() {
  289. return insets();
  290. }
  291. /**
  292. * @deprecated As of JDK version 1.1,
  293. * replaced by <code>getInsets()</code>.
  294. */
  295. @Deprecated
  296. public Insets insets() {
  297. if (this.peer != null && this.peer instanceof ContainerPeer) {
  298. ContainerPeer peer = (ContainerPeer)this.peer;
  299. return (Insets)peer.insets().clone();
  300. }
  301. return new Insets(0, 0, 0, 0);
  302. }
  303. /**
  304. * Appends the specified component to the end of this container.
  305. * This is a convenience method for {@link #addImpl}.
  306. * <p>
  307. * Note: If a component has been added to a container that
  308. * has been displayed, <code>validate</code> must be
  309. * called on that container to display the new component.
  310. * If multiple components are being added, you can improve
  311. * efficiency by calling <code>validate</code> only once,
  312. * after all the components have been added.
  313. *
  314. * @param comp the component to be added
  315. * @see #addImpl
  316. * @see #validate
  317. * @see javax.swing.JComponent#revalidate()
  318. * @return the component argument
  319. */
  320. public Component add(Component comp) {
  321. addImpl(comp, null, -1);
  322. return comp;
  323. }
  324. /**
  325. * Adds the specified component to this container.
  326. * This is a convenience method for {@link #addImpl}.
  327. * <p>
  328. * This method is obsolete as of 1.1. Please use the
  329. * method <code>add(Component, Object)</code> instead.
  330. * @see #add(Component, Object)
  331. */
  332. public Component add(String name, Component comp) {
  333. addImpl(comp, name, -1);
  334. return comp;
  335. }
  336. /**
  337. * Adds the specified component to this container at the given
  338. * position.
  339. * This is a convenience method for {@link #addImpl}.
  340. * <p>
  341. * Note: If a component has been added to a container that
  342. * has been displayed, <code>validate</code> must be
  343. * called on that container to display the new component.
  344. * If multiple components are being added, you can improve
  345. * efficiency by calling <code>validate</code> only once,
  346. * after all the components have been added.
  347. *
  348. * @param comp the component to be added
  349. * @param index the position at which to insert the component,
  350. * or <code>-1</code> to append the component to the end
  351. * @return the component <code>comp</code>
  352. * @see #addImpl
  353. * @see #remove
  354. * @see #validate
  355. * @see javax.swing.JComponent#revalidate()
  356. */
  357. public Component add(Component comp, int index) {
  358. addImpl(comp, null, index);
  359. return comp;
  360. }
  361. void checkTreeLock() {
  362. if (!Thread.holdsLock(getTreeLock())) {
  363. throw new IllegalStateException("This function should be called while holding treeLock");
  364. }
  365. }
  366. /**
  367. * Checks that the component comp can be added to this container
  368. * Checks : index in bounds of container's size,
  369. * comp is not one of this container's parents,
  370. * and comp is not a window.
  371. * Comp and container must be on the same GraphicsDevice.
  372. * if comp is container, all sub-components must be on
  373. * same GraphicsDevice.
  374. *
  375. * @since 1.5
  376. */
  377. private void checkAdding(Component comp, int index) {
  378. checkTreeLock();
  379. GraphicsConfiguration thisGC = getGraphicsConfiguration();
  380. if (index > ncomponents || index < 0) {
  381. throw new IllegalArgumentException("illegal component position");
  382. }
  383. if (comp.parent == this) {
  384. if (index == ncomponents) {
  385. throw new IllegalArgumentException("illegal component position " +
  386. index + " should be less then " + ncomponents);
  387. }
  388. }
  389. if (comp instanceof Container) {
  390. for (Container cn = this; cn != null; cn=cn.parent) {
  391. if (cn == comp) {
  392. throw new IllegalArgumentException("adding container's parent to itself");
  393. }
  394. }
  395. if (comp instanceof Window) {
  396. throw new IllegalArgumentException("adding a window to a container");
  397. }
  398. }
  399. Window thisTopLevel = getContainingWindow();
  400. Window compTopLevel = comp.getContainingWindow();
  401. if (thisTopLevel != compTopLevel) {
  402. throw new IllegalArgumentException("component and container should be in the same top-level window");
  403. }
  404. if (thisGC != null) {
  405. comp.checkGD(thisGC.getDevice().getIDstring());
  406. }
  407. }
  408. /**
  409. * Removes component comp from this container without making unneccessary changes
  410. * and generating unneccessary events. This function intended to perform optimized
  411. * remove, for example, if newParent and current parent are the same it just changes
  412. * index without calling removeNotify.
  413. * Note: Should be called while holding treeLock
  414. * @since: 1.5
  415. */
  416. private void removeDelicately(Component comp, Container newParent, int newIndex) {
  417. checkTreeLock();
  418. int index = getComponentZOrder(comp);
  419. if (isRemoveNotifyNeeded(comp, this, newParent)) {
  420. comp.removeNotify();
  421. }
  422. if (newParent != this) {
  423. if (layoutMgr != null) {
  424. layoutMgr.removeLayoutComponent(comp);
  425. }
  426. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  427. -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  428. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  429. -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  430. adjustDescendants(-(comp.countHierarchyMembers()));
  431. comp.parent = null;
  432. System.arraycopy(component, index + 1,
  433. component, index,
  434. ncomponents - index - 1);
  435. component[--ncomponents] = null;
  436. if (valid) {
  437. invalidate();
  438. }
  439. } else {
  440. if (newIndex > index) { // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
  441. if (newIndex-index > 0) {
  442. System.arraycopy(component, index+1, component, index, newIndex-index);
  443. }
  444. } else { // 4->2: 012345 -> 014235
  445. if (index-newIndex > 0) {
  446. System.arraycopy(component, newIndex, component, newIndex+1, index-newIndex);
  447. }
  448. }
  449. component[newIndex] = comp;
  450. }
  451. if (comp.parent == null) { // was actually removed
  452. if (containerListener != null ||
  453. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  454. Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  455. ContainerEvent e = new ContainerEvent(this,
  456. ContainerEvent.COMPONENT_REMOVED,
  457. comp);
  458. dispatchEvent(e);
  459. }
  460. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  461. this, HierarchyEvent.PARENT_CHANGED,
  462. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  463. if (peer != null && layoutMgr == null && isVisible()) {
  464. updateCursorImmediately();
  465. }
  466. }
  467. }
  468. /**
  469. * Checks whether this container can contain component which is focus owner.
  470. * Verifies that container is enable and showing, and if it is focus cycle root
  471. * its FTP allows component to be focus owner
  472. * @since 1.5
  473. */
  474. boolean canContainFocusOwner(Component focusOwnerCandidate) {
  475. if (!(isEnabled() && isDisplayable()
  476. && isVisible() && isFocusable()))
  477. {
  478. return false;
  479. }
  480. if (isFocusCycleRoot()) {
  481. FocusTraversalPolicy policy = getFocusTraversalPolicy();
  482. if (policy instanceof DefaultFocusTraversalPolicy) {
  483. if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
  484. return false;
  485. }
  486. }
  487. }
  488. synchronized(getTreeLock()) {
  489. if (parent != null) {
  490. return parent.canContainFocusOwner(focusOwnerCandidate);
  491. }
  492. }
  493. return true;
  494. }
  495. /**
  496. * Checks whether or not this container has heavyweight children.
  497. * Note: Should be called while holding tree lock
  498. * @return true if there is at least one heavyweight children in a container, false otherwise
  499. * @since 1.5
  500. */
  501. private boolean hasHeavyweightChildren() {
  502. checkTreeLock();
  503. boolean res = true; // true while it is lightweight
  504. for (int i = 0; i < getComponentCount() && res; i++) {
  505. Component child = getComponent(i);
  506. res &= child.isLightweight();
  507. if (res && child instanceof Container) {
  508. res &= !((Container)child).hasHeavyweightChildren();
  509. }
  510. }
  511. return !res;
  512. }
  513. /**
  514. * Returns closest heavyweight component to this container. If this container is heavyweight
  515. * returns this.
  516. * @since 1.5
  517. */
  518. Container getHeavyweightContainer() {
  519. checkTreeLock();
  520. if (peer != null && !(peer instanceof LightweightPeer)) {
  521. return this;
  522. } else {
  523. return getNativeContainer();
  524. }
  525. }
  526. /**
  527. * Detects whether or not remove from current parent and adding to new parent requires call of
  528. * removeNotify on the component. Since removeNotify destroys native window this might (not)
  529. * be required. For example, if new container and old containers are the same we don't need to
  530. * destroy native window.
  531. * @since: 1.5
  532. */
  533. private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
  534. if (oldContainer == null) { // Component didn't have parent - no removeNotify
  535. return false;
  536. }
  537. if (comp.peer == null) { // Component didn't have peer - no removeNotify
  538. return false;
  539. }
  540. if (newContainer.peer == null) {
  541. // Component has peer but new Container doesn't - call removeNotify
  542. return true;
  543. }
  544. // If component is lightweight non-Container or lightweight Container with all but heavyweight
  545. // children there is no need to call remove notify
  546. if (comp.isLightweight()) {
  547. if (comp instanceof Container) {
  548. // If it has heavyweight children then removeNotify is required
  549. return ((Container)comp).hasHeavyweightChildren();
  550. } else {
  551. // Just a lightweight
  552. return false;
  553. }
  554. }
  555. // All three components have peers, check for peer change
  556. Container newNativeContainer = oldContainer.getHeavyweightContainer();
  557. Container oldNativeContainer = newContainer.getHeavyweightContainer();
  558. if (newNativeContainer != oldNativeContainer) {
  559. // Native containers change - check whether or not current platform supports
  560. // changing of widget hierarchy on native level without recreation.
  561. return !comp.peer.isReparentSupported();
  562. } else {
  563. // if container didn't change we still might need to recreate component's window as
  564. // changes to zorder should be reflected in native window stacking order and it might
  565. // not be supported by the platform. This is important only for heavyweight child
  566. return !comp.isLightweight() &&
  567. !((ContainerPeer)(newNativeContainer.peer)).isRestackSupported();
  568. }
  569. }
  570. /**
  571. * Moves the specified component to the specified z-order index in
  572. * the container. The z-order determines the order that components
  573. * are painted; the component with the highest z-order paints first
  574. * and the component with the lowest z-order paints last.
  575. * Where components overlap, the component with the lower
  576. * z-order paints over the component with the higher z-order.
  577. * <p>
  578. * If the component is a child of some other container, it is
  579. * removed from that container before being added to this container.
  580. * The important difference between this method and
  581. * <code>java.awt.Container.add(Component, int)</code> is that this method
  582. * doesn't call <code>removeNotify</code> on the component while
  583. * removing it from its previous container unless necessary and when
  584. * allowed by the underlying native windowing system. This way, if the
  585. * component has the keyboard focus, it maintains the focus when
  586. * moved to the new position.
  587. * <p>
  588. * This property is guaranteed to apply only to lightweight
  589. * non-<code>Container</code> components.
  590. * <p>
  591. * <b>Note</b>: Not all platforms support changing the z-order of
  592. * heavyweight components from one container into another without
  593. * the call to <code>removeNotify</code>. There is no way to detect
  594. * whether a platform supports this, so developers shouldn't make
  595. * any assumptions.
  596. *
  597. * @param comp the component to be moved
  598. * @param index the position in the container's list to
  599. * insert the component, where <code>getComponentCount()</code>
  600. * appends to the end
  601. * @exception NullPointerException if <code>comp</code> is
  602. * <code>null</code>
  603. * @exception IllegalArgumentException if <code>comp</code> is one of the
  604. * container's parents
  605. * @exception IllegalArgumentException if <code>index</code> is not in
  606. * the range <code>[0, getComponentCount()]</code> for moving
  607. * between containers, or not in the range
  608. * <code>[0, getComponentCount()-1]</code> for moving inside
  609. * a container
  610. * @exception IllegalArgumentException if adding a container to itself
  611. * @exception IllegalArgumentException if adding a <code>Window</code>
  612. * to a container
  613. * @see #getComponentZOrder(java.awt.Component)
  614. * @since 1.5
  615. */
  616. public final void setComponentZOrder(Component comp, int index) {
  617. synchronized (getTreeLock()) {
  618. // Store parent because remove will clear it
  619. Container curParent = comp.parent;
  620. if (curParent == this && index == getComponentZOrder(comp)) {
  621. return;
  622. }
  623. checkAdding(comp, index);
  624. if (curParent != null) {
  625. curParent.removeDelicately(comp, this, index);
  626. }
  627. addDelicately(comp, curParent, index);
  628. }
  629. }
  630. /**
  631. * Traverses the tree of components and reparents children heavyweight component
  632. * to new heavyweight parent.
  633. * @since 1.5
  634. */
  635. private void reparentTraverse(ContainerPeer parentPeer, Container child) {
  636. checkTreeLock();
  637. for (int i = 0; i < child.getComponentCount(); i++) {
  638. Component comp = child.getComponent(i);
  639. if (comp.isLightweight()) {
  640. // If components is lightweight check if it is container
  641. // If it is container it might contain heavyweight children we need to reparent
  642. if (comp instanceof Container) {
  643. reparentTraverse(parentPeer, (Container)comp);
  644. }
  645. } else {
  646. // Q: Need to update NativeInLightFixer?
  647. comp.getPeer().reparent(parentPeer);
  648. }
  649. }
  650. }
  651. /**
  652. * Reparents child component peer to this container peer.
  653. * Container must be heavyweight.
  654. * @since 1.5
  655. */
  656. private void reparentChild(Component comp) {
  657. checkTreeLock();
  658. if (comp == null) {
  659. return;
  660. }
  661. if (comp.isLightweight()) {
  662. // If component is lightweight container we need to reparent all its explicit heavyweight children
  663. if (comp instanceof Container) {
  664. // Traverse component's tree till depth-first until encountering heavyweight component
  665. reparentTraverse((ContainerPeer)getPeer(), (Container)comp);
  666. }
  667. } else {
  668. comp.getPeer().reparent((ContainerPeer)getPeer());
  669. }
  670. }
  671. /**
  672. * Adds component to this container. Tries to minimize side effects of this adding -
  673. * doesn't call remove notify if it is not required.
  674. * @since 1.5
  675. */
  676. private void addDelicately(Component comp, Container curParent, int index) {
  677. checkTreeLock();
  678. // Check if moving between containers
  679. if (curParent != this) {
  680. /* Add component to list; allocate new array if necessary. */
  681. if (ncomponents == component.length) {
  682. Component newcomponents[] = new Component[ncomponents * 2 + 1];
  683. System.arraycopy(component, 0, newcomponents, 0, ncomponents);
  684. component = newcomponents;
  685. }
  686. if (index == -1 || index == ncomponents) {
  687. component[ncomponents++] = comp;
  688. } else {
  689. System.arraycopy(component, index, component,
  690. index + 1, ncomponents - index);
  691. component[index] = comp;
  692. ncomponents++;
  693. }
  694. comp.parent = this;
  695. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  696. comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  697. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  698. comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  699. adjustDescendants(comp.countHierarchyMembers());
  700. } else {
  701. if (index < ncomponents) {
  702. component[index] = comp;
  703. }
  704. }
  705. if (valid) {
  706. invalidate();
  707. }
  708. if (peer != null) {
  709. if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
  710. comp.addNotify();
  711. // New created peer creates component on top of the stacking order
  712. Container newNativeContainer = getHeavyweightContainer();
  713. if (((ContainerPeer)newNativeContainer.getPeer()).isRestackSupported()) {
  714. ((ContainerPeer)newNativeContainer.getPeer()).restack();
  715. }
  716. } else { // Both container and child have peers, it means child peer should be reparented.
  717. // In both cases we need to reparent native widgets.
  718. Container newNativeContainer = getHeavyweightContainer();
  719. Container oldNativeContainer = curParent.getHeavyweightContainer();
  720. if (oldNativeContainer != newNativeContainer) {
  721. // Native container changed - need to reparent native widgets
  722. newNativeContainer.reparentChild(comp);
  723. }
  724. // If component still has a peer and it is either container or heavyweight
  725. // and restack is supported we have to restack native windows since order might have changed
  726. if ((!comp.isLightweight() || (comp instanceof Container))
  727. && ((ContainerPeer)newNativeContainer.getPeer()).isRestackSupported())
  728. {
  729. ((ContainerPeer)newNativeContainer.getPeer()).restack();
  730. }
  731. if (!comp.isLightweight() && isLightweight()) {
  732. // If component is heavyweight and one of the containers is lightweight
  733. // some NativeInLightFixer activity should be performed
  734. if (!curParent.isLightweight()) {
  735. // Moving from heavyweight container to lightweight container - should create NativeInLightFixer
  736. // since addNotify does this
  737. comp.nativeInLightFixer = new NativeInLightFixer();
  738. } else {
  739. // Component already has NativeInLightFixer - just reinstall it
  740. // because hierarchy changed and he needs to rebuild list of parents to listen.
  741. comp.nativeInLightFixer.install(this);
  742. }
  743. }
  744. }
  745. }
  746. if (curParent != this) {
  747. /* Notify the layout manager of the added component. */
  748. if (layoutMgr != null) {
  749. if (layoutMgr instanceof LayoutManager2) {
  750. ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
  751. } else {
  752. layoutMgr.addLayoutComponent(null, comp);
  753. }
  754. }
  755. if (containerListener != null ||
  756. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  757. Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  758. ContainerEvent e = new ContainerEvent(this,
  759. ContainerEvent.COMPONENT_ADDED,
  760. comp);
  761. dispatchEvent(e);
  762. }
  763. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  764. this, HierarchyEvent.PARENT_CHANGED,
  765. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  766. // If component is focus owner or parent container of focus owner check that after reparenting
  767. // focus owner moved out if new container prohibit this kind of focus owner.
  768. if (comp.isFocusOwner() && !comp.canBeFocusOwner()) {
  769. comp.transferFocus();
  770. } else if (comp instanceof Container) {
  771. Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
  772. if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwner()) {
  773. focusOwner.transferFocus();
  774. }
  775. }
  776. } else {
  777. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  778. this, HierarchyEvent.HIERARCHY_CHANGED,
  779. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  780. }
  781. if (peer != null && layoutMgr == null && isVisible()) {
  782. updateCursorImmediately();
  783. }
  784. }
  785. /**
  786. * Returns the z-order index of the component inside the container.
  787. * The higher a component is in the z-order hierarchy, the lower
  788. * its index. The component with the lowest z-order index is
  789. * painted last, above all other child components.
  790. *
  791. * @param comp the component being queried
  792. * @return the z-order index of the component; otherwise
  793. * returns -1 if the component is <code>null</code
  794. * or doesn't belong to the container
  795. * @see #setComponentZOrder(java.awt.Component, int)
  796. * @since 1.5
  797. */
  798. public final int getComponentZOrder(Component comp) {
  799. if (comp == null) {
  800. return -1;
  801. }
  802. synchronized(getTreeLock()) {
  803. // Quick check - container should be immediate parent of the component
  804. if (comp.parent != this) {
  805. return -1;
  806. }
  807. for (int i = 0; i < ncomponents; i++) {
  808. if (component[i] == comp) {
  809. return i;
  810. }
  811. }
  812. }
  813. // To please javac
  814. return -1;
  815. }
  816. /**
  817. * Adds the specified component to the end of this container.
  818. * Also notifies the layout manager to add the component to
  819. * this container's layout using the specified constraints object.
  820. * This is a convenience method for {@link #addImpl}.
  821. * <p>
  822. * Note: If a component has been added to a container that
  823. * has been displayed, <code>validate</code> must be
  824. * called on that container to display the new component.
  825. * If multiple components are being added, you can improve
  826. * efficiency by calling <code>validate</code> only once,
  827. * after all the components have been added.
  828. *
  829. * @param comp the component to be added
  830. * @param constraints an object expressing
  831. * layout contraints for this component
  832. * @see #addImpl
  833. * @see #validate
  834. * @see javax.swing.JComponent#revalidate()
  835. * @see LayoutManager
  836. * @since JDK1.1
  837. */
  838. public void add(Component comp, Object constraints) {
  839. addImpl(comp, constraints, -1);
  840. }
  841. /**
  842. * Adds the specified component to this container with the specified
  843. * constraints at the specified index. Also notifies the layout
  844. * manager to add the component to the this container's layout using
  845. * the specified constraints object.
  846. * This is a convenience method for {@link #addImpl}.
  847. * <p>
  848. * Note: If a component has been added to a container that
  849. * has been displayed, <code>validate</code> must be
  850. * called on that container to display the new component.
  851. * If multiple components are being added, you can improve
  852. * efficiency by calling <code>validate</code> only once,
  853. * after all the components have been added.
  854. *
  855. * @param comp the component to be added
  856. * @param constraints an object expressing layout contraints for this
  857. * @param index the position in the container's list at which to insert
  858. * the component; <code>-1</code> means insert at the end
  859. * component
  860. * @see #addImpl
  861. * @see #validate
  862. * @see javax.swing.JComponent#revalidate()
  863. * @see #remove
  864. * @see LayoutManager
  865. */
  866. public void add(Component comp, Object constraints, int index) {
  867. addImpl(comp, constraints, index);
  868. }
  869. /**
  870. * Adds the specified component to this container at the specified
  871. * index. This method also notifies the layout manager to add
  872. * the component to this container's layout using the specified
  873. * constraints object via the <code>addLayoutComponent</code>
  874. * method.
  875. * <p>
  876. * The constraints are
  877. * defined by the particular layout manager being used. For
  878. * example, the <code>BorderLayout</code> class defines five
  879. * constraints: <code>BorderLayout.NORTH</code>,
  880. * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
  881. * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
  882. * <p>
  883. * The <code>GridBagLayout</code> class requires a
  884. * <code>GridBagConstraints</code> object. Failure to pass
  885. * the correct type of constraints object results in an
  886. * <code>IllegalArgumentException</code>.
  887. * <p>
  888. * If the layout manager implements both the <code>LayoutManager</code>
  889. * and <code>LayoutManager2</code> interfaces, the
  890. * <code>LayoutManager2</code> methods are called.
  891. * <p>
  892. * Note that if the component already exists
  893. * in this container or a child of this container,
  894. * it is removed from that container before
  895. * being added to this container.
  896. * <p>
  897. * This is the method to override if a program needs to track
  898. * every add request to a container as all other add methods defer
  899. * to this one. An overriding method should
  900. * usually include a call to the superclass's version of the method:
  901. * <p>
  902. * <blockquote>
  903. * <code>super.addImpl(comp, constraints, index)</code>
  904. * </blockquote>
  905. * <p>
  906. * @param comp the component to be added
  907. * @param constraints an object expressing layout constraints
  908. * for this component
  909. * @param index the position in the container's list at which to
  910. * insert the component, where <code>-1</code>
  911. * means append to the end
  912. * @exception IllegalArgumentException if <code>index</code> is invalid
  913. * @exception IllegalArgumentException if adding the container's parent
  914. * to itself
  915. * @throws IllegalArgumentException if <code>comp</code> has been added
  916. * to the <code>Container</code> more than once
  917. * @exception IllegalArgumentException if adding a window to a container
  918. * @see #add(Component)
  919. * @see #add(Component, int)
  920. * @see #add(Component, java.lang.Object)
  921. * @see LayoutManager
  922. * @see LayoutManager2
  923. * @since JDK1.1
  924. */
  925. protected void addImpl(Component comp, Object constraints, int index) {
  926. synchronized (getTreeLock()) {
  927. /* Check for correct arguments: index in bounds,
  928. * comp cannot be one of this container's parents,
  929. * and comp cannot be a window.
  930. * comp and container must be on the same GraphicsDevice.
  931. * if comp is container, all sub-components must be on
  932. * same GraphicsDevice.
  933. */
  934. GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
  935. if (index > ncomponents || (index < 0 && index != -1)) {
  936. throw new IllegalArgumentException(
  937. "illegal component position");
  938. }
  939. if (comp instanceof Container) {
  940. for (Container cn = this; cn != null; cn=cn.parent) {
  941. if (cn == comp) {
  942. throw new IllegalArgumentException(
  943. "adding container's parent to itself");
  944. }
  945. }
  946. if (comp instanceof Window) {
  947. throw new IllegalArgumentException(
  948. "adding a window to a container");
  949. }
  950. }
  951. if (thisGC != null) {
  952. comp.checkGD(thisGC.getDevice().getIDstring());
  953. }
  954. /* Reparent the component and tidy up the tree's state. */
  955. if (comp.parent != null) {
  956. comp.parent.remove(comp);
  957. if (index > ncomponents) {
  958. throw new IllegalArgumentException("illegal component position");
  959. }
  960. }
  961. /* Add component to list; allocate new array if necessary. */
  962. if (ncomponents == component.length) {
  963. Component newcomponents[] = new Component[ncomponents * 2 + 1];
  964. System.arraycopy(component, 0, newcomponents, 0, ncomponents);
  965. component = newcomponents;
  966. }
  967. if (index == -1 || index == ncomponents) {
  968. component[ncomponents++] = comp;
  969. } else {
  970. System.arraycopy(component, index, component,
  971. index + 1, ncomponents - index);
  972. component[index] = comp;
  973. ncomponents++;
  974. }
  975. comp.parent = this;
  976. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  977. comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  978. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  979. comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  980. adjustDescendants(comp.countHierarchyMembers());
  981. if (valid) {
  982. invalidate();
  983. }
  984. if (peer != null) {
  985. comp.addNotify();
  986. }
  987. /* Notify the layout manager of the added component. */
  988. if (layoutMgr != null) {
  989. if (layoutMgr instanceof LayoutManager2) {
  990. ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
  991. } else if (constraints instanceof String) {
  992. layoutMgr.addLayoutComponent((String)constraints, comp);
  993. }
  994. }
  995. if (containerListener != null ||
  996. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  997. Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  998. ContainerEvent e = new ContainerEvent(this,
  999. ContainerEvent.COMPONENT_ADDED,
  1000. comp);
  1001. dispatchEvent(e);
  1002. }
  1003. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  1004. this, HierarchyEvent.PARENT_CHANGED,
  1005. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  1006. if (peer != null && layoutMgr == null && isVisible()) {
  1007. updateCursorImmediately();
  1008. }
  1009. }
  1010. }
  1011. /**
  1012. * Checks that all Components that this Container contains are on
  1013. * the same GraphicsDevice as this Container. If not, throws an
  1014. * IllegalArgumentException.
  1015. */
  1016. void checkGD(String stringID) {
  1017. Component tempComp;
  1018. for (int i = 0; i < component.length; i++) {
  1019. tempComp= component[i];
  1020. if (tempComp != null) {
  1021. tempComp.checkGD(stringID);
  1022. }
  1023. }
  1024. }
  1025. /**
  1026. * Removes the component, specified by <code>index</code>,
  1027. * from this container.
  1028. * This method also notifies the layout manager to remove the
  1029. * component from this container's layout via the
  1030. * <code>removeLayoutComponent</code> method.
  1031. *
  1032. * @param index the index of the component to be removed
  1033. * @see #add
  1034. * @since JDK1.1
  1035. */
  1036. public void remove(int index) {
  1037. synchronized (getTreeLock()) {
  1038. if (index < 0 || index >= ncomponents) {
  1039. throw new ArrayIndexOutOfBoundsException(index);
  1040. }
  1041. Component comp = component[index];
  1042. if (peer != null) {
  1043. comp.removeNotify();
  1044. }
  1045. if (layoutMgr != null) {
  1046. layoutMgr.removeLayoutComponent(comp);
  1047. }
  1048. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  1049. -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  1050. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  1051. -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  1052. adjustDescendants(-(comp.countHierarchyMembers()));
  1053. comp.parent = null;
  1054. System.arraycopy(component, index + 1,
  1055. component, index,
  1056. ncomponents - index - 1);
  1057. component[--ncomponents] = null;
  1058. if (valid) {
  1059. invalidate();
  1060. }
  1061. if (containerListener != null ||
  1062. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  1063. Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  1064. ContainerEvent e = new ContainerEvent(this,
  1065. ContainerEvent.COMPONENT_REMOVED,
  1066. comp);
  1067. dispatchEvent(e);
  1068. }
  1069. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  1070. this, HierarchyEvent.PARENT_CHANGED,
  1071. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  1072. if (peer != null && layoutMgr == null && isVisible()) {
  1073. updateCursorImmediately();
  1074. }
  1075. }
  1076. }
  1077. /**
  1078. * Removes the specified component from this container.
  1079. * This method also notifies the layout manager to remove the
  1080. * component from this container's layout via the
  1081. * <code>removeLayoutComponent</code> method.
  1082. *
  1083. * @param comp the component to be removed
  1084. * @see #add
  1085. * @see #remove(int)
  1086. */
  1087. public void remove(Component comp) {
  1088. synchronized (getTreeLock()) {
  1089. if (comp.parent == this) {
  1090. /* Search backwards, expect that more recent additions
  1091. * are more likely to be removed.
  1092. */
  1093. Component component[] = this.component;
  1094. for (int i = ncomponents; --i >= 0; ) {
  1095. if (component[i] == comp) {
  1096. remove(i);
  1097. }
  1098. }
  1099. }
  1100. }
  1101. }
  1102. /**
  1103. * Removes all the components from this container.
  1104. * This method also notifies the layout manager to remove the
  1105. * components from this container's layout via the
  1106. * <code>removeLayoutComponent</code> method.
  1107. * @see #add
  1108. * @see #remove
  1109. */
  1110. public void removeAll() {
  1111. synchronized (getTreeLock()) {
  1112. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  1113. -listeningChildren);
  1114. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  1115. -listeningBoundsChildren);
  1116. adjustDescendants(-descendantsCount);
  1117. while (ncomponents > 0) {
  1118. Component comp = component[--ncomponents];
  1119. component[ncomponents] = null;
  1120. if (peer != null) {
  1121. comp.removeNotify();
  1122. }
  1123. if (layoutMgr != null) {
  1124. layoutMgr.removeLayoutComponent(comp);
  1125. }
  1126. comp.parent = null;
  1127. if (containerListener != null ||
  1128. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  1129. Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  1130. ContainerEvent e = new ContainerEvent(this,
  1131. ContainerEvent.COMPONENT_REMOVED,
  1132. comp);
  1133. dispatchEvent(e);
  1134. }
  1135. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
  1136. comp, this,
  1137. HierarchyEvent.PARENT_CHANGED,
  1138. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  1139. }
  1140. if (peer != null && layoutMgr == null && isVisible()) {
  1141. updateCursorImmediately();
  1142. }
  1143. if (valid) {
  1144. invalidate();
  1145. }
  1146. }
  1147. }
  1148. // Should only be called while holding tree lock
  1149. int numListening(long mask) {
  1150. int superListening = super.numListening(mask);
  1151. if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
  1152. if (dbg.on) {
  1153. // Verify listeningChildren is correct
  1154. int sum = 0;
  1155. for (int i = 0; i < ncomponents; i++) {
  1156. sum += component[i].numListening(mask);
  1157. }
  1158. dbg.assertion(listeningChildren == sum);
  1159. }
  1160. return listeningChildren + superListening;
  1161. } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
  1162. if (dbg.on) {
  1163. // Verify listeningBoundsChildren is correct
  1164. int sum = 0;
  1165. for (int i = 0; i < ncomponents; i++) {
  1166. sum += component[i].numListening(mask);
  1167. }
  1168. dbg.assertion(listeningBoundsChildren == sum);
  1169. }
  1170. return listeningBoundsChildren + superListening;
  1171. } else {
  1172. if (dbg.on) {
  1173. dbg.assertion(false);
  1174. }
  1175. return superListening;
  1176. }
  1177. }
  1178. // Should only be called while holding tree lock
  1179. void adjustListeningChildren(long mask, int num) {
  1180. if (dbg.on) {
  1181. dbg.assertion(mask == AWTEvent.HIERARCHY_EVENT_MASK ||
  1182. mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
  1183. mask == (AWTEvent.HIERARCHY_EVENT_MASK |
  1184. AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  1185. }
  1186. if (num == 0)
  1187. return;
  1188. if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
  1189. listeningChildren += num;
  1190. }
  1191. if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
  1192. listeningBoundsChildren += num;
  1193. }
  1194. adjustListeningChildrenOnParent(mask, num);
  1195. }
  1196. // Should only be called while holding tree lock
  1197. void adjustDescendants(int num) {
  1198. if (num == 0)
  1199. return;
  1200. descendantsCount += num;
  1201. adjustDecendantsOnParent(num);
  1202. }
  1203. // Should only be called while holding tree lock
  1204. void adjustDecendantsOnParent(int num) {
  1205. if (parent != null) {
  1206. parent.adjustDescendants(num);
  1207. }
  1208. }
  1209. // Should only be called while holding tree lock
  1210. int countHierarchyMembers() {
  1211. if (dbg.on) {
  1212. // Verify descendantsCount is correct
  1213. int sum = 0;
  1214. for (int i = 0; i < ncomponents; i++) {
  1215. sum += component[i].countHierarchyMembers();
  1216. }
  1217. dbg.assertion(descendantsCount == sum);
  1218. }
  1219. return descendantsCount + 1;
  1220. }
  1221. private int getListenersCount(int id, boolean enabledOnToolkit) {
  1222. assert Thread.holdsLock(getTreeLock());
  1223. if (enabledOnToolkit) {
  1224. return descendantsCount;
  1225. }
  1226. switch (id) {
  1227. case HierarchyEvent.HIERARCHY_CHANGED:
  1228. return listeningChildren;
  1229. case HierarchyEvent.ANCESTOR_MOVED:
  1230. case HierarchyEvent.ANCESTOR_RESIZED:
  1231. return listeningBoundsChildren;
  1232. default:
  1233. return 0;
  1234. }
  1235. }
  1236. final int createHierarchyEvents(int id, Component changed,
  1237. Container changedParent, long changeFlags, boolean enabledOnToolkit)
  1238. {
  1239. assert Thread.holdsLock(getTreeLock());
  1240. int listeners = getListenersCount(id, enabledOnToolkit);
  1241. for (int count = listeners, i = 0; count > 0; i++) {
  1242. count -= component[i].createHierarchyEvents(id, changed,
  1243. changedParent, changeFlags, enabledOnToolkit);
  1244. }
  1245. return listeners +
  1246. super.createHierarchyEvents(id, changed, changedParent,
  1247. changeFlags, enabledOnToolkit);
  1248. }
  1249. final void createChildHierarchyEvents(int id, long changeFlags,
  1250. boolean enabledOnToolkit)
  1251. {
  1252. assert Thread.holdsLock(getTreeLock());
  1253. if (ncomponents == 0) {
  1254. return;
  1255. }
  1256. int listeners = getListenersCount(id, enabledOnToolkit);
  1257. for (int count = listeners, i = 0; count > 0; i++) {
  1258. count -= component[i].createHierarchyEvents(id, this, parent,
  1259. changeFlags, enabledOnToolkit);
  1260. }
  1261. }
  1262. /**
  1263. * Gets the layout manager for this container.
  1264. * @see #doLayout
  1265. * @see #setLayout
  1266. */
  1267. public LayoutManager getLayout() {
  1268. return layoutMgr;
  1269. }
  1270. /**
  1271. * Sets the layout manager for this container.
  1272. * @param mgr the specified layout manager
  1273. * @see #doLayout
  1274. * @see #getLayout
  1275. */
  1276. public void setLayout(LayoutManager mgr) {
  1277. layoutMgr = mgr;
  1278. if (valid) {
  1279. invalidate();
  1280. }
  1281. }
  1282. /**
  1283. * Causes this container to lay out its components. Most programs
  1284. * should not call this method directly, but should invoke
  1285. * the <code>validate</code> method instead.
  1286. * @see LayoutManager#layoutContainer
  1287. * @see #setLayout
  1288. * @see #validate
  1289. * @since JDK1.1
  1290. */
  1291. public void doLayout() {
  1292. layout();
  1293. }
  1294. /**
  1295. * @deprecated As of JDK version 1.1,
  1296. * replaced by <code>doLayout()</code>.
  1297. */
  1298. @Deprecated
  1299. public void layout() {
  1300. LayoutManager layoutMgr = this.layoutMgr;
  1301. if (layoutMgr != null) {
  1302. layoutMgr.layoutContainer(this);
  1303. }
  1304. }
  1305. /**
  1306. * Invalidates the container. The container and all parents
  1307. * above it are marked as needing to be laid out. This method can
  1308. * be called often, so it needs to execute quickly.
  1309. * @see #validate
  1310. * @see #layout
  1311. * @see LayoutManager
  1312. */
  1313. public void invalidate() {
  1314. LayoutManager layoutMgr = this.layoutMgr;
  1315. if (layoutMgr instanceof LayoutManager2) {
  1316. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  1317. lm.invalidateLayout(this);
  1318. }
  1319. super.invalidate();
  1320. }
  1321. /**
  1322. * Validates this container and all of its subcomponents.
  1323. * <p>
  1324. * The <code>validate</code> method is used to cause a container
  1325. * to lay out its subcomponents again. It should be invoked when
  1326. * this container's subcomponents are modified (added to or
  1327. * removed from the container, or layout-related information
  1328. * changed) after the container has been displayed.
  1329. *
  1330. * @see #add(java.awt.Component)
  1331. * @see Component#invalidate
  1332. * @see javax.swing.JComponent#revalidate()
  1333. */
  1334. public void validate() {
  1335. /* Avoid grabbing lock unless really necessary. */
  1336. if (!valid) {
  1337. boolean updateCur = false;
  1338. synchronized (getTreeLock()) {
  1339. if (!valid && peer != null) {
  1340. ContainerPeer p = null;
  1341. if (peer instanceof ContainerPeer) {
  1342. p = (ContainerPeer) peer;
  1343. }
  1344. if (p != null) {
  1345. p.beginValidate();
  1346. }
  1347. validateTree();
  1348. valid = true;
  1349. if (p != null) {
  1350. p.endValidate();
  1351. updateCur = isVisible();
  1352. }
  1353. }
  1354. }
  1355. if (updateCur) {
  1356. updateCursorImmediately();
  1357. }
  1358. }
  1359. }
  1360. /**
  1361. * Recursively descends the container tree and recomputes the
  1362. * layout for any subtrees marked as needing it (those marked as
  1363. * invalid). Synchronization should be provided by the method
  1364. * that calls this one: <code>validate</code>.
  1365. */
  1366. protected void validateTree() {
  1367. if (!valid) {
  1368. if (peer instanceof ContainerPeer) {
  1369. ((ContainerPeer)peer).beginLayout();
  1370. }
  1371. doLayout();
  1372. Component component[] = this.component;
  1373. for (int i = 0 ; i < ncomponents ; ++i) {
  1374. Component comp = component[i];
  1375. if ( (comp instanceof Container)
  1376. && !(comp instanceof Window)
  1377. && !comp.valid) {
  1378. ((Container)comp).validateTree();
  1379. } else {
  1380. comp.validate();
  1381. }
  1382. }
  1383. if (peer instanceof ContainerPeer) {
  1384. ((ContainerPeer)peer).endLayout();
  1385. }
  1386. }
  1387. valid = true;
  1388. }
  1389. /**
  1390. * Recursively descends the container tree and invalidates all
  1391. * contained components.
  1392. */
  1393. void invalidateTree() {
  1394. synchronized (getTreeLock()) {
  1395. for (int i = 0; i < ncomponents; ++i) {
  1396. Component comp = component[i];
  1397. if (comp instanceof Container) {
  1398. ((Container)comp).invalidateTree();
  1399. }
  1400. else {
  1401. if (comp.valid) {
  1402. comp.invalidate();
  1403. }
  1404. }
  1405. }
  1406. if (valid) {
  1407. invalidate();
  1408. }
  1409. }
  1410. }
  1411. /**
  1412. * Sets the font of this container.
  1413. * @param f The font to become this container's font.
  1414. * @see Component#getFont
  1415. * @since JDK1.0
  1416. */
  1417. public void setFont(Font f) {
  1418. boolean shouldinvalidate = false;
  1419. Font oldfont = getFont();
  1420. super.setFont(f);
  1421. Font newfont = getFont();
  1422. if (newfont != oldfont && (oldfont == null ||
  1423. !oldfont.equals(newfont))) {
  1424. invalidateTree();
  1425. }
  1426. }
  1427. /**
  1428. * Returns the preferred size of this container.
  1429. * @return an instance of <code>Dimension</code> that represents
  1430. * the preferred size of this container.
  1431. * @see #getMinimumSize
  1432. * @see #getLayout
  1433. * @see LayoutManager#preferredLayoutSize(Container)
  1434. * @see Component#getPreferredSize
  1435. */
  1436. public Dimension getPreferredSize() {
  1437. return preferredSize();
  1438. }
  1439. /**
  1440. * @deprecated As of JDK version 1.1,
  1441. * replaced by <code>getPreferredSize()</code>.
  1442. */
  1443. @Deprecated
  1444. public Dimension preferredSize() {
  1445. /* Avoid grabbing the lock if a reasonable cached size value
  1446. * is available.
  1447. */
  1448. Dimension dim = prefSize;
  1449. if (dim == null || !(isPreferredSizeSet() || isValid())) {
  1450. synchronized (getTreeLock()) {
  1451. prefSize = (layoutMgr != null) ?
  1452. layoutMgr.preferredLayoutSize(this) :
  1453. super.preferredSize();
  1454. dim = prefSize;
  1455. }
  1456. }
  1457. if (dim != null){
  1458. return new Dimension(dim);
  1459. }
  1460. else{
  1461. return dim;
  1462. }
  1463. }
  1464. /**
  1465. * Returns the minimum size of this container.
  1466. * @return an instance of <code>Dimension</code> that represents
  1467. * the minimum size of this container.
  1468. * @see #getPreferredSize
  1469. * @see #getLayout
  1470. * @see LayoutManager#minimumLayoutSize(Container)
  1471. * @see Component#getMinimumSize
  1472. * @since JDK1.1
  1473. */
  1474. public Dimension getMinimumSize() {
  1475. return minimumSize();
  1476. }
  1477. /**
  1478. * @deprecated As of JDK version 1.1,
  1479. * replaced by <code>getMinimumSize()</code>.
  1480. */
  1481. @Deprecated
  1482. public Dimension minimumSize() {
  1483. /* Avoid grabbing the lock if a reasonable cached size value
  1484. * is available.
  1485. */
  1486. Dimension dim = minSize;
  1487. if (dim == null || !(isMinimumSizeSet() || isValid())) {
  1488. synchronized (getTreeLock()) {
  1489. minSize = (layoutMgr != null) ?
  1490. layoutMgr.minimumLayoutSize(this) :
  1491. super.minimumSize();
  1492. dim = minSize;
  1493. }
  1494. }
  1495. if (dim != null){
  1496. return new Dimension(dim);
  1497. }
  1498. else{
  1499. return dim;
  1500. }
  1501. }
  1502. /**
  1503. * Returns the maximum size of this container.
  1504. * @see #getPreferredSize
  1505. */
  1506. public Dimension getMaximumSize() {
  1507. /* Avoid grabbing the lock if a reasonable cached size value
  1508. * is available.
  1509. */
  1510. Dimension dim = maxSize;
  1511. if (dim == null || !(isMaximumSizeSet() || isValid())) {
  1512. synchronized (getTreeLock()) {
  1513. if (layoutMgr instanceof LayoutManager2) {
  1514. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  1515. maxSize = lm.maximumLayoutSize(this);
  1516. } else {
  1517. maxSize = super.getMaximumSize();
  1518. }
  1519. dim = maxSize;
  1520. }
  1521. }
  1522. if (dim != null){
  1523. return new Dimension(dim);
  1524. }
  1525. else{
  1526. return dim;
  1527. }
  1528. }
  1529. /**
  1530. * Returns the alignment along the x axis. This specifies how
  1531. * the component would like to be aligned relative to other
  1532. * components. The value should be a number between 0 and 1
  1533. * where 0 represents alignment along the origin, 1 is aligned
  1534. * the furthest away from the origin, 0.5 is centered, etc.
  1535. */
  1536. public float getAlignmentX() {
  1537. float xAlign;
  1538. if (layoutMgr instanceof LayoutManager2) {
  1539. synchronized (getTreeLock()) {
  1540. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  1541. xAlign = lm.getLayoutAlignmentX(this);
  1542. }
  1543. } else {
  1544. xAlign = super.getAlignmentX();
  1545. }
  1546. return xAlign;
  1547. }
  1548. /**
  1549. * Returns the alignment along the y axis. This specifies how
  1550. * the component would like to be aligned relative to other
  1551. * components. The value should be a number between 0 and 1
  1552. * where 0 represents alignment along the origin, 1 is aligned
  1553. * the furthest away from the origin, 0.5 is centered, etc.
  1554. */
  1555. public float getAlignmentY() {
  1556. float yAlign;
  1557. if (layoutMgr instanceof LayoutManager2) {
  1558. synchronized (getTreeLock()) {
  1559. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  1560. yAlign = lm.getLayoutAlignmentY(this);
  1561. }
  1562. } else {
  1563. yAlign = super.getAlignmentY();
  1564. }
  1565. return yAlign;
  1566. }
  1567. /**
  1568. * Paints the container. This forwards the paint to any lightweight
  1569. * components that are children of this container. If this method is
  1570. * reimplemented, super.paint(g) should be called so that lightweight
  1571. * components are properly rendered. If a child component is entirely
  1572. * clipped by the current clipping setting in g, paint() will not be
  1573. * forwarded to that child.
  1574. *
  1575. * @param g the specified Graphics window
  1576. * @see Component#update(Graphics)
  1577. */
  1578. public void paint(Graphics g) {
  1579. if (isShowing()) {
  1580. if (printing) {
  1581. synchronized (this) {
  1582. if (printing) {
  1583. if (printingThreads.contains(Thread.currentThread())) {
  1584. return;
  1585. }
  1586. }
  1587. }
  1588. }
  1589. // The container is showing on screen and
  1590. // this paint() is not called from print().
  1591. // Paint self and forward the paint to lightweight subcomponents.
  1592. // super.paint(); -- Don't bother, since it's a NOP.
  1593. GraphicsCallback.PaintCallback.getInstance().
  1594. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
  1595. }
  1596. }
  1597. /**
  1598. * Updates the container. This forwards the update to any lightweight
  1599. * components that are children of this container. If this method is
  1600. * reimplemented, super.update(g) should be called so that lightweight
  1601. * components are properly rendered. If a child component is entirely
  1602. * clipped by the current clipping setting in g, update() will not be
  1603. * forwarded to that child.
  1604. *
  1605. * @param g the specified Graphics window
  1606. * @see Component#update(Graphics)
  1607. */
  1608. public void update(Graphics g) {
  1609. if (isShowing()) {
  1610. if (! (peer instanceof LightweightPeer)) {
  1611. g.clearRect(0, 0, width, height);
  1612. }
  1613. paint(g);
  1614. }
  1615. }
  1616. /**
  1617. * Prints the container. This forwards the print to any lightweight
  1618. * components that are children of this container. If this method is
  1619. * reimplemented, super.print(g) should be called so that lightweight
  1620. * components are properly rendered. If a child component is entirely
  1621. * clipped by the current clipping setting in g, print() will not be
  1622. * forwarded to that child.
  1623. *
  1624. * @param g the specified Graphics window
  1625. * @see Component#update(Graphics)
  1626. */
  1627. public void print(Graphics g) {
  1628. if (isShowing()) {
  1629. Thread t = Thread.currentThread();
  1630. try {
  1631. synchronized (this) {
  1632. if (printingThreads == null) {
  1633. printingThreads = new HashSet();
  1634. }
  1635. printingThreads.add(t);
  1636. printing = true;
  1637. }
  1638. super.print(g); // By default, Component.print() calls paint()
  1639. } finally {
  1640. synchronized (this) {
  1641. printingThreads.remove(t);
  1642. printing = !printingThreads.isEmpty();
  1643. }
  1644. }
  1645. GraphicsCallback.PrintCallback.getInstance().
  1646. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
  1647. }
  1648. }
  1649. /**
  1650. * Paints each of the components in this container.
  1651. * @param g the graphics context.
  1652. * @see Component#paint
  1653. * @see Component#paintAll
  1654. */
  1655. public void paintComponents(Graphics g) {
  1656. if (isShowing()) {
  1657. GraphicsCallback.PaintAllCallback.getInstance().
  1658. runComponents(component, g, GraphicsCallback.TWO_PASSES);
  1659. }
  1660. }
  1661. /**
  1662. * Simulates the peer callbacks into java.awt for printing of
  1663. * lightweight Containers.
  1664. * @param g the graphics context to use for printing.
  1665. * @see Component#printAll
  1666. * @see #printComponents
  1667. */
  1668. void lightweightPaint(Graphics g) {
  1669. super.lightweightPaint(g);
  1670. paintHeavyweightComponents(g);
  1671. }
  1672. /**
  1673. * Prints all the heavyweight subcomponents.
  1674. */
  1675. void paintHeavyweightComponents(Graphics g) {
  1676. if (isShowing()) {
  1677. GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
  1678. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
  1679. GraphicsCallback.HEAVYWEIGHTS);
  1680. }
  1681. }
  1682. /**
  1683. * Prints each of the components in this container.
  1684. * @param g the graphics context.
  1685. * @see Component#print
  1686. * @see Component#printAll
  1687. */
  1688. public void printComponents(Graphics g) {
  1689. if (isShowing()) {
  1690. GraphicsCallback.PrintAllCallback.getInstance().
  1691. runComponents(component, g, GraphicsCallback.TWO_PASSES);
  1692. }
  1693. }
  1694. /**
  1695. * Simulates the peer callbacks into java.awt for printing of
  1696. * lightweight Containers.
  1697. * @param g the graphics context to use for printing.
  1698. * @see Component#printAll
  1699. * @see #printComponents
  1700. */
  1701. void lightweightPrint(Graphics g) {
  1702. super.lightweightPrint(g);
  1703. printHeavyweightComponents(g);
  1704. }
  1705. /**
  1706. * Prints all the heavyweight subcomponents.
  1707. */
  1708. void printHeavyweightComponents(Graphics g) {
  1709. if (isShowing()) {
  1710. GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
  1711. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
  1712. GraphicsCallback.HEAVYWEIGHTS);
  1713. }
  1714. }
  1715. /**
  1716. * Adds the specified container listener to receive container events
  1717. * from this container.
  1718. * If l is null, no exception is thrown and no action is performed.
  1719. *
  1720. * @param l the container listener
  1721. *
  1722. * @see #removeContainerListener
  1723. * @see #getContainerListeners
  1724. */
  1725. public synchronized void addContainerListener(ContainerListener l) {
  1726. if (l == null) {
  1727. return;
  1728. }
  1729. containerListener = AWTEventMulticaster.add(containerListener, l);
  1730. newEventsOnly = true;
  1731. }
  1732. /**
  1733. * Removes the specified container listener so it no longer receives
  1734. * container events from this container.
  1735. * If l is null, no exception is thrown and no action is performed.
  1736. *
  1737. * @param l the container listener
  1738. *
  1739. * @see #addContainerListener
  1740. * @see #getContainerListeners
  1741. */
  1742. public synchronized void removeContainerListener(ContainerListener l) {
  1743. if (l == null) {
  1744. return;
  1745. }
  1746. containerListener = AWTEventMulticaster.remove(containerListener, l);
  1747. }
  1748. /**
  1749. * Returns an array of all the container listeners
  1750. * registered on this container.
  1751. *
  1752. * @return all of this container's <code>ContainerListener</code>s
  1753. * or an empty array if no container
  1754. * listeners are currently registered
  1755. *
  1756. * @see #addContainerListener
  1757. * @see #removeContainerListener
  1758. * @since 1.4
  1759. */
  1760. public synchronized ContainerListener[] getContainerListeners() {
  1761. return (ContainerListener[]) (getListeners(ContainerListener.class));
  1762. }
  1763. /**
  1764. * Returns an array of all the objects currently registered
  1765. * as <code><em>Foo</em>Listener</code>s
  1766. * upon this <code>Container</code>.
  1767. * <code><em>Foo</em>Listener</code>s are registered using the
  1768. * <code>add<em>Foo</em>Listener</code> method.
  1769. *
  1770. * <p>
  1771. * You can specify the <code>listenerType</code> argument
  1772. * with a class literal, such as
  1773. * <code><em>Foo</em>Listener.class</code>.
  1774. * For example, you can query a
  1775. * <code>Container</code> <code>c</code>
  1776. * for its container listeners with the following code:
  1777. *
  1778. * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
  1779. *
  1780. * If no such listeners exist, this method returns an empty array.
  1781. *
  1782. * @param listenerType the type of listeners requested; this parameter
  1783. * should specify an interface that descends from
  1784. * <code>java.util.EventListener</code>
  1785. * @return an array of all objects registered as
  1786. * <code><em>Foo</em>Listener</code>s on this container,
  1787. * or an empty array if no such listeners have been added
  1788. * @exception ClassCastException if <code>listenerType</code>
  1789. * doesn't specify a class or interface that implements
  1790. * <code>java.util.EventListener</code>
  1791. *
  1792. * @see #getContainerListeners
  1793. *
  1794. * @since 1.3
  1795. */
  1796. public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
  1797. EventListener l = null;
  1798. if (listenerType == ContainerListener.class) {
  1799. l = containerListener;
  1800. } else {
  1801. return super.getListeners(listenerType);
  1802. }
  1803. return AWTEventMulticaster.getListeners(l, listenerType);
  1804. }
  1805. // REMIND: remove when filtering is done at lower level
  1806. boolean eventEnabled(AWTEvent e) {
  1807. int id = e.getID();
  1808. if (id == ContainerEvent.COMPONENT_ADDED ||
  1809. id == ContainerEvent.COMPONENT_REMOVED) {
  1810. if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  1811. containerListener != null) {
  1812. return true;
  1813. }
  1814. return false;
  1815. }
  1816. return super.eventEnabled(e);
  1817. }
  1818. /**
  1819. * Processes events on this container. If the event is a
  1820. * <code>ContainerEvent</code>, it invokes the
  1821. * <code>processContainerEvent</code> method, else it invokes
  1822. * its superclass's <code>processEvent</code>.
  1823. * <p>Note that if the event parameter is <code>null</code>
  1824. * the behavior is unspecified and may result in an
  1825. * exception.
  1826. *
  1827. * @param e the event
  1828. */
  1829. protected void processEvent(AWTEvent e) {
  1830. if (e instanceof ContainerEvent) {
  1831. processContainerEvent((ContainerEvent)e);
  1832. return;
  1833. }
  1834. super.processEvent(e);
  1835. }
  1836. /**
  1837. * Processes container events occurring on this container by
  1838. * dispatching them to any registered ContainerListener objects.
  1839. * NOTE: This method will not be called unless container events
  1840. * are enabled for this component; this happens when one of the
  1841. * following occurs:
  1842. * <ul>
  1843. * <li>A ContainerListener object is registered via
  1844. * <code>addContainerListener</code>
  1845. * <li>Container events are enabled via <code>enableEvents</code>
  1846. * </ul>
  1847. * <p>Note that if the event parameter is <code>null</code>
  1848. * the behavior is unspecified and may result in an
  1849. * exception.
  1850. *
  1851. * @param e the container event
  1852. * @see Component#enableEvents
  1853. */
  1854. protected void processContainerEvent(ContainerEvent e) {
  1855. ContainerListener listener = containerListener;
  1856. if (listener != null) {
  1857. switch(e.getID()) {
  1858. case ContainerEvent.COMPONENT_ADDED:
  1859. listener.componentAdded(e);
  1860. break;
  1861. case ContainerEvent.COMPONENT_REMOVED:
  1862. listener.componentRemoved(e);
  1863. break;
  1864. }
  1865. }
  1866. }
  1867. /*
  1868. * Dispatches an event to this component or one of its sub components.
  1869. * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
  1870. * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
  1871. * here instead of in processComponentEvent because ComponentEvents
  1872. * may not be enabled for this Container.
  1873. * @param e the event
  1874. */
  1875. void dispatchEventImpl(AWTEvent e) {
  1876. if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
  1877. // event was sent to a lightweight component. The
  1878. // native-produced event sent to the native container
  1879. // must be properly disposed of by the peer, so it
  1880. // gets forwarded. If the native host has been removed
  1881. // as a result of the sending the lightweight event,
  1882. // the peer reference will be null.
  1883. e.consume();
  1884. if (peer != null) {
  1885. peer.handleEvent(e);
  1886. }
  1887. return;
  1888. }
  1889. super.dispatchEventImpl(e);
  1890. synchronized (getTreeLock()) {
  1891. switch (e.getID()) {
  1892. case ComponentEvent.COMPONENT_RESIZED:
  1893. createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
  1894. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  1895. break;
  1896. case ComponentEvent.COMPONENT_MOVED:
  1897. createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
  1898. Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  1899. break;
  1900. default:
  1901. break;
  1902. }
  1903. }
  1904. }
  1905. /*
  1906. * Dispatches an event to this component, without trying to forward
  1907. * it to any subcomponents
  1908. * @param e the event
  1909. */
  1910. void dispatchEventToSelf(AWTEvent e) {
  1911. super.dispatchEventImpl(e);
  1912. }
  1913. /**
  1914. * Fetchs the top-most (deepest) lightweight component that is interested
  1915. * in receiving mouse events.
  1916. */
  1917. Component getMouseEventTarget(int x, int y, boolean includeSelf) {
  1918. return getMouseEventTarget(x, y, includeSelf,
  1919. MouseEventTargetFilter.FILTER,
  1920. !SEARCH_HEAVYWEIGHTS);
  1921. }
  1922. /**
  1923. * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
  1924. */
  1925. Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
  1926. return getMouseEventTarget(x, y, includeSelf,
  1927. DropTargetEventTargetFilter.FILTER,
  1928. SEARCH_HEAVYWEIGHTS);
  1929. }
  1930. /**
  1931. * A private version of getMouseEventTarget which has two additional
  1932. * controllable behaviors. This method searches for the top-most
  1933. * descendant of this container that contains the given coordinates
  1934. * and is accepted by the given filter. The search will be constrained to
  1935. * lightweight descendants if the last argument is <code>false</code>.
  1936. *
  1937. * @param filter EventTargetFilter instance to determine whether the
  1938. * given component is a valid target for this event.
  1939. * @param searchHeavyweights if <code>false</false>, the method
  1940. * will bypass heavyweight components during the search.
  1941. */
  1942. private Component getMouseEventTarget(int x, int y, boolean includeSelf,
  1943. EventTargetFilter filter,
  1944. boolean searchHeavyweights) {
  1945. Component comp = null;
  1946. if (searchHeavyweights) {
  1947. comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
  1948. SEARCH_HEAVYWEIGHTS,
  1949. searchHeavyweights);
  1950. }
  1951. if (comp == null || comp == this) {
  1952. comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
  1953. !SEARCH_HEAVYWEIGHTS,
  1954. searchHeavyweights);
  1955. }
  1956. return comp;
  1957. }
  1958. /**
  1959. * A private version of getMouseEventTarget which has three additional
  1960. * controllable behaviors. This method searches for the top-most
  1961. * descendant of this container that contains the given coordinates
  1962. * and is accepted by the given filter. The search will be constrained to
  1963. * descendants of only lightweight children or only heavyweight children
  1964. * of this container depending on searchHeavyweightChildren. The search will
  1965. * be constrained to only lightweight descendants of the searched children
  1966. * of this container if searchHeavyweightDescendants is <code>false</code>.
  1967. *
  1968. * @param filter EventTargetFilter instance to determine whether the
  1969. * selected component is a valid target for this event.
  1970. * @param searchHeavyweightChildren if <code>true</false>, the method
  1971. * will bypass immediate lightweight children during the search.
  1972. * If <code>false</code>, the methods will bypass immediate
  1973. * heavyweight children during the search.
  1974. * @param searchHeavyweightDescendants if <code>false</false>, the method
  1975. * will bypass heavyweight descendants which are not immediate
  1976. * children during the search. If <code>true</code>, the method
  1977. * will traverse both lightweight and heavyweight descendants during
  1978. * the search.
  1979. */
  1980. private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
  1981. EventTargetFilter filter,
  1982. boolean searchHeavyweightChildren,
  1983. boolean searchHeavyweightDescendants) {
  1984. int ncomponents = this.ncomponents;
  1985. Component component[] = this.component;
  1986. for (int i = 0 ; i < ncomponents ; i++) {
  1987. Component comp = component[i];
  1988. if (comp != null && comp.visible &&
  1989. ((!searchHeavyweightChildren &&
  1990. comp.peer instanceof LightweightPeer) ||
  1991. (searchHeavyweightChildren &&
  1992. !(comp.peer instanceof LightweightPeer))) &&
  1993. comp.contains(x - comp.x, y - comp.y)) {
  1994. // found a component that intersects the point, see if there is
  1995. // a deeper possibility.
  1996. if (comp instanceof Container) {
  1997. Container child = (Container) comp;
  1998. Component deeper = child.getMouseEventTarget(x - child.x,
  1999. y - child.y,
  2000. includeSelf,
  2001. filter,
  2002. searchHeavyweightDescendants);
  2003. if (deeper != null) {
  2004. return deeper;
  2005. }
  2006. } else {
  2007. if (filter.accept(comp)) {
  2008. // there isn't a deeper target, but this component is a
  2009. // target
  2010. return comp;
  2011. }
  2012. }
  2013. }
  2014. }
  2015. boolean isPeerOK;
  2016. boolean isMouseOverMe;
  2017. isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
  2018. isMouseOverMe = contains(x,y);
  2019. // didn't find a child target, return this component if it's a possible
  2020. // target
  2021. if (isMouseOverMe && isPeerOK && filter.accept(this)) {
  2022. return this;
  2023. }
  2024. // no possible target
  2025. return null;
  2026. }
  2027. static interface EventTargetFilter {
  2028. boolean accept(final Component comp);
  2029. }
  2030. static class MouseEventTargetFilter implements EventTargetFilter {
  2031. static final EventTargetFilter FILTER = new MouseEventTargetFilter();
  2032. private MouseEventTargetFilter() {}
  2033. public boolean accept(final Component comp) {
  2034. return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
  2035. || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
  2036. || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
  2037. || comp.mouseListener != null
  2038. || comp.mouseMotionListener != null
  2039. || comp.mouseWheelListener != null;
  2040. }
  2041. }
  2042. static class DropTargetEventTargetFilter implements EventTargetFilter {
  2043. static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();
  2044. private DropTargetEventTargetFilter() {}
  2045. public boolean accept(final Component comp) {
  2046. DropTarget dt = comp.getDropTarget();
  2047. return dt != null && dt.isActive();
  2048. }
  2049. }
  2050. /**
  2051. * This is called by lightweight components that want the containing
  2052. * windowed parent to enable some kind of events on their behalf.
  2053. * This is needed for events that are normally only dispatched to
  2054. * windows to be accepted so that they can be forwarded downward to
  2055. * the lightweight component that has enabled them.
  2056. */
  2057. void proxyEnableEvents(long events) {
  2058. if (peer instanceof LightweightPeer) {
  2059. // this container is lightweight.... continue sending it
  2060. // upward.
  2061. if (parent != null) {
  2062. parent.proxyEnableEvents(events);
  2063. }
  2064. } else {
  2065. // This is a native container, so it needs to host
  2066. // one of it's children. If this function is called before
  2067. // a peer has been created we don't yet have a dispatcher
  2068. // because it has not yet been determined if this instance
  2069. // is lightweight.
  2070. if (dispatcher != null) {
  2071. dispatcher.enableEvents(events);
  2072. }
  2073. }
  2074. }
  2075. /**
  2076. * @deprecated As of JDK version 1.1,
  2077. * replaced by <code>dispatchEvent(AWTEvent e)</code>
  2078. */
  2079. @Deprecated
  2080. public void deliverEvent(Event e) {
  2081. Component comp = getComponentAt(e.x, e.y);
  2082. if ((comp != null) && (comp != this)) {
  2083. e.translate(-comp.x, -comp.y);
  2084. comp.deliverEvent(e);
  2085. } else {
  2086. postEvent(e);
  2087. }
  2088. }
  2089. /**
  2090. * Locates the component that contains the x,y position. The
  2091. * top-most child component is returned in the case where there
  2092. * is overlap in the components. This is determined by finding
  2093. * the component closest to the index 0 that claims to contain
  2094. * the given point via Component.contains(), except that Components
  2095. * which have native peers take precedence over those which do not
  2096. * (i.e., lightweight Components).
  2097. *
  2098. * @param x the <i>x</i> coordinate
  2099. * @param y the <i>y</i> coordinate
  2100. * @return null if the component does not contain the position.
  2101. * If there is no child component at the requested point and the
  2102. * point is within the bounds of the container the container itself
  2103. * is returned; otherwise the top-most child is returned.
  2104. * @see Component#contains
  2105. * @since JDK1.1
  2106. */
  2107. public Component getComponentAt(int x, int y) {
  2108. return locate(x, y);
  2109. }
  2110. /**
  2111. * @deprecated As of JDK version 1.1,
  2112. * replaced by <code>getComponentAt(int, int)</code>.
  2113. */
  2114. @Deprecated
  2115. public Component locate(int x, int y) {
  2116. if (!contains(x, y)) {
  2117. return null;
  2118. }
  2119. synchronized (getTreeLock()) {
  2120. // Two passes: see comment in sun.awt.SunGraphicsCallback
  2121. for (int i = 0 ; i < ncomponents ; i++) {
  2122. Component comp = component[i];
  2123. if (comp != null &&
  2124. !(comp.peer instanceof LightweightPeer)) {
  2125. if (comp.contains(x - comp.x, y - comp.y)) {
  2126. return comp;
  2127. }
  2128. }
  2129. }
  2130. for (int i = 0 ; i < ncomponents ; i++) {
  2131. Component comp = component[i];
  2132. if (comp != null &&
  2133. comp.peer instanceof LightweightPeer) {
  2134. if (comp.contains(x - comp.x, y - comp.y)) {
  2135. return comp;
  2136. }
  2137. }
  2138. }
  2139. }
  2140. return this;
  2141. }
  2142. /**
  2143. * Gets the component that contains the specified point.
  2144. * @param p the point.
  2145. * @return returns the component that contains the point,
  2146. * or <code>null</code> if the component does
  2147. * not contain the point.
  2148. * @see Component#contains
  2149. * @since JDK1.1
  2150. */
  2151. public Component getComponentAt(Point p) {
  2152. return getComponentAt(p.x, p.y);
  2153. }
  2154. /**
  2155. * Returns the position of the mouse pointer in this <code>Container</code>'s
  2156. * coordinate space if the <code>Container</code> is under the mouse pointer,
  2157. * otherwise returns <code>null</code>.
  2158. * This method is similar to {@link Component#getMousePosition()} with the exception
  2159. * that it can take the <code>Container</code>'s children into account.
  2160. * If <code>allowChildren</code> is <code>false</code>, this method will return
  2161. * a non-null value only if the mouse pointer is above the <code>Container</code>
  2162. * directly, not above the part obscured by children.
  2163. * If <code>allowChildren</code> is <code>true</code>, this method returns
  2164. * a non-null value if the mouse pointer is above <code>Container</code> or any
  2165. * of its descendants.
  2166. *
  2167. * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
  2168. * @param allowChildren true if children should be taken into account
  2169. * @see Component#getMousePosition
  2170. * @return mouse coordinates relative to this <code>Component</code>, or null
  2171. * @since 1.5
  2172. */
  2173. public Point getMousePosition(boolean allowChildren) throws HeadlessException {
  2174. if (GraphicsEnvironment.isHeadless()) {
  2175. throw new HeadlessException();
  2176. }
  2177. PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged(
  2178. new java.security.PrivilegedAction() {
  2179. public Object run() {
  2180. return MouseInfo.getPointerInfo();
  2181. }
  2182. }
  2183. );
  2184. synchronized (getTreeLock()) {
  2185. Component inTheSameWindow = findUnderMouseInWindow(pi);
  2186. if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
  2187. return pointRelativeToComponent(pi.getLocation());
  2188. }
  2189. return null;
  2190. }
  2191. }
  2192. boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
  2193. return this == comp || (allowChildren && isParentOf(comp));
  2194. }
  2195. /**
  2196. * Locates the visible child component that contains the specified
  2197. * position. The top-most child component is returned in the case
  2198. * where there is overlap in the components. If the containing child
  2199. * component is a Container, this method will continue searching for
  2200. * the deepest nested child component. Components which are not
  2201. * visible are ignored during the search.<p>
  2202. *
  2203. * The findComponentAt method is different from getComponentAt in
  2204. * that getComponentAt only searches the Container's immediate
  2205. * children; if the containing component is a Container,
  2206. * findComponentAt will search that child to find a nested component.
  2207. *
  2208. * @param x the <i>x</i> coordinate
  2209. * @param y the <i>y</i> coordinate
  2210. * @return null if the component does not contain the position.
  2211. * If there is no child component at the requested point and the
  2212. * point is within the bounds of the container the container itself
  2213. * is returned.
  2214. * @see Component#contains
  2215. * @see #getComponentAt
  2216. * @since 1.2
  2217. */
  2218. public Component findComponentAt(int x, int y) {
  2219. synchronized (getTreeLock()) {
  2220. return findComponentAt(x, y, true);
  2221. }
  2222. }
  2223. /**
  2224. * Private version of findComponentAt which has a controllable
  2225. * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
  2226. * Components during the search. This behavior is used by the
  2227. * lightweight cursor support in sun.awt.GlobalCursorManager.
  2228. * The cursor code calls this function directly via native code.
  2229. *
  2230. * The addition of this feature is temporary, pending the
  2231. * adoption of new, public API which exports this feature.
  2232. */
  2233. final Component findComponentAt(int x, int y, boolean ignoreEnabled)
  2234. {
  2235. if (isRecursivelyVisible()){
  2236. return findComponentAtImpl(x, y, ignoreEnabled);
  2237. }
  2238. return null;
  2239. }
  2240. final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){
  2241. if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
  2242. return null;
  2243. }
  2244. int ncomponents = this.ncomponents;
  2245. Component component[] = this.component;
  2246. // Two passes: see comment in sun.awt.SunGraphicsCallback
  2247. for (int i = 0 ; i < ncomponents ; i++) {
  2248. Component comp = component[i];
  2249. if (comp != null &&
  2250. !(comp.peer instanceof LightweightPeer)) {
  2251. if (comp instanceof Container) {
  2252. comp = ((Container)comp).findComponentAtImpl(x - comp.x,
  2253. y - comp.y,
  2254. ignoreEnabled);
  2255. } else {
  2256. comp = comp.locate(x - comp.x, y - comp.y);
  2257. }
  2258. if (comp != null && comp.visible &&
  2259. (ignoreEnabled || comp.enabled))
  2260. {
  2261. return comp;
  2262. }
  2263. }
  2264. }
  2265. for (int i = 0 ; i < ncomponents ; i++) {
  2266. Component comp = component[i];
  2267. if (comp != null &&
  2268. comp.peer instanceof LightweightPeer) {
  2269. if (comp instanceof Container) {
  2270. comp = ((Container)comp).findComponentAtImpl(x - comp.x,
  2271. y - comp.y,
  2272. ignoreEnabled);
  2273. } else {
  2274. comp = comp.locate(x - comp.x, y - comp.y);
  2275. }
  2276. if (comp != null && comp.visible &&
  2277. (ignoreEnabled || comp.enabled))
  2278. {
  2279. return comp;
  2280. }
  2281. }
  2282. }
  2283. return this;
  2284. }
  2285. /**
  2286. * Locates the visible child component that contains the specified
  2287. * point. The top-most child component is returned in the case
  2288. * where there is overlap in the components. If the containing child
  2289. * component is a Container, this method will continue searching for
  2290. * the deepest nested child component. Components which are not
  2291. * visible are ignored during the search.<p>
  2292. *
  2293. * The findComponentAt method is different from getComponentAt in
  2294. * that getComponentAt only searches the Container's immediate
  2295. * children; if the containing component is a Container,
  2296. * findComponentAt will search that child to find a nested component.
  2297. *
  2298. * @param p the point.
  2299. * @return null if the component does not contain the position.
  2300. * If there is no child component at the requested point and the
  2301. * point is within the bounds of the container the container itself
  2302. * is returned.
  2303. * @see Component#contains
  2304. * @see #getComponentAt
  2305. * @since 1.2
  2306. */
  2307. public Component findComponentAt(Point p) {
  2308. return findComponentAt(p.x, p.y);
  2309. }
  2310. /**
  2311. * Makes this Container displayable by connecting it to
  2312. * a native screen resource. Making a container displayable will
  2313. * cause all of its children to be made displayable.
  2314. * This method is called internally by the toolkit and should
  2315. * not be called directly by programs.
  2316. * @see Component#isDisplayable
  2317. * @see #removeNotify
  2318. */
  2319. public void addNotify() {
  2320. synchronized (getTreeLock()) {
  2321. // addNotify() on the children may cause proxy event enabling
  2322. // on this instance, so we first call super.addNotify() and
  2323. // possibly create an lightweight event dispatcher before calling
  2324. // addNotify() on the children which may be lightweight.
  2325. super.addNotify();
  2326. if (! (peer instanceof LightweightPeer)) {
  2327. dispatcher = new LightweightDispatcher(this);
  2328. }
  2329. int ncomponents = this.ncomponents;
  2330. Component component[] = this.component;
  2331. for (int i = 0 ; i < ncomponents ; i++) {
  2332. component[i].addNotify();
  2333. }
  2334. // Update stacking order if native platform allows
  2335. ContainerPeer cpeer = (ContainerPeer)peer;
  2336. if (cpeer.isRestackSupported()) {
  2337. cpeer.restack();
  2338. }
  2339. }
  2340. }
  2341. /**
  2342. * Makes this Container undisplayable by removing its connection
  2343. * to its native screen resource. Making a container undisplayable
  2344. * will cause all of its children to be made undisplayable.
  2345. * This method is called by the toolkit internally and should
  2346. * not be called directly by programs.
  2347. * @see Component#isDisplayable
  2348. * @see #addNotify
  2349. */
  2350. public void removeNotify() {
  2351. synchronized (getTreeLock()) {
  2352. int ncomponents = this.ncomponents;
  2353. Component component[] = this.component;
  2354. for (int i = ncomponents-1 ; i >= 0 ; i--) {
  2355. if( component[i] != null )
  2356. component[i].removeNotify();
  2357. }
  2358. if ( dispatcher != null ) {
  2359. dispatcher.dispose();
  2360. dispatcher = null;
  2361. }
  2362. super.removeNotify();
  2363. }
  2364. }
  2365. /**
  2366. * Checks if the component is contained in the component hierarchy of
  2367. * this container.
  2368. * @param c the component
  2369. * @return <code>true</code> if it is an ancestor;
  2370. * <code>false</code> otherwise.
  2371. * @since JDK1.1
  2372. */
  2373. public boolean isAncestorOf(Component c) {
  2374. Container p;
  2375. if (c == null || ((p = c.getParent()) == null)) {
  2376. return false;
  2377. }
  2378. while (p != null) {
  2379. if (p == this) {
  2380. return true;
  2381. }
  2382. p = p.getParent();
  2383. }
  2384. return false;
  2385. }
  2386. /*
  2387. * The following code was added to support modal JInternalFrames
  2388. * Unfortunately this code has to be added here so that we can get access to
  2389. * some private AWT classes like SequencedEvent.
  2390. *
  2391. * The native container of the LW component has this field set
  2392. * to tell it that it should block Mouse events for all LW
  2393. * children except for the modal component.
  2394. *
  2395. * In the case of nested Modal components, we store the previous
  2396. * modal component in the new modal components value of modalComp;
  2397. */
  2398. transient Component modalComp;
  2399. transient AppContext modalAppContext;
  2400. private void startLWModal() {
  2401. // Store the app context on which this component is being shown.
  2402. // Event dispatch thread of this app context will be sleeping until
  2403. // we wake it by any event from hideAndDisposeHandler().
  2404. modalAppContext = AppContext.getAppContext();
  2405. // keep the KeyEvents from being dispatched
  2406. // until the focus has been transfered
  2407. long time = Toolkit.getEventQueue().getMostRecentEventTime();
  2408. Component predictedFocusOwner = (this instanceof javax.swing.JInternalFrame) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
  2409. if (predictedFocusOwner != null) {
  2410. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  2411. enqueueKeyEvents(time, predictedFocusOwner);
  2412. }
  2413. // We have two mechanisms for blocking: 1. If we're on the
  2414. // EventDispatchThread, start a new event pump. 2. If we're
  2415. // on any other thread, call wait() on the treelock.
  2416. final Container nativeContainer;
  2417. synchronized (getTreeLock()) {
  2418. nativeContainer = getHeavyweightContainer();
  2419. if (nativeContainer.modalComp != null) {
  2420. this.modalComp = nativeContainer.modalComp;
  2421. nativeContainer.modalComp = this;
  2422. return;
  2423. }
  2424. else {
  2425. nativeContainer.modalComp = this;
  2426. }
  2427. }
  2428. Runnable pumpEventsForHierarchy = new Runnable() {
  2429. public void run() {
  2430. EventDispatchThread dispatchThread =
  2431. (EventDispatchThread)Thread.currentThread();
  2432. dispatchThread.pumpEventsForHierarchy(
  2433. new Conditional() {
  2434. public boolean evaluate() {
  2435. return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ;
  2436. }
  2437. }, Container.this);
  2438. }
  2439. };
  2440. if (EventQueue.isDispatchThread()) {
  2441. SequencedEvent currentSequencedEvent =
  2442. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  2443. getCurrentSequencedEvent();
  2444. if (currentSequencedEvent != null) {
  2445. currentSequencedEvent.dispose();
  2446. }
  2447. pumpEventsForHierarchy.run();
  2448. } else {
  2449. synchronized (getTreeLock()) {
  2450. Toolkit.getEventQueue().
  2451. postEvent(new PeerEvent(this,
  2452. pumpEventsForHierarchy,
  2453. PeerEvent.PRIORITY_EVENT));
  2454. while (windowClosingException == null) {
  2455. try {
  2456. getTreeLock().wait();
  2457. } catch (InterruptedException e) {
  2458. break;
  2459. }
  2460. }
  2461. }
  2462. }
  2463. if (windowClosingException != null) {
  2464. windowClosingException.fillInStackTrace();
  2465. throw windowClosingException;
  2466. }
  2467. if (predictedFocusOwner != null) {
  2468. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  2469. dequeueKeyEvents(time, predictedFocusOwner);
  2470. }
  2471. }
  2472. private void stopLWModal() {
  2473. synchronized (getTreeLock()) {
  2474. if (modalAppContext != null) {
  2475. Container nativeContainer = getHeavyweightContainer();
  2476. if(nativeContainer != null) {
  2477. if (this.modalComp != null) {
  2478. nativeContainer.modalComp = this.modalComp;
  2479. this.modalComp = null;
  2480. return;
  2481. }
  2482. else {
  2483. nativeContainer.modalComp = null;
  2484. }
  2485. }
  2486. // Wake up event dispatch thread on which the dialog was
  2487. // initially shown
  2488. SunToolkit.postEvent(modalAppContext,
  2489. new PeerEvent(this,
  2490. new WakingRunnable(),
  2491. PeerEvent.PRIORITY_EVENT));
  2492. }
  2493. EventQueue.invokeLater(new WakingRunnable());
  2494. getTreeLock().notifyAll();
  2495. }
  2496. }
  2497. final static class WakingRunnable implements Runnable {
  2498. public void run() {
  2499. }
  2500. }
  2501. /* End of JOptionPane support code */
  2502. /**
  2503. * Returns a string representing the state of this <code>Container</code>.
  2504. * This method is intended to be used only for debugging purposes, and the
  2505. * content and format of the returned string may vary between
  2506. * implementations. The returned string may be empty but may not be
  2507. * <code>null</code>.
  2508. *
  2509. * @return the parameter string of this container
  2510. */
  2511. protected String paramString() {
  2512. String str = super.paramString();
  2513. LayoutManager layoutMgr = this.layoutMgr;
  2514. if (layoutMgr != null) {
  2515. str += ",layout=" + layoutMgr.getClass().getName();
  2516. }
  2517. return str;
  2518. }
  2519. /**
  2520. * Prints a listing of this container to the specified output
  2521. * stream. The listing starts at the specified indentation.
  2522. * <p>
  2523. * The immediate children of the container are printed with
  2524. * an indentation of <code>indent+1</code>. The children
  2525. * of those children are printed at <code>indent+2</code>
  2526. * and so on.
  2527. *
  2528. * @param out a print stream
  2529. * @param indent the number of spaces to indent
  2530. * @see Component#list(java.io.PrintStream, int)
  2531. * @since JDK1.0
  2532. */
  2533. public void list(PrintStream out, int indent) {
  2534. super.list(out, indent);
  2535. int ncomponents = this.ncomponents;
  2536. Component component[] = this.component;
  2537. for (int i = 0 ; i < ncomponents ; i++) {
  2538. Component comp = component[i];
  2539. if (comp != null) {
  2540. comp.list(out, indent+1);
  2541. }
  2542. }
  2543. }
  2544. /**
  2545. * Prints out a list, starting at the specified indentation,
  2546. * to the specified print writer.
  2547. * <p>
  2548. * The immediate children of the container are printed with
  2549. * an indentation of <code>indent+1</code>. The children
  2550. * of those children are printed at <code>indent+2</code>
  2551. * and so on.
  2552. *
  2553. * @param out a print writer
  2554. * @param indent the number of spaces to indent
  2555. * @see Component#list(java.io.PrintWriter, int)
  2556. * @since JDK1.1
  2557. */
  2558. public void list(PrintWriter out, int indent) {
  2559. super.list(out, indent);
  2560. int ncomponents = this.ncomponents;
  2561. Component component[] = this.component;
  2562. for (int i = 0 ; i < ncomponents ; i++) {
  2563. Component comp = component[i];
  2564. if (comp != null) {
  2565. comp.list(out, indent+1);
  2566. }
  2567. }
  2568. }
  2569. /**
  2570. * Sets the focus traversal keys for a given traversal operation for this
  2571. * Container.
  2572. * <p>
  2573. * The default values for a Container's focus traversal keys are
  2574. * implementation-dependent. Sun recommends that all implementations for a
  2575. * particular native platform use the same default values. The
  2576. * recommendations for Windows and Unix are listed below. These
  2577. * recommendations are used in the Sun AWT implementations.
  2578. *
  2579. * <table border=1 summary="Recommended default values for a Container's focus traversal keys">
  2580. * <tr>
  2581. * <th>Identifier</th>
  2582. * <th>Meaning</th>
  2583. * <th>Default</th>
  2584. * </tr>
  2585. * <tr>
  2586. * <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
  2587. * <td>Normal forward keyboard traversal</td>
  2588. * <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
  2589. * </tr>
  2590. * <tr>
  2591. * <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
  2592. * <td>Normal reverse keyboard traversal</td>
  2593. * <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
  2594. * </tr>
  2595. * <tr>
  2596. * <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
  2597. * <td>Go up one focus traversal cycle</td>
  2598. * <td>none</td>
  2599. * </tr>
  2600. * <tr>
  2601. * <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td>
  2602. * <td>Go down one focus traversal cycle</td>
  2603. * <td>none</td>
  2604. * </tr>
  2605. * </table>
  2606. *
  2607. * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
  2608. * recommended.
  2609. * <p>
  2610. * Using the AWTKeyStroke API, client code can specify on which of two
  2611. * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
  2612. * operation will occur. Regardless of which KeyEvent is specified,
  2613. * however, all KeyEvents related to the focus traversal key, including the
  2614. * associated KEY_TYPED event, will be consumed, and will not be dispatched
  2615. * to any Container. It is a runtime error to specify a KEY_TYPED event as
  2616. * mapping to a focus traversal operation, or to map the same event to
  2617. * multiple default focus traversal operations.
  2618. * <p>
  2619. * If a value of null is specified for the Set, this Container inherits the
  2620. * Set from its parent. If all ancestors of this Container have null
  2621. * specified for the Set, then the current KeyboardFocusManager's default
  2622. * Set is used.
  2623. *
  2624. * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  2625. * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  2626. * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
  2627. * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
  2628. * @param keystrokes the Set of AWTKeyStroke for the specified operation
  2629. * @see #getFocusTraversalKeys
  2630. * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
  2631. * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
  2632. * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
  2633. * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
  2634. * @throws IllegalArgumentException if id is not one of
  2635. * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  2636. * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  2637. * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
  2638. * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
  2639. * contains null, or if any Object in keystrokes is not an
  2640. * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
  2641. * or if any keystroke already maps to another focus traversal
  2642. * operation for this Container
  2643. * @since 1.4
  2644. * @beaninfo
  2645. * bound: true
  2646. */
  2647. public void setFocusTraversalKeys(int id,
  2648. Set<? extends AWTKeyStroke> keystrokes)
  2649. {
  2650. if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
  2651. throw new IllegalArgumentException("invalid focus traversal key identifier");
  2652. }
  2653. // Don't call super.setFocusTraversalKey. The Component parameter check
  2654. // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
  2655. setFocusTraversalKeys_NoIDCheck(id, keystrokes);
  2656. }
  2657. /**
  2658. * Returns the Set of focus traversal keys for a given traversal operation
  2659. * for this Container. (See
  2660. * <code>setFocusTraversalKeys</code> for a full description of each key.)
  2661. * <p>
  2662. * If a Set of traversal keys has not been explicitly defined for this
  2663. * Container, then this Container's parent's Set is returned. If no Set
  2664. * has been explicitly defined for any of this Container's ancestors, then
  2665. * the current KeyboardFocusManager's default Set is returned.
  2666. *
  2667. * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  2668. * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  2669. * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
  2670. * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
  2671. * @return the Set of AWTKeyStrokes for the specified operation. The Set
  2672. * will be unmodifiable, and may be empty. null will never be
  2673. * returned.
  2674. * @see #setFocusTraversalKeys
  2675. * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
  2676. * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
  2677. * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
  2678. * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
  2679. * @throws IllegalArgumentException if id is not one of
  2680. * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  2681. * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  2682. * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
  2683. * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
  2684. * @since 1.4
  2685. */
  2686. public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
  2687. if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
  2688. throw new IllegalArgumentException("invalid focus traversal key identifier");
  2689. }
  2690. // Don't call super.getFocusTraversalKey. The Component parameter check
  2691. // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
  2692. return getFocusTraversalKeys_NoIDCheck(id);
  2693. }
  2694. /**
  2695. * Returns whether the Set of focus traversal keys for the given focus
  2696. * traversal operation has been explicitly defined for this Container. If
  2697. * this method returns <code>false</code>, this Container is inheriting the
  2698. * Set from an ancestor, or from the current KeyboardFocusManager.
  2699. *
  2700. * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  2701. * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  2702. * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
  2703. * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
  2704. * @return <code>true</code> if the the Set of focus traversal keys for the
  2705. * given focus traversal operation has been explicitly defined for
  2706. * this Component; <code>false</code> otherwise.
  2707. * @throws IllegalArgumentException if id is not one of
  2708. * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  2709. * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  2710. * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
  2711. * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
  2712. * @since 1.4
  2713. */
  2714. public boolean areFocusTraversalKeysSet(int id) {
  2715. if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
  2716. throw new IllegalArgumentException("invalid focus traversal key identifier");
  2717. }
  2718. return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
  2719. }
  2720. /**
  2721. * Returns whether the specified Container is the focus cycle root of this
  2722. * Container's focus traversal cycle. Each focus traversal cycle has only
  2723. * a single focus cycle root and each Container which is not a focus cycle
  2724. * root belongs to only a single focus traversal cycle. Containers which
  2725. * are focus cycle roots belong to two cycles: one rooted at the Container
  2726. * itself, and one rooted at the Container's nearest focus-cycle-root
  2727. * ancestor. This method will return <code>true</code> for both such
  2728. * Containers in this case.
  2729. *
  2730. * @param container the Container to be tested
  2731. * @return <code>true</code> if the specified Container is a focus-cycle-
  2732. * root of this Container; <code>false</code> otherwise
  2733. * @see #isFocusCycleRoot()
  2734. * @since 1.4
  2735. */
  2736. public boolean isFocusCycleRoot(Container container) {
  2737. if (isFocusCycleRoot() && container == this) {
  2738. return true;
  2739. } else {
  2740. return super.isFocusCycleRoot(container);
  2741. }
  2742. }
  2743. private Container findTraversalRoot() {
  2744. // I potentially have two roots, myself and my root parent
  2745. // If I am the current root, then use me
  2746. // If none of my parents are roots, then use me
  2747. // If my root parent is the current root, then use my root parent
  2748. // If neither I nor my root parent is the current root, then
  2749. // use my root parent (a guess)
  2750. Container currentFocusCycleRoot = KeyboardFocusManager.
  2751. getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
  2752. Container root;
  2753. if (currentFocusCycleRoot == this) {
  2754. root = this;
  2755. } else {
  2756. root = getFocusCycleRootAncestor();
  2757. if (root == null) {
  2758. root = this;
  2759. }
  2760. }
  2761. if (root != currentFocusCycleRoot) {
  2762. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  2763. setGlobalCurrentFocusCycleRoot(root);
  2764. }
  2765. return root;
  2766. }
  2767. final boolean containsFocus() {
  2768. synchronized (getTreeLock()) {
  2769. Component comp = KeyboardFocusManager.
  2770. getCurrentKeyboardFocusManager().getFocusOwner();
  2771. while (comp != null && !(comp instanceof Window) && comp != this)
  2772. {
  2773. comp = (Component) comp.getParent();
  2774. }
  2775. return (comp == this);
  2776. }
  2777. }
  2778. /**
  2779. * Check if this component is the child of this container or its children.
  2780. * Note: this function acquires treeLock
  2781. * Note: this function traverses children tree only in one Window.
  2782. * @param comp a component in test, must not be null
  2783. */
  2784. boolean isParentOf(Component comp) {
  2785. synchronized(getTreeLock()) {
  2786. while (comp != null && comp != this && !(comp instanceof Window)) {
  2787. comp = comp.getParent();
  2788. }
  2789. return (comp == this);
  2790. }
  2791. }
  2792. void clearMostRecentFocusOwnerOnHide() {
  2793. Component comp = null;
  2794. Container window = this;
  2795. synchronized (getTreeLock()) {
  2796. while (window != null && !(window instanceof Window)) {
  2797. window = window.getParent();
  2798. }
  2799. if (window != null) {
  2800. comp = KeyboardFocusManager.
  2801. getMostRecentFocusOwner((Window)window);
  2802. while ((comp != null) && (comp != this) && !(comp instanceof Window)) {
  2803. comp = comp.getParent();
  2804. }
  2805. }
  2806. }
  2807. if (comp == this) {
  2808. KeyboardFocusManager.setMostRecentFocusOwner((Window)window, null);
  2809. }
  2810. if (window != null) {
  2811. Window myWindow = (Window)window;
  2812. synchronized(getTreeLock()) {
  2813. // This synchronized should always be the second in a pair (tree lock, KeyboardFocusManager.class)
  2814. synchronized(KeyboardFocusManager.class) {
  2815. Component storedComp = myWindow.getTemporaryLostComponent();
  2816. if (isParentOf(storedComp) || storedComp == this) {
  2817. myWindow.setTemporaryLostComponent(null);
  2818. }
  2819. }
  2820. }
  2821. }
  2822. }
  2823. void clearCurrentFocusCycleRootOnHide() {
  2824. KeyboardFocusManager kfm =
  2825. KeyboardFocusManager.getCurrentKeyboardFocusManager();
  2826. Container cont = kfm.getCurrentFocusCycleRoot();
  2827. synchronized (getTreeLock()) {
  2828. while (this != cont && !(cont instanceof Window) && (cont != null)) {
  2829. cont = cont.getParent();
  2830. }
  2831. }
  2832. if (cont == this) {
  2833. kfm.setGlobalCurrentFocusCycleRoot(null);
  2834. }
  2835. }
  2836. boolean nextFocusHelper() {
  2837. if (isFocusCycleRoot()) {
  2838. Container root = findTraversalRoot();
  2839. Component comp = this;
  2840. Container anc;
  2841. while (root != null &&
  2842. (anc = root.getFocusCycleRootAncestor()) != null &&
  2843. !(root.isShowing() &&
  2844. root.isFocusable() &&
  2845. root.isEnabled()))
  2846. {
  2847. comp = root;
  2848. root = anc;
  2849. }
  2850. if (root != null) {
  2851. FocusTraversalPolicy policy = root.getFocusTraversalPolicy();
  2852. Component toFocus = policy.getComponentAfter(root, comp);
  2853. if (toFocus == null) {
  2854. toFocus = policy.getDefaultComponent(root);
  2855. }
  2856. if (toFocus != null) {
  2857. return toFocus.requestFocus(false);
  2858. }
  2859. }
  2860. return false;
  2861. } else {
  2862. // I only have one root, so the general case will suffice
  2863. return super.nextFocusHelper();
  2864. }
  2865. }
  2866. public void transferFocusBackward() {
  2867. if (isFocusCycleRoot()) {
  2868. Container root = findTraversalRoot();
  2869. Component comp = this;
  2870. while (root != null &&
  2871. !(root.isShowing() &&
  2872. root.isFocusable() &&
  2873. root.isEnabled()))
  2874. {
  2875. comp = root;
  2876. root = comp.getFocusCycleRootAncestor();
  2877. }
  2878. if (root != null) {
  2879. FocusTraversalPolicy policy = root.getFocusTraversalPolicy();
  2880. Component toFocus = policy.getComponentBefore(root, comp);
  2881. if (toFocus == null) {
  2882. toFocus = policy.getDefaultComponent(root);
  2883. }
  2884. if (toFocus != null) {
  2885. toFocus.requestFocus();
  2886. }
  2887. }
  2888. } else {
  2889. // I only have one root, so the general case will suffice
  2890. super.transferFocusBackward();
  2891. }
  2892. }
  2893. /**
  2894. * Sets the focus traversal policy that will manage keyboard traversal of
  2895. * this Container's children, if this Container is a focus cycle root. If
  2896. * the argument is null, this Container inherits its policy from its focus-
  2897. * cycle-root ancestor. If the argument is non-null, this policy will be
  2898. * inherited by all focus-cycle-root children that have no keyboard-
  2899. * traversal policy of their own (as will, recursively, their focus-cycle-
  2900. * root children).
  2901. * <p>
  2902. * If this Container is not a focus cycle root, the policy will be
  2903. * remembered, but will not be used or inherited by this or any other
  2904. * Containers until this Container is made a focus cycle root.
  2905. *
  2906. * @param policy the new focus traversal policy for this Container
  2907. * @see #getFocusTraversalPolicy
  2908. * @see #setFocusCycleRoot
  2909. * @see #isFocusCycleRoot
  2910. * @since 1.4
  2911. * @beaninfo
  2912. * bound: true
  2913. */
  2914. public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
  2915. FocusTraversalPolicy oldPolicy;
  2916. synchronized (this) {
  2917. oldPolicy = this.focusTraversalPolicy;
  2918. this.focusTraversalPolicy = policy;
  2919. }
  2920. firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
  2921. }
  2922. /**
  2923. * Returns the focus traversal policy that will manage keyboard traversal
  2924. * of this Container's children, or null if this Container is not a focus
  2925. * cycle root. If no traversal policy has been explicitly set for this
  2926. * Container, then this Container's focus-cycle-root ancestor's policy is
  2927. * returned.
  2928. *
  2929. * @return this Container's focus traversal policy, or null if this
  2930. * Container is not a focus cycle root.
  2931. * @see #setFocusTraversalPolicy
  2932. * @see #setFocusCycleRoot
  2933. * @see #isFocusCycleRoot
  2934. * @since 1.4
  2935. */
  2936. public FocusTraversalPolicy getFocusTraversalPolicy() {
  2937. if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
  2938. return null;
  2939. }
  2940. FocusTraversalPolicy policy = this.focusTraversalPolicy;
  2941. if (policy != null) {
  2942. return policy;
  2943. }
  2944. Container rootAncestor = getFocusCycleRootAncestor();
  2945. if (rootAncestor != null) {
  2946. return rootAncestor.getFocusTraversalPolicy();
  2947. } else {
  2948. return KeyboardFocusManager.getCurrentKeyboardFocusManager().
  2949. getDefaultFocusTraversalPolicy();
  2950. }
  2951. }
  2952. /**
  2953. * Returns whether the focus traversal policy has been explicitly set for
  2954. * this Container. If this method returns <code>false</code>, this
  2955. * Container will inherit its focus traversal policy from an ancestor.
  2956. *
  2957. * @return <code>true</code> if the focus traversal policy has been
  2958. * explicitly set for this Container; <code>false</code> otherwise.
  2959. * @since 1.4
  2960. */
  2961. public boolean isFocusTraversalPolicySet() {
  2962. return (focusTraversalPolicy != null);
  2963. }
  2964. /**
  2965. * Sets whether this Container is the root of a focus traversal cycle. Once
  2966. * focus enters a traversal cycle, typically it cannot leave it via focus
  2967. * traversal unless one of the up- or down-cycle keys is pressed. Normal
  2968. * traversal is limited to this Container, and all of this Container's
  2969. * descendants that are not descendants of inferior focus cycle roots. Note
  2970. * that a FocusTraversalPolicy may bend these restrictions, however. For
  2971. * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
  2972. * traversal.
  2973. * <p>
  2974. * The alternative way to specify the traversal order of this Container's
  2975. * children is to make this Container a
  2976. * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
  2977. *
  2978. * @param focusCycleRoot indicates whether this Container is the root of a
  2979. * focus traversal cycle
  2980. * @see #isFocusCycleRoot()
  2981. * @see #setFocusTraversalPolicy
  2982. * @see #getFocusTraversalPolicy
  2983. * @see ContainerOrderFocusTraversalPolicy
  2984. * @see #setFocusTraversalPolicyProvider
  2985. * @since 1.4
  2986. * @beaninfo
  2987. * bound: true
  2988. */
  2989. public void setFocusCycleRoot(boolean focusCycleRoot) {
  2990. boolean oldFocusCycleRoot;
  2991. synchronized (this) {
  2992. oldFocusCycleRoot = this.focusCycleRoot;
  2993. this.focusCycleRoot = focusCycleRoot;
  2994. }
  2995. firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
  2996. focusCycleRoot);
  2997. }
  2998. /**
  2999. * Returns whether this Container is the root of a focus traversal cycle.
  3000. * Once focus enters a traversal cycle, typically it cannot leave it via
  3001. * focus traversal unless one of the up- or down-cycle keys is pressed.
  3002. * Normal traversal is limited to this Container, and all of this
  3003. * Container's descendants that are not descendants of inferior focus
  3004. * cycle roots. Note that a FocusTraversalPolicy may bend these
  3005. * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
  3006. * supports implicit down-cycle traversal.
  3007. *
  3008. * @return whether this Container is the root of a focus traversal cycle
  3009. * @see #setFocusCycleRoot
  3010. * @see #setFocusTraversalPolicy
  3011. * @see #getFocusTraversalPolicy
  3012. * @see ContainerOrderFocusTraversalPolicy
  3013. * @since 1.4
  3014. */
  3015. public boolean isFocusCycleRoot() {
  3016. return focusCycleRoot;
  3017. }
  3018. /**
  3019. * Sets whether this container will be used to provide focus
  3020. * traversal policy. Container with this property as
  3021. * <code>true</code> will be used to acquire focus traversal policy
  3022. * instead of closest focus cycle root ancestor.
  3023. * @param provide indicates whether this container will be used to
  3024. * provide focus traversal policy
  3025. * @see #setFocusTraversalPolicy
  3026. * @see #getFocusTraversalPolicy
  3027. * @see #isFocusTraversalPolicyProvider
  3028. * @since 1.5
  3029. * @beaninfo
  3030. * bound: true
  3031. */
  3032. public final void setFocusTraversalPolicyProvider(boolean provider) {
  3033. boolean oldProvider;
  3034. synchronized(this) {
  3035. oldProvider = focusTraversalPolicyProvider;
  3036. focusTraversalPolicyProvider = provider;
  3037. }
  3038. firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
  3039. }
  3040. /**
  3041. * Returns whether this container provides focus traversal
  3042. * policy. If this property is set to <code>true</code> then when
  3043. * keyboard focus manager searches container hierarchy for focus
  3044. * traversal policy and encounters this container before any other
  3045. * container with this property as true or focus cycle roots then
  3046. * its focus traversal policy will be used instead of focus cycle
  3047. * root's policy.
  3048. * @see #setFocusTraversalPolicy
  3049. * @see #getFocusTraversalPolicy
  3050. * @see #setFocusCycleRoot
  3051. * @see #setFocusTraversalPolicyProvider
  3052. * @return <code>true</code> if this container provides focus traversal
  3053. * policy, <code>false</code> otherwise
  3054. * @since 1.5
  3055. * @beaninfo
  3056. * bound: true
  3057. */
  3058. public final boolean isFocusTraversalPolicyProvider() {
  3059. return focusTraversalPolicyProvider;
  3060. }
  3061. /**
  3062. * Transfers the focus down one focus traversal cycle. If this Container is
  3063. * a focus cycle root, then the focus owner is set to this Container's
  3064. * default Component to focus, and the current focus cycle root is set to
  3065. * this Container. If this Container is not a focus cycle root, then no
  3066. * focus traversal operation occurs.
  3067. *
  3068. * @see Component#requestFocus()
  3069. * @see #isFocusCycleRoot
  3070. * @see #setFocusCycleRoot
  3071. * @since 1.4
  3072. */
  3073. public void transferFocusDownCycle() {
  3074. if (isFocusCycleRoot()) {
  3075. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  3076. setGlobalCurrentFocusCycleRoot(this);
  3077. Component toFocus = getFocusTraversalPolicy().
  3078. getDefaultComponent(this);
  3079. if (toFocus != null) {
  3080. toFocus.requestFocus();
  3081. }
  3082. }
  3083. }
  3084. void preProcessKeyEvent(KeyEvent e) {
  3085. Container parent = this.parent;
  3086. if (parent != null) {
  3087. parent.preProcessKeyEvent(e);
  3088. }
  3089. }
  3090. void postProcessKeyEvent(KeyEvent e) {
  3091. Container parent = this.parent;
  3092. if (parent != null) {
  3093. parent.postProcessKeyEvent(e);
  3094. }
  3095. }
  3096. boolean postsOldMouseEvents() {
  3097. return true;
  3098. }
  3099. /**
  3100. * Sets the <code>ComponentOrientation</code> property of this container
  3101. * and all components contained within it.
  3102. *
  3103. * @param o the new component orientation of this container and
  3104. * the components contained within it.
  3105. * @exception NullPointerException if <code>orientation</code> is null.
  3106. * @see Component#setComponentOrientation
  3107. * @see Component#getComponentOrientation
  3108. * @since 1.4
  3109. */
  3110. public void applyComponentOrientation(ComponentOrientation o) {
  3111. super.applyComponentOrientation(o);
  3112. for (int i = 0 ; i < ncomponents ; ++i) {
  3113. component[i].applyComponentOrientation(o);
  3114. }
  3115. }
  3116. /**
  3117. * Adds a PropertyChangeListener to the listener list. The listener is
  3118. * registered for all bound properties of this class, including the
  3119. * following:
  3120. * <ul>
  3121. * <li>this Container's font ("font")</li>
  3122. * <li>this Container's background color ("background")</li>
  3123. * <li>this Container's foreground color ("foreground")</li>
  3124. * <li>this Container's focusability ("focusable")</li>
  3125. * <li>this Container's focus traversal keys enabled state
  3126. * ("focusTraversalKeysEnabled")</li>
  3127. * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
  3128. * ("forwardFocusTraversalKeys")</li>
  3129. * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
  3130. * ("backwardFocusTraversalKeys")</li>
  3131. * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
  3132. * ("upCycleFocusTraversalKeys")</li>
  3133. * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
  3134. * ("downCycleFocusTraversalKeys")</li>
  3135. * <li>this Container's focus traversal policy ("focusTraversalPolicy")
  3136. * </li>
  3137. * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
  3138. * </ul>
  3139. * Note that if this Container is inheriting a bound property, then no
  3140. * event will be fired in response to a change in the inherited property.
  3141. * <p>
  3142. * If listener is null, no exception is thrown and no action is performed.
  3143. *
  3144. * @param listener the PropertyChangeListener to be added
  3145. *
  3146. * @see Component#removePropertyChangeListener
  3147. * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
  3148. */
  3149. public void addPropertyChangeListener(PropertyChangeListener listener) {
  3150. super.addPropertyChangeListener(listener);
  3151. }
  3152. /**
  3153. * Adds a PropertyChangeListener to the listener list for a specific
  3154. * property. The specified property may be user-defined, or one of the
  3155. * following defaults:
  3156. * <ul>
  3157. * <li>this Container's font ("font")</li>
  3158. * <li>this Container's background color ("background")</li>
  3159. * <li>this Container's foreground color ("foreground")</li>
  3160. * <li>this Container's focusability ("focusable")</li>
  3161. * <li>this Container's focus traversal keys enabled state
  3162. * ("focusTraversalKeysEnabled")</li>
  3163. * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
  3164. * ("forwardFocusTraversalKeys")</li>
  3165. * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
  3166. * ("backwardFocusTraversalKeys")</li>
  3167. * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
  3168. * ("upCycleFocusTraversalKeys")</li>
  3169. * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
  3170. * ("downCycleFocusTraversalKeys")</li>
  3171. * <li>this Container's focus traversal policy ("focusTraversalPolicy")
  3172. * </li>
  3173. * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
  3174. * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
  3175. * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
  3176. * </ul>
  3177. * Note that if this Container is inheriting a bound property, then no
  3178. * event will be fired in response to a change in the inherited property.
  3179. * <p>
  3180. * If listener is null, no exception is thrown and no action is performed.
  3181. *
  3182. * @param propertyName one of the property names listed above
  3183. * @param listener the PropertyChangeListener to be added
  3184. *
  3185. * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
  3186. * @see Component#removePropertyChangeListener
  3187. */
  3188. public void addPropertyChangeListener(String propertyName,
  3189. PropertyChangeListener listener) {
  3190. super.addPropertyChangeListener(propertyName, listener);
  3191. }
  3192. // Serialization support. A Container is responsible for restoring the
  3193. // parent fields of its component children.
  3194. /**
  3195. * Container Serial Data Version.
  3196. */
  3197. private int containerSerializedDataVersion = 1;
  3198. /**
  3199. * Serializes this <code>Container</code> to the specified
  3200. * <code>ObjectOutputStream</code>.
  3201. * <ul>
  3202. * <li>Writes default serializable fields to the stream.</li>
  3203. * <li>Writes a list of serializable ContainerListener(s) as optional
  3204. * data. The non-serializable ContainerListner(s) are detected and
  3205. * no attempt is made to serialize them.</li>
  3206. * <li>Write this Container's FocusTraversalPolicy if and only if it
  3207. * is Serializable; otherwise, <code>null</code> is written.</li>
  3208. * </ul>
  3209. *
  3210. * @param s the <code>ObjectOutputStream</code> to write
  3211. * @serialData <code>null</code> terminated sequence of 0 or more pairs;
  3212. * the pair consists of a <code>String</code> and <code>Object</code>
  3213. * the <code>String</code> indicates the type of object and
  3214. * is one of the following:
  3215. * <code>containerListenerK</code> indicating an
  3216. * <code>ContainerListener</code> object;
  3217. * the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
  3218. * or <code>null</code>
  3219. *
  3220. * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
  3221. * @see Container#containerListenerK
  3222. * @see #readObject(ObjectInputStream)
  3223. */
  3224. private void writeObject(ObjectOutputStream s) throws IOException {
  3225. ObjectOutputStream.PutField f = s.putFields();
  3226. f.put("ncomponents", ncomponents);
  3227. f.put("component", component);
  3228. f.put("layoutMgr", layoutMgr);
  3229. f.put("dispatcher", dispatcher);
  3230. f.put("maxSize", maxSize);
  3231. f.put("focusCycleRoot", focusCycleRoot);
  3232. f.put("containerSerializedDataVersion", containerSerializedDataVersion);
  3233. f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
  3234. s.writeFields();
  3235. AWTEventMulticaster.save(s, containerListenerK, containerListener);
  3236. s.writeObject(null);
  3237. if (focusTraversalPolicy instanceof java.io.Serializable) {
  3238. s.writeObject(focusTraversalPolicy);
  3239. } else {
  3240. s.writeObject(null);
  3241. }
  3242. }
  3243. /**
  3244. * Deserializes this <code>Container</code> from the specified
  3245. * <code>ObjectInputStream</code>.
  3246. * <ul>
  3247. * <li>Reads default serializable fields from the stream.</li>
  3248. * <li>Reads a list of serializable ContainerListener(s) as optional
  3249. * data. If the list is null, no Listeners are installed.</li>
  3250. * <li>Reads this Container's FocusTraversalPolicy, which may be null,
  3251. * as optional data.</li>
  3252. * </ul>
  3253. *
  3254. * @param s the <code>ObjectInputStream</code> to read
  3255. * @serial
  3256. * @see #addContainerListener
  3257. * @see #writeObject(ObjectOutputStream)
  3258. */
  3259. private void readObject(ObjectInputStream s)
  3260. throws ClassNotFoundException, IOException
  3261. {
  3262. ObjectInputStream.GetField f = s.readFields();
  3263. ncomponents = f.get("ncomponents", 0);
  3264. component = (Component[])f.get("component", new Component[0]);
  3265. layoutMgr = (LayoutManager)f.get("layoutMgr", null);
  3266. dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
  3267. // Old stream. Doesn't contain maxSize among Component's fields.
  3268. if (maxSize == null) {
  3269. maxSize = (Dimension)f.get("maxSize", null);
  3270. }
  3271. focusCycleRoot = f.get("focusCycleRoot", false);
  3272. containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
  3273. focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
  3274. Component component[] = this.component;
  3275. for(int i = 0; i < ncomponents; i++) {
  3276. component[i].parent = this;
  3277. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  3278. component[i].numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  3279. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  3280. component[i].numListening(
  3281. AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  3282. adjustDescendants(component[i].countHierarchyMembers());
  3283. }
  3284. Object keyOrNull;
  3285. while(null != (keyOrNull = s.readObject())) {
  3286. String key = ((String)keyOrNull).intern();
  3287. if (containerListenerK == key) {
  3288. addContainerListener((ContainerListener)(s.readObject()));
  3289. } else {
  3290. // skip value for unrecognized key
  3291. s.readObject();
  3292. }
  3293. }
  3294. try {
  3295. Object policy = s.readObject();
  3296. if (policy instanceof FocusTraversalPolicy) {
  3297. focusTraversalPolicy = (FocusTraversalPolicy)policy;
  3298. }
  3299. } catch (java.io.OptionalDataException e) {
  3300. // JDK 1.1/1.2/1.3 instances will not have this optional data.
  3301. // e.eof will be true to indicate that there is no more data
  3302. // available for this object. If e.eof is not true, throw the
  3303. // exception as it might have been caused by reasons unrelated to
  3304. // focusTraversalPolicy.
  3305. if (!e.eof) {
  3306. throw e;
  3307. }
  3308. }
  3309. }
  3310. /*
  3311. * --- Accessibility Support ---
  3312. */
  3313. /**
  3314. * Inner class of Container used to provide default support for
  3315. * accessibility. This class is not meant to be used directly by
  3316. * application developers, but is instead meant only to be
  3317. * subclassed by container developers.
  3318. * <p>
  3319. * The class used to obtain the accessible role for this object,
  3320. * as well as implementing many of the methods in the
  3321. * AccessibleContainer interface.
  3322. */
  3323. protected class AccessibleAWTContainer extends AccessibleAWTComponent {
  3324. /**
  3325. * JDK1.3 serialVersionUID
  3326. */
  3327. private static final long serialVersionUID = 5081320404842566097L;
  3328. /**
  3329. * Returns the number of accessible children in the object. If all
  3330. * of the children of this object implement <code>Accessible</code>,
  3331. * then this method should return the number of children of this object.
  3332. *
  3333. * @return the number of accessible children in the object
  3334. */
  3335. public int getAccessibleChildrenCount() {
  3336. return Container.this.getAccessibleChildrenCount();
  3337. }
  3338. /**
  3339. * Returns the nth <code>Accessible</code> child of the object.
  3340. *
  3341. * @param i zero-based index of child
  3342. * @return the nth <code>Accessible</code> child of the object
  3343. */
  3344. public Accessible getAccessibleChild(int i) {
  3345. return Container.this.getAccessibleChild(i);
  3346. }
  3347. /**
  3348. * Returns the <code>Accessible</code> child, if one exists,
  3349. * contained at the local coordinate <code>Point</code>.
  3350. *
  3351. * @param p the point defining the top-left corner of the
  3352. * <code>Accessible</code>, given in the coordinate space
  3353. * of the object's parent
  3354. * @return the <code>Accessible</code>, if it exists,
  3355. * at the specified location; else <code>null</code>
  3356. */
  3357. public Accessible getAccessibleAt(Point p) {
  3358. return Container.this.getAccessibleAt(p);
  3359. }
  3360. protected ContainerListener accessibleContainerHandler = null;
  3361. /**
  3362. * Fire <code>PropertyChange</code> listener, if one is registered,
  3363. * when children are added or removed.
  3364. */
  3365. protected class AccessibleContainerHandler
  3366. implements ContainerListener {
  3367. public void componentAdded(ContainerEvent e) {
  3368. Component c = e.getChild();
  3369. if (c != null && c instanceof Accessible) {
  3370. AccessibleAWTContainer.this.firePropertyChange(
  3371. AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
  3372. null, ((Accessible) c).getAccessibleContext());
  3373. }
  3374. }
  3375. public void componentRemoved(ContainerEvent e) {
  3376. Component c = e.getChild();
  3377. if (c != null && c instanceof Accessible) {
  3378. AccessibleAWTContainer.this.firePropertyChange(
  3379. AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
  3380. ((Accessible) c).getAccessibleContext(), null);
  3381. }
  3382. }
  3383. }
  3384. /**
  3385. * Adds a PropertyChangeListener to the listener list.
  3386. *
  3387. * @param listener the PropertyChangeListener to be added
  3388. */
  3389. public void addPropertyChangeListener(PropertyChangeListener listener) {
  3390. if (accessibleContainerHandler == null) {
  3391. accessibleContainerHandler = new AccessibleContainerHandler();
  3392. Container.this.addContainerListener(accessibleContainerHandler);
  3393. }
  3394. super.addPropertyChangeListener(listener);
  3395. }
  3396. } // inner class AccessibleAWTContainer
  3397. /**
  3398. * Returns the <code>Accessible</code> child contained at the local
  3399. * coordinate <code>Point</code>, if one exists. Otherwise
  3400. * returns <code>null</code>.
  3401. *
  3402. * @param p the point defining the top-left corner of the
  3403. * <code>Accessible</code>, given in the coordinate space
  3404. * of the object's parent
  3405. * @return the <code>Accessible</code> at the specified location,
  3406. * if it exists; otherwise <code>null</code>
  3407. */
  3408. Accessible getAccessibleAt(Point p) {
  3409. synchronized (getTreeLock()) {
  3410. if (this instanceof Accessible) {
  3411. Accessible a = (Accessible)this;
  3412. AccessibleContext ac = a.getAccessibleContext();
  3413. if (ac != null) {
  3414. AccessibleComponent acmp;
  3415. Point location;
  3416. int nchildren = ac.getAccessibleChildrenCount();
  3417. for (int i=0; i < nchildren; i++) {
  3418. a = ac.getAccessibleChild(i);
  3419. if ((a != null)) {
  3420. ac = a.getAccessibleContext();
  3421. if (ac != null) {
  3422. acmp = ac.getAccessibleComponent();
  3423. if ((acmp != null) && (acmp.isShowing())) {
  3424. location = acmp.getLocation();
  3425. Point np = new Point(p.x-location.x,
  3426. p.y-location.y);
  3427. if (acmp.contains(np)){
  3428. return a;
  3429. }
  3430. }
  3431. }
  3432. }
  3433. }
  3434. }
  3435. return (Accessible)this;
  3436. } else {
  3437. Component ret = this;
  3438. if (!this.contains(p.x,p.y)) {
  3439. ret = null;
  3440. } else {
  3441. int ncomponents = this.getComponentCount();
  3442. for (int i=0; i < ncomponents; i++) {
  3443. Component comp = this.getComponent(i);
  3444. if ((comp != null) && comp.isShowing()) {
  3445. Point location = comp.getLocation();
  3446. if (comp.contains(p.x-location.x,p.y-location.y)) {
  3447. ret = comp;
  3448. }
  3449. }
  3450. }
  3451. }
  3452. if (ret instanceof Accessible) {
  3453. return (Accessible) ret;
  3454. }
  3455. }
  3456. return null;
  3457. }
  3458. }
  3459. /**
  3460. * Returns the number of accessible children in the object. If all
  3461. * of the children of this object implement <code>Accessible</code>,
  3462. * then this method should return the number of children of this object.
  3463. *
  3464. * @return the number of accessible children in the object
  3465. */
  3466. int getAccessibleChildrenCount() {
  3467. synchronized (getTreeLock()) {
  3468. int count = 0;
  3469. Component[] children = this.getComponents();
  3470. for (int i = 0; i < children.length; i++) {
  3471. if (children[i] instanceof Accessible) {
  3472. count++;
  3473. }
  3474. }
  3475. return count;
  3476. }
  3477. }
  3478. /**
  3479. * Returns the nth <code>Accessible</code> child of the object.
  3480. *
  3481. * @param i zero-based index of child
  3482. * @return the nth <code>Accessible</code> child of the object
  3483. */
  3484. Accessible getAccessibleChild(int i) {
  3485. synchronized (getTreeLock()) {
  3486. Component[] children = this.getComponents();
  3487. int count = 0;
  3488. for (int j = 0; j < children.length; j++) {
  3489. if (children[j] instanceof Accessible) {
  3490. if (count == i) {
  3491. return (Accessible) children[j];
  3492. } else {
  3493. count++;
  3494. }
  3495. }
  3496. }
  3497. return null;
  3498. }
  3499. }
  3500. }
  3501. /**
  3502. * Class to manage the dispatching of MouseEvents to the lightweight descendants
  3503. * and SunDropTargetEvents to both lightweight and heavyweight descendants
  3504. * contained by a native container.
  3505. *
  3506. * NOTE: the class name is not appropriate anymore, but we cannot change it
  3507. * because we must keep serialization compatibility.
  3508. *
  3509. * @author Timothy Prinzing
  3510. */
  3511. class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
  3512. /*
  3513. * JDK 1.1 serialVersionUID
  3514. */
  3515. private static final long serialVersionUID = 5184291520170872969L;
  3516. /*
  3517. * Our own mouse event for when we're dragged over from another hw
  3518. * container
  3519. */
  3520. private static final int LWD_MOUSE_DRAGGED_OVER = 1500;
  3521. private static final DebugHelper dbg = DebugHelper.create(LightweightDispatcher.class);
  3522. LightweightDispatcher(Container nativeContainer) {
  3523. this.nativeContainer = nativeContainer;
  3524. mouseEventTarget = null;
  3525. eventMask = 0;
  3526. }
  3527. /*
  3528. * Clean up any resources allocated when dispatcher was created;
  3529. * should be called from Container.removeNotify
  3530. */
  3531. void dispose() {
  3532. //System.out.println("Disposing lw dispatcher");
  3533. stopListeningForOtherDrags();
  3534. mouseEventTarget = null;
  3535. }
  3536. /**
  3537. * Enables events to subcomponents.
  3538. */
  3539. void enableEvents(long events) {
  3540. eventMask |= events;
  3541. }
  3542. /**
  3543. * Dispatches an event to a sub-component if necessary, and
  3544. * returns whether or not the event was forwarded to a
  3545. * sub-component.
  3546. *
  3547. * @param e the event
  3548. */
  3549. boolean dispatchEvent(AWTEvent e) {
  3550. boolean ret = false;
  3551. /*
  3552. * Fix for BugTraq Id 4389284.
  3553. * Dispatch SunDropTargetEvents regardless of eventMask value.
  3554. * Do not update cursor on dispatching SunDropTargetEvents.
  3555. */
  3556. if (e instanceof SunDropTargetEvent) {
  3557. SunDropTargetEvent sdde = (SunDropTargetEvent) e;
  3558. ret = processDropTargetEvent(sdde);
  3559. } else {
  3560. if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
  3561. MouseEvent me = (MouseEvent) e;
  3562. ret = processMouseEvent(me);
  3563. }
  3564. if (e.getID() == MouseEvent.MOUSE_MOVED) {
  3565. nativeContainer.updateCursorImmediately();
  3566. }
  3567. }
  3568. return ret;
  3569. }
  3570. /* This method effectively returns whether or not a mouse button was down
  3571. * just BEFORE the event happened. A better method name might be
  3572. * wasAMouseButtonDownBeforeThisEvent().
  3573. */
  3574. private boolean isMouseGrab(MouseEvent e) {
  3575. int modifiers = e.getModifiersEx();
  3576. if(e.getID() == MouseEvent.MOUSE_PRESSED
  3577. || e.getID() == MouseEvent.MOUSE_RELEASED)
  3578. {
  3579. switch (e.getButton()) {
  3580. case MouseEvent.BUTTON1:
  3581. modifiers ^= InputEvent.BUTTON1_DOWN_MASK;
  3582. break;
  3583. case MouseEvent.BUTTON2:
  3584. modifiers ^= InputEvent.BUTTON2_DOWN_MASK;
  3585. break;
  3586. case MouseEvent.BUTTON3:
  3587. modifiers ^= InputEvent.BUTTON3_DOWN_MASK;
  3588. break;
  3589. }
  3590. }
  3591. /* modifiers now as just before event */
  3592. return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
  3593. | InputEvent.BUTTON2_DOWN_MASK
  3594. | InputEvent.BUTTON3_DOWN_MASK)) != 0);
  3595. }
  3596. /**
  3597. * This method attempts to distribute a mouse event to a lightweight
  3598. * component. It tries to avoid doing any unnecessary probes down
  3599. * into the component tree to minimize the overhead of determining
  3600. * where to route the event, since mouse movement events tend to
  3601. * come in large and frequent amounts.
  3602. */
  3603. private boolean processMouseEvent(MouseEvent e) {
  3604. int id = e.getID();
  3605. Component mouseOver = // sensitive to mouse events
  3606. nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
  3607. Container.INCLUDE_SELF);
  3608. trackMouseEnterExit(mouseOver, e);
  3609. // 4508327 : MOUSE_CLICKED should only go to the recipient of
  3610. // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
  3611. // MOUSE_CLICKED.
  3612. if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
  3613. mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
  3614. }
  3615. if (mouseEventTarget != null) {
  3616. switch (id) {
  3617. case MouseEvent.MOUSE_ENTERED:
  3618. case MouseEvent.MOUSE_EXITED:
  3619. break;
  3620. case MouseEvent.MOUSE_PRESSED:
  3621. retargetMouseEvent(mouseEventTarget, id, e);
  3622. break;
  3623. case MouseEvent.MOUSE_RELEASED:
  3624. retargetMouseEvent(mouseEventTarget, id, e);
  3625. break;
  3626. case MouseEvent.MOUSE_CLICKED:
  3627. // 4508327: MOUSE_CLICKED should never be dispatched to a Component
  3628. // other than that which received the MOUSE_PRESSED event. If the
  3629. // mouse is now over a different Component, don't dispatch the event.
  3630. // The previous fix for a similar problem was associated with bug
  3631. // 4155217.
  3632. if (mouseOver == mouseEventTarget) {
  3633. retargetMouseEvent(mouseOver, id, e);
  3634. }
  3635. break;
  3636. case MouseEvent.MOUSE_MOVED:
  3637. retargetMouseEvent(mouseEventTarget, id, e);
  3638. break;
  3639. case MouseEvent.MOUSE_DRAGGED:
  3640. if (isMouseGrab(e)) {
  3641. retargetMouseEvent(mouseEventTarget, id, e);
  3642. }
  3643. break;
  3644. case MouseEvent.MOUSE_WHEEL:
  3645. // This may send it somewhere that doesn't have MouseWheelEvents
  3646. // enabled. In this case, Component.dispatchEventImpl() will
  3647. // retarget the event to a parent that DOES have the events enabled.
  3648. if (dbg.on && mouseOver != null) {
  3649. dbg.println("LD retargeting mouse wheel to " +
  3650. mouseOver.getName() + ", " +
  3651. mouseOver.getClass());
  3652. }
  3653. retargetMouseEvent(mouseOver, id, e);
  3654. break;
  3655. }
  3656. e.consume();
  3657. }
  3658. return e.isConsumed();
  3659. }
  3660. private boolean processDropTargetEvent(SunDropTargetEvent e) {
  3661. int id = e.getID();
  3662. int x = e.getX();
  3663. int y = e.getY();
  3664. /*
  3665. * Fix for BugTraq ID 4395290.
  3666. * It is possible that SunDropTargetEvent's Point is outside of the
  3667. * native container bounds. In this case we truncate coordinates.
  3668. */
  3669. if (!nativeContainer.contains(x, y)) {
  3670. final Dimension d = nativeContainer.getSize();
  3671. if (d.width <= x) {
  3672. x = d.width - 1;
  3673. } else if (x < 0) {
  3674. x = 0;
  3675. }
  3676. if (d.height <= y) {
  3677. y = d.height - 1;
  3678. } else if (y < 0) {
  3679. y = 0;
  3680. }
  3681. }
  3682. Component mouseOver = // not necessarily sensitive to mouse events
  3683. nativeContainer.getDropTargetEventTarget(x, y,
  3684. Container.INCLUDE_SELF);
  3685. trackMouseEnterExit(mouseOver, e);
  3686. if (mouseOver != nativeContainer && mouseOver != null) {
  3687. switch (id) {
  3688. case SunDropTargetEvent.MOUSE_ENTERED:
  3689. case SunDropTargetEvent.MOUSE_EXITED:
  3690. break;
  3691. default:
  3692. retargetMouseEvent(mouseOver, id, e);
  3693. e.consume();
  3694. break;
  3695. }
  3696. }
  3697. return e.isConsumed();
  3698. }
  3699. /*
  3700. * Generates enter/exit events as mouse moves over lw components
  3701. * @param targetOver Target mouse is over (including native container)
  3702. * @param e Mouse event in native container
  3703. */
  3704. private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
  3705. Component targetEnter = null;
  3706. int id = e.getID();
  3707. if (e instanceof SunDropTargetEvent &&
  3708. id == MouseEvent.MOUSE_ENTERED &&
  3709. isMouseInNativeContainer == true) {
  3710. // This can happen if a lightweight component which initiated the
  3711. // drag has an associated drop target. MOUSE_ENTERED comes when the
  3712. // mouse is in the native container already. To propagate this event
  3713. // properly we should null out targetLastEntered.
  3714. targetLastEntered = null;
  3715. } else if ( id != MouseEvent.MOUSE_EXITED &&
  3716. id != MouseEvent.MOUSE_DRAGGED &&
  3717. id != LWD_MOUSE_DRAGGED_OVER &&
  3718. isMouseInNativeContainer == false ) {
  3719. // any event but an exit or drag means we're in the native container
  3720. isMouseInNativeContainer = true;
  3721. startListeningForOtherDrags();
  3722. } else if ( id == MouseEvent.MOUSE_EXITED ) {
  3723. isMouseInNativeContainer = false;
  3724. stopListeningForOtherDrags();
  3725. }
  3726. if (isMouseInNativeContainer) {
  3727. targetEnter = targetOver;
  3728. }
  3729. if (targetLastEntered == targetEnter) {
  3730. return;
  3731. }
  3732. if (targetLastEntered != null) {
  3733. retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
  3734. }
  3735. if (id == MouseEvent.MOUSE_EXITED) {
  3736. // consume native exit event if we generate one
  3737. e.consume();
  3738. }
  3739. if (targetEnter != null) {
  3740. retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
  3741. }
  3742. if (id == MouseEvent.MOUSE_ENTERED) {
  3743. // consume native enter event if we generate one
  3744. e.consume();
  3745. }
  3746. targetLastEntered = targetEnter;
  3747. }
  3748. /*
  3749. * Listens to global mouse drag events so even drags originating
  3750. * from other heavyweight containers will generate enter/exit
  3751. * events in this container
  3752. */
  3753. private void startListeningForOtherDrags() {
  3754. //System.out.println("Adding AWTEventListener");
  3755. java.security.AccessController.doPrivileged(
  3756. new java.security.PrivilegedAction() {
  3757. public Object run() {
  3758. nativeContainer.getToolkit().addAWTEventListener(
  3759. LightweightDispatcher.this,
  3760. AWTEvent.MOUSE_EVENT_MASK |
  3761. AWTEvent.MOUSE_MOTION_EVENT_MASK);
  3762. return null;
  3763. }
  3764. }
  3765. );
  3766. }
  3767. private void stopListeningForOtherDrags() {
  3768. //System.out.println("Removing AWTEventListener");
  3769. java.security.AccessController.doPrivileged(
  3770. new java.security.PrivilegedAction() {
  3771. public Object run() {
  3772. nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
  3773. return null;
  3774. }
  3775. }
  3776. );
  3777. }
  3778. /*
  3779. * (Implementation of AWTEventListener)
  3780. * Listen for drag events posted in other hw components so we can
  3781. * track enter/exit regardless of where a drag originated
  3782. */
  3783. public void eventDispatched(AWTEvent e) {
  3784. boolean isForeignDrag = (e instanceof MouseEvent) &&
  3785. !(e instanceof SunDropTargetEvent) &&
  3786. (e.id == MouseEvent.MOUSE_DRAGGED) &&
  3787. (e.getSource() != nativeContainer);
  3788. if (!isForeignDrag) {
  3789. // only interested in drags from other hw components
  3790. return;
  3791. }
  3792. MouseEvent srcEvent = (MouseEvent)e;
  3793. MouseEvent me;
  3794. synchronized (nativeContainer.getTreeLock()) {
  3795. Component srcComponent = srcEvent.getComponent();
  3796. // component may have disappeared since drag event posted
  3797. // (i.e. Swing hierarchical menus)
  3798. if ( !srcComponent.isShowing() ) {
  3799. return;
  3800. }
  3801. //
  3802. // create an internal 'dragged-over' event indicating
  3803. // we are being dragged over from another hw component
  3804. //
  3805. me = new MouseEvent(nativeContainer,
  3806. LWD_MOUSE_DRAGGED_OVER,
  3807. srcEvent.getWhen(),
  3808. srcEvent.getModifiersEx() | srcEvent.getModifiers(),
  3809. srcEvent.getX(),
  3810. srcEvent.getY(),
  3811. srcEvent.getClickCount(),
  3812. srcEvent.isPopupTrigger(),
  3813. srcEvent.getButton());
  3814. ((AWTEvent)srcEvent).copyPrivateDataInto(me);
  3815. // translate coordinates to this native container
  3816. final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
  3817. if (AppContext.getAppContext() != nativeContainer.appContext) {
  3818. final MouseEvent mouseEvent = me;
  3819. Runnable r = new Runnable() {
  3820. public void run() {
  3821. if (!nativeContainer.isShowing() ) {
  3822. return;
  3823. }
  3824. Point ptDstOrigin = nativeContainer.getLocationOnScreen();
  3825. mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
  3826. ptSrcOrigin.y - ptDstOrigin.y );
  3827. Component targetOver =
  3828. nativeContainer.getMouseEventTarget(mouseEvent.getX(),
  3829. mouseEvent.getY(),
  3830. Container.INCLUDE_SELF);
  3831. trackMouseEnterExit(targetOver, mouseEvent);
  3832. }
  3833. };
  3834. SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
  3835. return;
  3836. } else {
  3837. if (!nativeContainer.isShowing() ) {
  3838. return;
  3839. }
  3840. Point ptDstOrigin = nativeContainer.getLocationOnScreen();
  3841. me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
  3842. }
  3843. }
  3844. //System.out.println("Track event: " + me);
  3845. // feed the 'dragged-over' event directly to the enter/exit
  3846. // code (not a real event so don't pass it to dispatchEvent)
  3847. Component targetOver =
  3848. nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
  3849. Container.INCLUDE_SELF);
  3850. trackMouseEnterExit(targetOver, me);
  3851. }
  3852. /**
  3853. * Sends a mouse event to the current mouse event recipient using
  3854. * the given event (sent to the windowed host) as a srcEvent. If
  3855. * the mouse event target is still in the component tree, the
  3856. * coordinates of the event are translated to those of the target.
  3857. * If the target has been removed, we don't bother to send the
  3858. * message.
  3859. */
  3860. void retargetMouseEvent(Component target, int id, MouseEvent e) {
  3861. if (target == null) {
  3862. return; // mouse is over another hw component or target is disabled
  3863. }
  3864. int x = e.getX(), y = e.getY();
  3865. Component component;
  3866. for(component = target;
  3867. component != null && component != nativeContainer;
  3868. component = component.getParent()) {
  3869. x -= component.x;
  3870. y -= component.y;
  3871. }
  3872. MouseEvent retargeted;
  3873. if (component != null) {
  3874. if (e instanceof SunDropTargetEvent) {
  3875. retargeted = new SunDropTargetEvent(target,
  3876. id,
  3877. x,
  3878. y,
  3879. ((SunDropTargetEvent)e).getDispatcher());
  3880. } else if (id == MouseEvent.MOUSE_WHEEL) {
  3881. retargeted = new MouseWheelEvent(target,
  3882. id,
  3883. e.getWhen(),
  3884. e.getModifiersEx() | e.getModifiers(),
  3885. x,
  3886. y,
  3887. e.getClickCount(),
  3888. e.isPopupTrigger(),
  3889. ((MouseWheelEvent)e).getScrollType(),
  3890. ((MouseWheelEvent)e).getScrollAmount(),
  3891. ((MouseWheelEvent)e).getWheelRotation());
  3892. }
  3893. else {
  3894. retargeted = new MouseEvent(target,
  3895. id,
  3896. e.getWhen(),
  3897. e.getModifiersEx() | e.getModifiers(),
  3898. x,
  3899. y,
  3900. e.getClickCount(),
  3901. e.isPopupTrigger(),
  3902. e.getButton());
  3903. }
  3904. ((AWTEvent)e).copyPrivateDataInto(retargeted);
  3905. if (target == nativeContainer) {
  3906. // avoid recursively calling LightweightDispatcher...
  3907. ((Container)target).dispatchEventToSelf(retargeted);
  3908. } else {
  3909. assert AppContext.getAppContext() == target.appContext;
  3910. if (nativeContainer.modalComp != null) {
  3911. if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
  3912. target.dispatchEvent(retargeted);
  3913. } else {
  3914. e.consume();
  3915. }
  3916. } else {
  3917. target.dispatchEvent(retargeted);
  3918. }
  3919. }
  3920. }
  3921. }
  3922. // --- member variables -------------------------------
  3923. /**
  3924. * The windowed container that might be hosting events for
  3925. * subcomponents.
  3926. */
  3927. private Container nativeContainer;
  3928. /**
  3929. * This variable is not used, but kept for serialization compatibility
  3930. */
  3931. private Component focus;
  3932. /**
  3933. * The current subcomponent being hosted by this windowed
  3934. * component that has events being forwarded to it. If this
  3935. * is null, there are currently no events being forwarded to
  3936. * a subcomponent.
  3937. */
  3938. private transient Component mouseEventTarget;
  3939. /**
  3940. * The last component entered
  3941. */
  3942. private transient Component targetLastEntered;
  3943. /**
  3944. * Is the mouse over the native container
  3945. */
  3946. private transient boolean isMouseInNativeContainer = false;
  3947. /**
  3948. * This variable is not used, but kept for serialization compatibility
  3949. */
  3950. private Cursor nativeCursor;
  3951. /**
  3952. * The event mask for contained lightweight components. Lightweight
  3953. * components need a windowed container to host window-related
  3954. * events. This separate mask indicates events that have been
  3955. * requested by contained lightweight components without effecting
  3956. * the mask of the windowed component itself.
  3957. */
  3958. private long eventMask;
  3959. /**
  3960. * The kind of events routed to lightweight components from windowed
  3961. * hosts.
  3962. */
  3963. private static final long PROXY_EVENT_MASK =
  3964. AWTEvent.FOCUS_EVENT_MASK |
  3965. AWTEvent.KEY_EVENT_MASK |
  3966. AWTEvent.MOUSE_EVENT_MASK |
  3967. AWTEvent.MOUSE_MOTION_EVENT_MASK |
  3968. AWTEvent.MOUSE_WHEEL_EVENT_MASK;
  3969. private static final long MOUSE_MASK =
  3970. AWTEvent.MOUSE_EVENT_MASK |
  3971. AWTEvent.MOUSE_MOTION_EVENT_MASK |
  3972. AWTEvent.MOUSE_WHEEL_EVENT_MASK;
  3973. }