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 !=