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