1. /*
  2. * @(#)Container.java 1.181 00/04/06
  3. *
  4. * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.awt;
  11. import java.io.PrintStream;
  12. import java.io.PrintWriter;
  13. import java.awt.peer.ContainerPeer;
  14. import java.awt.peer.ComponentPeer;
  15. import java.awt.event.ComponentEvent;
  16. import java.awt.event.ContainerEvent;
  17. import java.awt.event.FocusEvent;
  18. import java.awt.event.HierarchyEvent;
  19. import java.awt.event.InputEvent;
  20. import java.awt.event.KeyEvent;
  21. import java.awt.event.MouseEvent;
  22. import java.awt.event.ContainerListener;
  23. import java.util.EventListener;
  24. import java.io.ObjectOutputStream;
  25. import java.io.ObjectInputStream;
  26. import java.io.IOException;
  27. import java.awt.event.AWTEventListener;
  28. import java.awt.event.WindowAdapter;
  29. import java.awt.event.WindowListener;
  30. import java.awt.event.WindowEvent;
  31. import java.util.Stack;
  32. import java.util.Vector;
  33. import javax.accessibility.*;
  34. import javax.swing.JRootPane;
  35. import sun.awt.DebugHelper;
  36. import sun.awt.GlobalCursorManager;
  37. /**
  38. * A generic Abstract Window Toolkit(AWT) container object is a component
  39. * that can contain other AWT components.
  40. * <p>
  41. * Components added to a container are tracked in a list. The order
  42. * of the list will define the components' front-to-back stacking order
  43. * within the container. If no index is specified when adding a
  44. * component to a container, it will be added to the end of the list
  45. * (and hence to the bottom of the stacking order).
  46. * @version 1.181, 04/06/00
  47. * @author Arthur van Hoff
  48. * @author Sami Shaio
  49. * @see java.awt.Container#add(java.awt.Component, int)
  50. * @see java.awt.Container#getComponent(int)
  51. * @see java.awt.LayoutManager
  52. * @since JDK1.0
  53. */
  54. public class Container extends Component {
  55. /**
  56. * The number of components in this container.
  57. * This value can be null.
  58. * @serial
  59. * @see getComponent()
  60. * @see getComponents()
  61. * @see getComponentCount()
  62. */
  63. int ncomponents;
  64. /**
  65. * The components in this container.
  66. * @serial
  67. * @see add()
  68. * @see getComponents()
  69. */
  70. Component component[] = new Component[4];
  71. /**
  72. * Layout manager for this container.
  73. * @serial
  74. * @see doLayout()
  75. * @see setLayout()
  76. * @see getLayout()
  77. */
  78. LayoutManager layoutMgr;
  79. /**
  80. * Event router for lightweight components. If this container
  81. * is native, this dispatcher takes care of forwarding and
  82. * retargeting the events to lightweight components contained
  83. * (if any).
  84. * @serial
  85. */
  86. private LightweightDispatcher dispatcher;
  87. /*
  88. * Internal, cached size information.
  89. * @serial
  90. * @see getMaximumSize()
  91. * @see getPreferredSize()
  92. */
  93. private Dimension maxSize;
  94. // keeps track of the threads that are printing this component
  95. private transient Vector printingThreads = new Vector();
  96. // True if there is at least one thread that's printing this component
  97. private transient boolean printing = false;
  98. transient ContainerListener containerListener;
  99. /* HierarchyListener and HierarchyBoundsListener support */
  100. transient int listeningChildren;
  101. transient int listeningBoundsChildren;
  102. /*
  103. * JDK 1.1 serialVersionUID
  104. */
  105. private static final long serialVersionUID = 4613797578919906343L;
  106. private static final DebugHelper dbg = DebugHelper.create(Container.class);
  107. static {
  108. /* ensure that the necessary native libraries are loaded */
  109. Toolkit.loadLibraries();
  110. initIDs();
  111. }
  112. /**
  113. * Initialize JNI field and method IDs for fields that may be
  114. called from C.
  115. */
  116. private static native void initIDs();
  117. /**
  118. * Constructs a new Container. Containers can be extended directly,
  119. * but are lightweight in this case and must be contained by a parent
  120. * somewhere higher up in the component tree that is native.
  121. * (such as Frame for example).
  122. */
  123. public Container() {
  124. }
  125. /**
  126. * Gets the number of components in this panel.
  127. * @return the number of components in this panel.
  128. * @see java.awt.Container#getComponent
  129. * @since JDK1.1
  130. */
  131. public int getComponentCount() {
  132. return countComponents();
  133. }
  134. /**
  135. * @deprecated As of JDK version 1.1,
  136. * replaced by getComponentCount().
  137. */
  138. public int countComponents() {
  139. return ncomponents;
  140. }
  141. /**
  142. * Gets the nth component in this container.
  143. * @param n the index of the component to get.
  144. * @return the n<sup>th</sup> component in this container.
  145. * @exception ArrayIndexOutOfBoundsException
  146. * if the n<sup>th</sup> value does not exist.
  147. */
  148. public Component getComponent(int n) {
  149. synchronized (getTreeLock()) {
  150. if ((n < 0) || (n >= ncomponents)) {
  151. throw new ArrayIndexOutOfBoundsException("No such child: " + n);
  152. }
  153. return component[n];
  154. }
  155. }
  156. /**
  157. * Gets all the components in this container.
  158. * @return an array of all the components in this container.
  159. */
  160. public Component[] getComponents() {
  161. return getComponents_NoClientCode();
  162. }
  163. // NOTE: This method may be called by privileged threads.
  164. // This functionality is implemented in a package-private method
  165. // to insure that it cannot be overridden by client subclasses.
  166. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  167. final Component[] getComponents_NoClientCode() {
  168. synchronized (getTreeLock()) {
  169. Component list[] = new Component[ncomponents];
  170. System.arraycopy(component, 0, list, 0, ncomponents);
  171. return list;
  172. }
  173. } // getComponents_NoClientCode()
  174. /**
  175. * Determines the insets of this container, which indicate the size
  176. * of the container's border.
  177. * <p>
  178. * A <code>Frame</code> object, for example, has a top inset that
  179. * corresponds to the height of the frame's title bar.
  180. * @return the insets of this container.
  181. * @see java.awt.Insets
  182. * @see java.awt.LayoutManager
  183. * @since JDK1.1
  184. */
  185. public Insets getInsets() {
  186. return insets();
  187. }
  188. /**
  189. * @deprecated As of JDK version 1.1,
  190. * replaced by <code>getInsets()</code>.
  191. */
  192. public Insets insets() {
  193. if (this.peer != null && this.peer instanceof ContainerPeer) {
  194. ContainerPeer peer = (ContainerPeer)this.peer;
  195. return (Insets)peer.insets().clone();
  196. }
  197. return new Insets(0, 0, 0, 0);
  198. }
  199. /**
  200. * Adds the specified component to the end of this container.
  201. * @param comp the component to be added.
  202. * @return the component argument.
  203. */
  204. public Component add(Component comp) {
  205. addImpl(comp, null, -1);
  206. return comp;
  207. }
  208. /**
  209. * Adds the specified component to this container.
  210. * It is strongly advised to use the 1.1 method, add(Component, Object),
  211. * in place of this method.
  212. */
  213. public Component add(String name, Component comp) {
  214. addImpl(comp, name, -1);
  215. return comp;
  216. }
  217. /**
  218. * Adds the specified component to this container at the given
  219. * position.
  220. * @param comp the component to be added.
  221. * @param index the position at which to insert the component,
  222. * or <code>-1</code> to insert the component at the end.
  223. * @return the component <code>comp</code>
  224. * @see #remove
  225. */
  226. public Component add(Component comp, int index) {
  227. addImpl(comp, null, index);
  228. return comp;
  229. }
  230. /**
  231. * Adds the specified component to the end of this container.
  232. * Also notifies the layout manager to add the component to
  233. * this container's layout using the specified constraints object.
  234. * @param comp the component to be added
  235. * @param constraints an object expressing
  236. * layout contraints for this component
  237. * @see java.awt.LayoutManager
  238. * @since JDK1.1
  239. */
  240. public void add(Component comp, Object constraints) {
  241. addImpl(comp, constraints, -1);
  242. }
  243. /**
  244. * Adds the specified component to this container with the specified
  245. * constraints at the specified index. Also notifies the layout
  246. * manager to add the component to the this container's layout using
  247. * the specified constraints object.
  248. * @param comp the component to be added
  249. * @param constraints an object expressing layout contraints for this
  250. * @param index the position in the container's list at which to insert
  251. * the component. -1 means insert at the end.
  252. * component
  253. * @see #remove
  254. * @see LayoutManager
  255. */
  256. public void add(Component comp, Object constraints, int index) {
  257. addImpl(comp, constraints, index);
  258. }
  259. /**
  260. * Adds the specified component to this container at the specified
  261. * index. This method also notifies the layout manager to add
  262. * the component to this container's layout using the specified
  263. * constraints object.
  264. * <p>
  265. * This is the method to override if a program needs to track
  266. * every add request to a container. An overriding method should
  267. * usually include a call to the superclass's version of the method:
  268. * <p>
  269. * <blockquote>
  270. * <code>super.addImpl(comp, constraints, index)</code>
  271. * </blockquote>
  272. * <p>
  273. * @param comp the component to be added.
  274. * @param constraints an object expressing layout contraints
  275. * for this component.
  276. * @param index the position in the container's list at which to
  277. * insert the component, where <code>-1</code>
  278. * means insert at the end.
  279. * @see java.awt.Container#add(java.awt.Component)
  280. * @see java.awt.Container#add(java.awt.Component, int)
  281. * @see java.awt.Container#add(java.awt.Component, java.lang.Object)
  282. * @see java.awt.LayoutManager
  283. * @since JDK1.1
  284. */
  285. protected void addImpl(Component comp, Object constraints, int index) {
  286. synchronized (getTreeLock()) {
  287. /* Check for correct arguments: index in bounds,
  288. * comp cannot be one of this container's parents,
  289. * and comp cannot be a window.
  290. * comp and container must be on the same GraphicsDevice.
  291. * if comp is container, all sub-components must be on
  292. * same GraphicsDevice.
  293. */
  294. GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
  295. if (index > ncomponents || (index < 0 && index != -1)) {
  296. throw new IllegalArgumentException(
  297. "illegal component position");
  298. }
  299. if (comp instanceof Container) {
  300. for (Container cn = this; cn != null; cn=cn.parent) {
  301. if (cn == comp) {
  302. throw new IllegalArgumentException(
  303. "adding container's parent to itself");
  304. }
  305. }
  306. if (comp instanceof Window) {
  307. throw new IllegalArgumentException(
  308. "adding a window to a container");
  309. }
  310. }
  311. if (thisGC != null) {
  312. comp.checkGD(thisGC.getDevice().getIDstring());
  313. }
  314. /* Reparent the component and tidy up the tree's state. */
  315. if (comp.parent != null) {
  316. comp.parent.remove(comp);
  317. }
  318. /* Add component to list; allocate new array if necessary. */
  319. if (ncomponents == component.length) {
  320. Component newcomponents[] = new Component[ncomponents * 2];
  321. System.arraycopy(component, 0, newcomponents, 0, ncomponents);
  322. component = newcomponents;
  323. }
  324. if (index == -1 || index == ncomponents) {
  325. component[ncomponents++] = comp;
  326. } else {
  327. System.arraycopy(component, index, component,
  328. index + 1, ncomponents - index);
  329. component[index] = comp;
  330. ncomponents++;
  331. }
  332. comp.parent = this;
  333. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  334. comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  335. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  336. comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  337. if (valid) {
  338. invalidate();
  339. }
  340. if (peer != null) {
  341. comp.addNotify();
  342. }
  343. /* Notify the layout manager of the added component. */
  344. if (layoutMgr != null) {
  345. if (layoutMgr instanceof LayoutManager2) {
  346. ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
  347. } else if (constraints instanceof String) {
  348. layoutMgr.addLayoutComponent((String)constraints, comp);
  349. }
  350. }
  351. if (containerListener != null ||
  352. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  353. ContainerEvent e = new ContainerEvent(this,
  354. ContainerEvent.COMPONENT_ADDED,
  355. comp);
  356. dispatchEvent(e);
  357. }
  358. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  359. this, HierarchyEvent.PARENT_CHANGED);
  360. if (peer != null && layoutMgr == null && isVisible()) {
  361. GlobalCursorManager.updateCursorImmediately();
  362. }
  363. }
  364. }
  365. /**
  366. * Checks that all Components that this Container contains are on
  367. * the same GraphicsDevice as this Container. If not, throws an
  368. * IllegalArgumentException.
  369. */
  370. void checkGD(String stringID) {
  371. Component tempComp;
  372. for (int i = 0; i < component.length; i++) {
  373. tempComp= component[i];
  374. if (tempComp != null) {
  375. tempComp.checkGD(stringID);
  376. }
  377. }
  378. }
  379. /**
  380. * Removes the component, specified by <code>index</code>,
  381. * from this container.
  382. * @param index the index of the component to be removed.
  383. * @see #add
  384. * @since JDK1.1
  385. */
  386. public void remove(int index) {
  387. synchronized (getTreeLock()) {
  388. Component comp = component[index];
  389. if (peer != null) {
  390. comp.removeNotify();
  391. }
  392. if (layoutMgr != null) {
  393. layoutMgr.removeLayoutComponent(comp);
  394. }
  395. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  396. -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  397. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  398. -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  399. comp.parent = null;
  400. System.arraycopy(component, index + 1,
  401. component, index,
  402. ncomponents - index - 1);
  403. component[--ncomponents] = null;
  404. if (valid) {
  405. invalidate();
  406. }
  407. if (containerListener != null ||
  408. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  409. ContainerEvent e = new ContainerEvent(this,
  410. ContainerEvent.COMPONENT_REMOVED,
  411. comp);
  412. dispatchEvent(e);
  413. }
  414. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  415. this, HierarchyEvent.PARENT_CHANGED);
  416. if (peer != null && layoutMgr == null && isVisible()) {
  417. GlobalCursorManager.updateCursorImmediately();
  418. }
  419. }
  420. }
  421. /**
  422. * Removes the specified component from this container.
  423. * @param comp the component to be removed
  424. * @see #add
  425. */
  426. public void remove(Component comp) {
  427. synchronized (getTreeLock()) {
  428. if (comp.parent == this) {
  429. /* Search backwards, expect that more recent additions
  430. * are more likely to be removed.
  431. */
  432. Component component[] = this.component;
  433. for (int i = ncomponents; --i >= 0; ) {
  434. if (component[i] == comp) {
  435. remove(i);
  436. }
  437. }
  438. }
  439. }
  440. }
  441. /**
  442. * Removes all the components from this container.
  443. * @see #add
  444. * @see #remove
  445. */
  446. public void removeAll() {
  447. synchronized (getTreeLock()) {
  448. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  449. -listeningChildren);
  450. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  451. -listeningBoundsChildren);
  452. while (ncomponents > 0) {
  453. Component comp = component[--ncomponents];
  454. component[ncomponents] = null;
  455. if (peer != null) {
  456. comp.removeNotify();
  457. }
  458. if (layoutMgr != null) {
  459. layoutMgr.removeLayoutComponent(comp);
  460. }
  461. comp.parent = null;
  462. if (containerListener != null ||
  463. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  464. ContainerEvent e = new ContainerEvent(this,
  465. ContainerEvent.COMPONENT_REMOVED,
  466. comp);
  467. dispatchEvent(e);
  468. }
  469. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
  470. comp, this,
  471. HierarchyEvent.PARENT_CHANGED);
  472. }
  473. if (peer != null && layoutMgr == null && isVisible()) {
  474. GlobalCursorManager.updateCursorImmediately();
  475. }
  476. if (valid) {
  477. invalidate();
  478. }
  479. }
  480. }
  481. // Should only be called while holding tree lock
  482. int numListening(long mask) {
  483. int superListening = super.numListening(mask);
  484. if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
  485. if (dbg.on) {
  486. // Verify listeningChildren is correct
  487. int sum = 0;
  488. for (int i = 0; i < ncomponents; i++) {
  489. sum += component[i].numListening(mask);
  490. }
  491. dbg.assert(listeningChildren == sum);
  492. }
  493. return listeningChildren + superListening;
  494. } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
  495. if (dbg.on) {
  496. // Verify listeningBoundsChildren is correct
  497. int sum = 0;
  498. for (int i = 0; i < ncomponents; i++) {
  499. sum += component[i].numListening(mask);
  500. }
  501. dbg.assert(listeningBoundsChildren == sum);
  502. }
  503. return listeningBoundsChildren + superListening;
  504. } else {
  505. if (dbg.on) {
  506. dbg.assert(false);
  507. }
  508. return superListening;
  509. }
  510. }
  511. // Should only be called while holding tree lock
  512. void adjustListeningChildren(long mask, int num) {
  513. if (dbg.on) {
  514. dbg.assert(mask == AWTEvent.HIERARCHY_EVENT_MASK ||
  515. mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
  516. mask == (AWTEvent.HIERARCHY_EVENT_MASK |
  517. AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  518. }
  519. if (num == 0)
  520. return;
  521. if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
  522. listeningChildren += num;
  523. }
  524. if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
  525. listeningBoundsChildren += num;
  526. }
  527. if (parent != null) {
  528. parent.adjustListeningChildren(mask, num);
  529. }
  530. }
  531. // Should only be called while holding tree lock
  532. int createHierarchyEvents(int id, Component changed,
  533. Container changedParent, long changeFlags) {
  534. int listeners = 0;
  535. switch (id) {
  536. case HierarchyEvent.HIERARCHY_CHANGED:
  537. listeners = listeningChildren;
  538. break;
  539. case HierarchyEvent.ANCESTOR_MOVED:
  540. case HierarchyEvent.ANCESTOR_RESIZED:
  541. if (dbg.on) {
  542. dbg.assert(changeFlags == 0);
  543. }
  544. listeners = listeningBoundsChildren;
  545. break;
  546. default:
  547. if (dbg.on) {
  548. dbg.assert(false);
  549. }
  550. break;
  551. }
  552. for (int count = listeners, i = 0; count > 0; i++) {
  553. count -= component[i].createHierarchyEvents(id, changed,
  554. changedParent,
  555. changeFlags);
  556. }
  557. return listeners +
  558. super.createHierarchyEvents(id, changed, changedParent,
  559. changeFlags);
  560. }
  561. void createChildHierarchyEvents(int id, long changeFlags) {
  562. synchronized (getTreeLock()) {
  563. int listeners = 0;
  564. switch (id) {
  565. case HierarchyEvent.HIERARCHY_CHANGED:
  566. listeners = listeningChildren;
  567. break;
  568. case HierarchyEvent.ANCESTOR_MOVED:
  569. case HierarchyEvent.ANCESTOR_RESIZED:
  570. if (dbg.on) {
  571. dbg.assert(changeFlags == 0);
  572. }
  573. listeners = listeningBoundsChildren;
  574. break;
  575. default:
  576. if (dbg.on) {
  577. dbg.assert(false);
  578. }
  579. break;
  580. }
  581. for (int count = listeners, i = 0; count > 0; i++) {
  582. count -= component[i].createHierarchyEvents(id, this, parent,
  583. changeFlags);
  584. }
  585. }
  586. }
  587. /**
  588. * Gets the layout manager for this container.
  589. * @see #doLayout
  590. * @see #setLayout
  591. */
  592. public LayoutManager getLayout() {
  593. return layoutMgr;
  594. }
  595. /**
  596. * Sets the layout manager for this container.
  597. * @param mgr the specified layout manager
  598. * @see #doLayout
  599. * @see #getLayout
  600. */
  601. public void setLayout(LayoutManager mgr) {
  602. layoutMgr = mgr;
  603. if (valid) {
  604. invalidate();
  605. }
  606. }
  607. /**
  608. * Causes this container to lay out its components. Most programs
  609. * should not call this method directly, but should invoke
  610. * the <code>validate</code> method instead.
  611. * @see java.awt.LayoutManager#layoutContainer
  612. * @see #setLayout
  613. * @see #validate
  614. * @since JDK1.1
  615. */
  616. public void doLayout() {
  617. layout();
  618. }
  619. /**
  620. * @deprecated As of JDK version 1.1,
  621. * replaced by <code>doLayout()</code>.
  622. */
  623. public void layout() {
  624. LayoutManager layoutMgr = this.layoutMgr;
  625. if (layoutMgr != null) {
  626. layoutMgr.layoutContainer(this);
  627. }
  628. }
  629. /**
  630. * Invalidates the container. The container and all parents
  631. * above it are marked as needing to be laid out. This method can
  632. * be called often, so it needs to execute quickly.
  633. * @see #validate
  634. * @see #layout
  635. * @see LayoutManager
  636. */
  637. public void invalidate() {
  638. if (layoutMgr instanceof LayoutManager2) {
  639. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  640. lm.invalidateLayout(this);
  641. }
  642. super.invalidate();
  643. }
  644. /**
  645. * Validates this container and all of its subcomponents.
  646. * <p>
  647. * AWT uses <code>validate</code> to cause a container to lay out
  648. * its subcomponents again after the components it contains
  649. * have been added to or modified.
  650. * @see #validate
  651. * @see Component#invalidate
  652. */
  653. public void validate() {
  654. /* Avoid grabbing lock unless really necessary. */
  655. if (!valid) {
  656. boolean updateCur = false;
  657. synchronized (getTreeLock()) {
  658. if (!valid && peer != null) {
  659. ContainerPeer p = null;
  660. if (peer instanceof ContainerPeer) {
  661. p = (ContainerPeer) peer;
  662. }
  663. if (p != null) {
  664. p.beginValidate();
  665. }
  666. validateTree();
  667. valid = true;
  668. if (p != null) {
  669. p.endValidate();
  670. updateCur = isVisible();
  671. }
  672. }
  673. }
  674. if (updateCur) {
  675. GlobalCursorManager.updateCursorImmediately();
  676. }
  677. }
  678. }
  679. /**
  680. * Recursively descends the container tree and recomputes the
  681. * layout for any subtrees marked as needing it (those marked as
  682. * invalid). Synchronization should be provided by the method
  683. * that calls this one: <code>validate</code>.
  684. */
  685. protected void validateTree() {
  686. if (!valid) {
  687. doLayout();
  688. Component component[] = this.component;
  689. for (int i = 0 ; i < ncomponents ; ++i) {
  690. Component comp = component[i];
  691. if ( (comp instanceof Container)
  692. && !(comp instanceof Window)
  693. && !comp.valid) {
  694. ((Container)comp).validateTree();
  695. } else {
  696. comp.validate();
  697. }
  698. }
  699. }
  700. valid = true;
  701. }
  702. /**
  703. * Recursively descends the container tree and invalidates all
  704. * contained components.
  705. */
  706. void invalidateTree() {
  707. synchronized (getTreeLock()) {
  708. for (int i = 0; i < ncomponents; ++i) {
  709. Component comp = component[i];
  710. if (comp instanceof Container) {
  711. ((Container)comp).invalidateTree();
  712. }
  713. else {
  714. if (comp.valid) {
  715. comp.invalidate();
  716. }
  717. }
  718. }
  719. if (valid) {
  720. invalidate();
  721. }
  722. }
  723. }
  724. /**
  725. * Sets the font of this container.
  726. * @param f The font to become this container's font.
  727. * @see Component#getFont
  728. * @since JDK1.0
  729. */
  730. public void setFont(Font f) {
  731. boolean shouldinvalidate = false;
  732. Font oldfont = getFont();
  733. super.setFont(f);
  734. Font newfont = getFont();
  735. if (newfont != oldfont && (oldfont == null ||
  736. !oldfont.equals(newfont))) {
  737. invalidateTree();
  738. }
  739. }
  740. /**
  741. * Returns the preferred size of this container.
  742. * @return an instance of <code>Dimension</code> that represents
  743. * the preferred size of this container.
  744. * @see java.awt.Container#getMinimumSize
  745. * @see java.awt.Container#getLayout
  746. * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
  747. * @see java.awt.Component#getPreferredSize
  748. */
  749. public Dimension getPreferredSize() {
  750. return preferredSize();
  751. }
  752. /**
  753. * @deprecated As of JDK version 1.1,
  754. * replaced by <code>getPreferredSize()</code>.
  755. */
  756. public Dimension preferredSize() {
  757. /* Avoid grabbing the lock if a reasonable cached size value
  758. * is available.
  759. */
  760. Dimension dim = prefSize;
  761. if (dim != null && isValid()) {
  762. return dim;
  763. }
  764. synchronized (getTreeLock()) {
  765. prefSize = (layoutMgr != null) ?
  766. layoutMgr.preferredLayoutSize(this) :
  767. super.preferredSize();
  768. return prefSize;
  769. }
  770. }
  771. /**
  772. * Returns the minimum size of this container.
  773. * @return an instance of <code>Dimension</code> that represents
  774. * the minimum size of this container.
  775. * @see java.awt.Container#getPreferredSize
  776. * @see java.awt.Container#getLayout
  777. * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
  778. * @see java.awt.Component#getMinimumSize
  779. * @since JDK1.1
  780. */
  781. public Dimension getMinimumSize() {
  782. return minimumSize();
  783. }
  784. /**
  785. * @deprecated As of JDK version 1.1,
  786. * replaced by <code>getMinimumSize()</code>.
  787. */
  788. public Dimension minimumSize() {
  789. /* Avoid grabbing the lock if a reasonable cached size value
  790. * is available.
  791. */
  792. Dimension dim = minSize;
  793. if (dim != null && isValid()) {
  794. return dim;
  795. }
  796. synchronized (getTreeLock()) {
  797. minSize = (layoutMgr != null) ?
  798. layoutMgr.minimumLayoutSize(this) :
  799. super.minimumSize();
  800. return minSize;
  801. }
  802. }
  803. /**
  804. * Returns the maximum size of this container.
  805. * @see #getPreferredSize
  806. */
  807. public Dimension getMaximumSize() {
  808. /* Avoid grabbing the lock if a reasonable cached size value
  809. * is available.
  810. */
  811. Dimension dim = maxSize;
  812. if (dim != null && isValid()) {
  813. return dim;
  814. }
  815. if (layoutMgr instanceof LayoutManager2) {
  816. synchronized (getTreeLock()) {
  817. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  818. maxSize = lm.maximumLayoutSize(this);
  819. }
  820. } else {
  821. maxSize = super.getMaximumSize();
  822. }
  823. return maxSize;
  824. }
  825. /**
  826. * Returns the alignment along the x axis. This specifies how
  827. * the component would like to be aligned relative to other
  828. * components. The value should be a number between 0 and 1
  829. * where 0 represents alignment along the origin, 1 is aligned
  830. * the furthest away from the origin, 0.5 is centered, etc.
  831. */
  832. public float getAlignmentX() {
  833. float xAlign;
  834. if (layoutMgr instanceof LayoutManager2) {
  835. synchronized (getTreeLock()) {
  836. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  837. xAlign = lm.getLayoutAlignmentX(this);
  838. }
  839. } else {
  840. xAlign = super.getAlignmentX();
  841. }
  842. return xAlign;
  843. }
  844. /**
  845. * Returns the alignment along the y axis. This specifies how
  846. * the component would like to be aligned relative to other
  847. * components. The value should be a number between 0 and 1
  848. * where 0 represents alignment along the origin, 1 is aligned
  849. * the furthest away from the origin, 0.5 is centered, etc.
  850. */
  851. public float getAlignmentY() {
  852. float yAlign;
  853. if (layoutMgr instanceof LayoutManager2) {
  854. synchronized (getTreeLock()) {
  855. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  856. yAlign = lm.getLayoutAlignmentY(this);
  857. }
  858. } else {
  859. yAlign = super.getAlignmentY();
  860. }
  861. return yAlign;
  862. }
  863. /**
  864. * Paints the container. This forwards the paint to any lightweight
  865. * components that are children of this container. If this method is
  866. * reimplemented, super.paint(g) should be called so that lightweight
  867. * components are properly rendered. If a child component is entirely
  868. * clipped by the current clipping setting in g, paint() will not be
  869. * forwarded to that child.
  870. *
  871. * @param g the specified Graphics window
  872. * @see java.awt.Component#update(java.awt.Graphics)
  873. */
  874. public void paint(Graphics g) {
  875. if (isShowing() &&
  876. (!printing ||
  877. !printingThreads.contains(Thread.currentThread())) ) {
  878. // The container is showing on screen and
  879. // this paint() is not called from print().
  880. // Paint self and forward the paint to lightweight subcomponents.
  881. // super.paint(); -- Don't bother, since it's a NOP.
  882. GraphicsCallback.PaintCallback.getInstance().
  883. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
  884. }
  885. }
  886. /**
  887. * Updates the container. This forwards the update to any lightweight
  888. * components that are children of this container. If this method is
  889. * reimplemented, super.update(g) should be called so that lightweight
  890. * components are properly rendered. If a child component is entirely
  891. * clipped by the current clipping setting in g, update() will not be
  892. * forwarded to that child.
  893. *
  894. * @param g the specified Graphics window
  895. * @see java.awt.Component#update(java.awt.Graphics)
  896. */
  897. public void update(Graphics g) {
  898. if (isShowing()) {
  899. if (! (peer instanceof java.awt.peer.LightweightPeer)) {
  900. g.clearRect(0, 0, width, height);
  901. }
  902. paint(g);
  903. }
  904. }
  905. /**
  906. * Prints the container. This forwards the print to any lightweight
  907. * components that are children of this container. If this method is
  908. * reimplemented, super.print(g) should be called so that lightweight
  909. * components are properly rendered. If a child component is entirely
  910. * clipped by the current clipping setting in g, print() will not be
  911. * forwarded to that child.
  912. *
  913. * @param g the specified Graphics window
  914. * @see java.awt.Component#update(java.awt.Graphics)
  915. */
  916. public void print(Graphics g) {
  917. if (isShowing()) {
  918. Thread t = Thread.currentThread();
  919. try {
  920. printingThreads.addElement(t);
  921. printing = true;
  922. super.print(g); // By default, Component.print() calls paint()
  923. } finally {
  924. printingThreads.removeElement(t);
  925. printing = !printingThreads.isEmpty();
  926. }
  927. GraphicsCallback.PrintCallback.getInstance().
  928. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
  929. }
  930. }
  931. /**
  932. * Paints each of the components in this container.
  933. * @param g the graphics context.
  934. * @see java.awt.Component#paint
  935. * @see java.awt.Component#paintAll
  936. */
  937. public void paintComponents(Graphics g) {
  938. if (isShowing()) {
  939. GraphicsCallback.PaintAllCallback.getInstance().
  940. runComponents(component, g, GraphicsCallback.TWO_PASSES);
  941. }
  942. }
  943. /**
  944. * Simulates the peer callbacks into java.awt for printing of
  945. * lightweight Containers.
  946. * @param g the graphics context to use for printing.
  947. * @see Component#printAll
  948. * @see #printComponents
  949. */
  950. void lightweightPaint(Graphics g) {
  951. super.lightweightPaint(g);
  952. paintHeavyweightComponents(g);
  953. }
  954. /**
  955. * Prints all the heavyweight subcomponents.
  956. */
  957. void paintHeavyweightComponents(Graphics g) {
  958. if (isShowing()) {
  959. GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
  960. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
  961. GraphicsCallback.HEAVYWEIGHTS);
  962. }
  963. }
  964. /**
  965. * Prints each of the components in this container.
  966. * @param g the graphics context.
  967. * @see java.awt.Component#print
  968. * @see java.awt.Component#printAll
  969. */
  970. public void printComponents(Graphics g) {
  971. if (isShowing()) {
  972. GraphicsCallback.PrintAllCallback.getInstance().
  973. runComponents(component, g, GraphicsCallback.TWO_PASSES);
  974. }
  975. }
  976. /**
  977. * Simulates the peer callbacks into java.awt for printing of
  978. * lightweight Containers.
  979. * @param g the graphics context to use for printing.
  980. * @see Component#printAll
  981. * @see #printComponents
  982. */
  983. void lightweightPrint(Graphics g) {
  984. super.lightweightPrint(g);
  985. printHeavyweightComponents(g);
  986. }
  987. /**
  988. * Prints all the heavyweight subcomponents.
  989. */
  990. void printHeavyweightComponents(Graphics g) {
  991. if (isShowing()) {
  992. GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
  993. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
  994. GraphicsCallback.HEAVYWEIGHTS);
  995. }
  996. }
  997. /**
  998. * Adds the specified container listener to receive container events
  999. * from this container.
  1000. * If l is null, no exception is thrown and no action is performed.
  1001. *
  1002. * @param l the container listener
  1003. */
  1004. public synchronized void addContainerListener(ContainerListener l) {
  1005. if (l == null) {
  1006. return;
  1007. }
  1008. containerListener = AWTEventMulticaster.add(containerListener, l);
  1009. newEventsOnly = true;
  1010. }
  1011. /**
  1012. * Removes the specified container listener so it no longer receives
  1013. * container events from this container.
  1014. * If l is null, no exception is thrown and no action is performed.
  1015. *
  1016. * @param l the container listener
  1017. */
  1018. public synchronized void removeContainerListener(ContainerListener l) {
  1019. if (l == null) {
  1020. return;
  1021. }
  1022. containerListener = AWTEventMulticaster.remove(containerListener, l);
  1023. }
  1024. /**
  1025. * Return an array of all the listeners that were added to the Container
  1026. * with addXXXListener(), where XXX is the name of the <code>listenerType</code>
  1027. * argument. For example, to get all of the ContainerListener(s) for the
  1028. * given Container <code>c</code>, one would write:
  1029. * <pre>
  1030. * ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class))
  1031. * </pre>
  1032. * If no such listener list exists, then an empty array is returned.
  1033. *
  1034. * @param listenerType Type of listeners requested
  1035. * @return all of the listeners of the specified type supported by this container
  1036. * @since 1.3
  1037. */
  1038. public EventListener[] getListeners(Class listenerType) {
  1039. EventListener l = null;
  1040. if (listenerType == ContainerListener.class) {
  1041. l = containerListener;
  1042. } else {
  1043. return super.getListeners(listenerType);
  1044. }
  1045. return AWTEventMulticaster.getListeners(l, listenerType);
  1046. }
  1047. // REMIND: remove when filtering is done at lower level
  1048. boolean eventEnabled(AWTEvent e) {
  1049. int id = e.getID();
  1050. if (id == ContainerEvent.COMPONENT_ADDED ||
  1051. id == ContainerEvent.COMPONENT_REMOVED) {
  1052. if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  1053. containerListener != null) {
  1054. return true;
  1055. }
  1056. return false;
  1057. }
  1058. return super.eventEnabled(e);
  1059. }
  1060. /**
  1061. * Processes events on this container. If the event is a ContainerEvent,
  1062. * it invokes the processContainerEvent method, else it invokes its
  1063. * superclass's processEvent.
  1064. * @param e the event
  1065. */
  1066. protected void processEvent(AWTEvent e) {
  1067. if (e instanceof ContainerEvent) {
  1068. processContainerEvent((ContainerEvent)e);
  1069. return;
  1070. }
  1071. super.processEvent(e);
  1072. }
  1073. /**
  1074. * Processes container events occurring on this container by
  1075. * dispatching them to any registered ContainerListener objects.
  1076. * NOTE: This method will not be called unless container events
  1077. * are enabled for this component; this happens when one of the
  1078. * following occurs:
  1079. * a) A ContainerListener object is registered via addContainerListener()
  1080. * b) Container events are enabled via enableEvents()
  1081. * @see Component#enableEvents
  1082. * @param e the container event
  1083. */
  1084. protected void processContainerEvent(ContainerEvent e) {
  1085. if (containerListener != null) {
  1086. switch(e.getID()) {
  1087. case ContainerEvent.COMPONENT_ADDED:
  1088. containerListener.componentAdded(e);
  1089. break;
  1090. case ContainerEvent.COMPONENT_REMOVED:
  1091. containerListener.componentRemoved(e);
  1092. break;
  1093. }
  1094. }
  1095. }
  1096. /*
  1097. * Dispatches an event to this component or one of its sub components.
  1098. * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
  1099. * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
  1100. * here instead of in processComponentEvent because ComponentEvents
  1101. * may not be enabled for this Container.
  1102. * @param e the event
  1103. */
  1104. void dispatchEventImpl(AWTEvent e) {
  1105. if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
  1106. // event was sent to a lightweight component. The
  1107. // native-produced event sent to the native container
  1108. // must be properly disposed of by the peer, so it
  1109. // gets forwarded. If the native host has been removed
  1110. // as a result of the sending the lightweight event,
  1111. // the peer reference will be null.
  1112. e.consume();
  1113. if (peer != null) {
  1114. peer.handleEvent(e);
  1115. }
  1116. return;
  1117. }
  1118. super.dispatchEventImpl(e);
  1119. switch (e.getID()) {
  1120. case ComponentEvent.COMPONENT_RESIZED:
  1121. createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0);
  1122. break;
  1123. case ComponentEvent.COMPONENT_MOVED:
  1124. createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0);
  1125. break;
  1126. default:
  1127. break;
  1128. }
  1129. }
  1130. /*
  1131. * Dispatches an event to this component, without trying to forward
  1132. * it to any sub components
  1133. * @param e the event
  1134. */
  1135. void dispatchEventToSelf(AWTEvent e) {
  1136. super.dispatchEventImpl(e);
  1137. }
  1138. /**
  1139. * Fetchs the top-most (deepest) lightweight component that is interested
  1140. * in receiving mouse events.
  1141. */
  1142. Component getMouseEventTarget(int x, int y, boolean includeSelf) {
  1143. int ncomponents = this.ncomponents;
  1144. Component component[] = this.component;
  1145. for (int i = 0 ; i < ncomponents ; i++) {
  1146. Component comp = component[i];
  1147. if ((comp != null) && (comp.contains(x - comp.x, y - comp.y)) &&
  1148. (comp.peer instanceof java.awt.peer.LightweightPeer) &&
  1149. (comp.visible == true)) {
  1150. // found a component that intersects the point, see if there is
  1151. // a deeper possibility.
  1152. if (comp instanceof Container) {
  1153. Container child = (Container) comp;
  1154. Component deeper = child.getMouseEventTarget(x - child.x, y - child.y, includeSelf);
  1155. if (deeper != null) {
  1156. return deeper;
  1157. }
  1158. } else {
  1159. if ((comp.mouseListener != null) ||
  1160. ((comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) ||
  1161. (comp.mouseMotionListener != null) ||
  1162. ((comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) {
  1163. // there isn't a deeper target, but this component is a target
  1164. return comp;
  1165. }
  1166. }
  1167. }
  1168. }
  1169. boolean isPeerOK;
  1170. boolean isMouseOverMe;
  1171. boolean isMouseListener;
  1172. boolean isMotionListener;
  1173. isPeerOK = (peer instanceof java.awt.peer.LightweightPeer) || includeSelf;
  1174. isMouseOverMe = contains(x,y);
  1175. isMouseListener = (mouseListener != null) ||
  1176. ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
  1177. isMotionListener = (mouseMotionListener != null) ||
  1178. ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
  1179. // didn't find a child target, return this component if it's a possible target
  1180. if ( isMouseOverMe && isPeerOK && (isMouseListener || isMotionListener) ) {
  1181. return this;
  1182. }
  1183. // no possible target
  1184. return null;
  1185. }
  1186. /**
  1187. * This is called by lightweight components that want the containing
  1188. * windowed parent to enable some kind of events on their behalf.
  1189. * This is needed for events that are normally only dispatched to
  1190. * windows to be accepted so that they can be forwarded downward to
  1191. * the lightweight component that has enabled them.
  1192. */
  1193. void proxyEnableEvents(long events) {
  1194. if (peer instanceof java.awt.peer.LightweightPeer) {
  1195. // this container is lightweight.... continue sending it
  1196. // upward.
  1197. if (parent != null) { parent.proxyEnableEvents(events); }
  1198. } else {
  1199. // This is a native container, so it needs to host
  1200. // one of it's children. If this function is called before
  1201. // a peer has been created we don't yet have a dispatcher
  1202. // because it has not yet been determined if this instance
  1203. // is lightweight.
  1204. if (dispatcher != null) {
  1205. dispatcher.enableEvents(events);
  1206. }
  1207. }
  1208. }
  1209. Window getWindow() {
  1210. Container w = this;
  1211. while( !(w instanceof Window) ) {
  1212. w = w.getParent();
  1213. }
  1214. return (Window)w;
  1215. }
  1216. /**
  1217. * This is called by lightweight components that have requested focus.
  1218. * The focus request is propagated upward until a native container is
  1219. * found, at which point the native container requests focus and records
  1220. * the component the host is requesting focus for.
  1221. */
  1222. void proxyRequestFocus(Component c) {
  1223. if (peer instanceof java.awt.peer.LightweightPeer) {
  1224. // this container is lightweight... continue sending it
  1225. // upward.
  1226. if (parent != null) { parent.proxyRequestFocus(c); }
  1227. } else {
  1228. // This is a windowed container, so record true focus
  1229. // component and request focus from the native window
  1230. // if needed.
  1231. if (dispatcher != null && dispatcher.setFocusRequest(c)) {
  1232. // If the focus is currently somewhere within this Window,
  1233. // call the peer to set focus to this Container. This way,
  1234. // we avoid activating this Window if it's not currently
  1235. // active. -fredx, 2-19-98, bug #4111098
  1236. Component window = this;
  1237. while (!(window instanceof Window) && window != null)
  1238. window = window.getParent();
  1239. if (window != null && ((Window)window).isActive()) {
  1240. peer.requestFocus();
  1241. }
  1242. Toolkit.getEventQueue().changeKeyEventFocus(this);
  1243. }
  1244. }
  1245. }
  1246. /**
  1247. * @deprecated As of JDK version 1.1,
  1248. * replaced by <code>dispatchEvent(AWTEvent e)</code>
  1249. */
  1250. public void deliverEvent(Event e) {
  1251. Component comp = getComponentAt(e.x, e.y);
  1252. if ((comp != null) && (comp != this)) {
  1253. e.translate(-comp.x, -comp.y);
  1254. comp.deliverEvent(e);
  1255. } else {
  1256. postEvent(e);
  1257. }
  1258. }
  1259. /**
  1260. * Locates the component that contains the x,y position. The
  1261. * top-most child component is returned in the case where there
  1262. * is overlap in the components. This is determined by finding
  1263. * the component closest to the index 0 that claims to contain
  1264. * the given point via Component.contains(), except that Components
  1265. * which have native peers take precedence over those which do not
  1266. * (i.e., lightweight Components).
  1267. *
  1268. * @param x the <i>x</i> coordinate
  1269. * @param y the <i>y</i> coordinate
  1270. * @return null if the component does not contain the position.
  1271. * If there is no child component at the requested point and the
  1272. * point is within the bounds of the container the container itself
  1273. * is returned; otherwise the top-most child is returned.
  1274. * @see Component#contains
  1275. * @since JDK1.1
  1276. */
  1277. public Component getComponentAt(int x, int y) {
  1278. return locate(x, y);
  1279. }
  1280. /**
  1281. * @deprecated As of JDK version 1.1,
  1282. * replaced by <code>getComponentAt(int, int)</code>.
  1283. */
  1284. public Component locate(int x, int y) {
  1285. if (!contains(x, y)) {
  1286. return null;
  1287. }
  1288. synchronized (getTreeLock()) {
  1289. // Two passes: see comment in sun.awt.SunGraphicsCallback
  1290. for (int i = 0 ; i < ncomponents ; i++) {
  1291. Component comp = component[i];
  1292. if (comp != null &&
  1293. !(comp.peer instanceof java.awt.peer.LightweightPeer)) {
  1294. if (comp.contains(x - comp.x, y - comp.y)) {
  1295. return comp;
  1296. }
  1297. }
  1298. }
  1299. for (int i = 0 ; i < ncomponents ; i++) {
  1300. Component comp = component[i];
  1301. if (comp != null &&
  1302. comp.peer instanceof java.awt.peer.LightweightPeer) {
  1303. if (comp.contains(x - comp.x, y - comp.y)) {
  1304. return comp;
  1305. }
  1306. }
  1307. }
  1308. }
  1309. return this;
  1310. }
  1311. /**
  1312. * Gets the component that contains the specified point.
  1313. * @param p the point.
  1314. * @return returns the component that contains the point,
  1315. * or <code>null</code> if the component does
  1316. * not contain the point.
  1317. * @see java.awt.Component#contains
  1318. * @since JDK1.1
  1319. */
  1320. public Component getComponentAt(Point p) {
  1321. return getComponentAt(p.x, p.y);
  1322. }
  1323. /**
  1324. * Locates the visible child component that contains the specified
  1325. * position. The top-most child component is returned in the case
  1326. * where there is overlap in the components. If the containing child
  1327. * component is a Container, this method will continue searching for
  1328. * the deepest nested child component. Components which are not
  1329. * visible are ignored during the search.<p>
  1330. *
  1331. * The findComponentAt method is different from getComponentAt in
  1332. * that getComponentAt only searches the Container's immediate
  1333. * children; if the containing component is a Container,
  1334. * findComponentAt will search that child to find a nested component.
  1335. *
  1336. * @param x the <i>x</i> coordinate
  1337. * @param y the <i>y</i> coordinate
  1338. * @return null if the component does not contain the position.
  1339. * If there is no child component at the requested point and the
  1340. * point is within the bounds of the container the container itself
  1341. * is returned.
  1342. * @see Component#contains
  1343. * @see getComponentAt
  1344. * @since 1.2
  1345. */
  1346. public Component findComponentAt(int x, int y) {
  1347. synchronized (getTreeLock()) {
  1348. return findComponentAt(x, y, true, false);
  1349. }
  1350. }
  1351. /**
  1352. * Private version of findComponentAt which has two controllable
  1353. * behaviors. Setting 'ignoreEnabled' to 'false' bypasses disabled
  1354. * Components during the serach. This behavior is used by the
  1355. * lightweight cursor support in sun.awt.GlobalCursorManager.
  1356. * Setting 'ignoreGlassPane' to 'true' bypasses the glass panes owned
  1357. * by any JRootPanes found during the search. This behavior is
  1358. * used by the DnD event targeting code. The cursor and DnD code
  1359. * both call this function directly via native code.
  1360. *
  1361. * The addition of both of these features is temporary, pending the
  1362. * adoption of new, public APIs which export these features (probably
  1363. * in merlin).
  1364. */
  1365. final Component findComponentAt(int x, int y, boolean ignoreEnabled,
  1366. boolean ignoreGlassPane)
  1367. {
  1368. if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
  1369. return null;
  1370. }
  1371. int ncomponents = this.ncomponents;
  1372. Component component[] = this.component;
  1373. Component glassPane = null;
  1374. if (ignoreGlassPane && (this instanceof JRootPane)) {
  1375. glassPane = ((JRootPane)this).getGlassPane();
  1376. }
  1377. // Two passes: see comment in sun.awt.SunGraphicsCallback
  1378. for (int i = 0 ; i < ncomponents ; i++) {
  1379. Component comp = component[i];
  1380. if (comp != null && comp != glassPane &&
  1381. !(comp.peer instanceof java.awt.peer.LightweightPeer)) {
  1382. if (comp instanceof Container) {
  1383. comp = ((Container)comp).findComponentAt(x - comp.x,
  1384. y - comp.y,
  1385. ignoreEnabled,
  1386. ignoreGlassPane);
  1387. } else {
  1388. comp = comp.locate(x - comp.x, y - comp.y);
  1389. }
  1390. if (comp != null && comp.visible &&
  1391. (ignoreEnabled || comp.enabled))
  1392. {
  1393. return comp;
  1394. }
  1395. }
  1396. }
  1397. for (int i = 0 ; i < ncomponents ; i++) {
  1398. Component comp = component[i];
  1399. if (comp != null && comp != glassPane &&
  1400. comp.peer instanceof java.awt.peer.LightweightPeer) {
  1401. if (comp instanceof Container) {
  1402. comp = ((Container)comp).findComponentAt(x - comp.x,
  1403. y - comp.y,
  1404. ignoreEnabled,
  1405. ignoreGlassPane);
  1406. } else {
  1407. comp = comp.locate(x - comp.x, y - comp.y);
  1408. }
  1409. if (comp != null && comp.visible &&
  1410. (ignoreEnabled || comp.enabled))
  1411. {
  1412. return comp;
  1413. }
  1414. }
  1415. }
  1416. return this;
  1417. }
  1418. /**
  1419. * Locates the visible child component that contains the specified
  1420. * point. The top-most child component is returned in the case
  1421. * where there is overlap in the components. If the containing child
  1422. * component is a Container, this method will continue searching for
  1423. * the deepest nested child component. Components which are not
  1424. * visible are ignored during the search.<p>
  1425. *
  1426. * The findComponentAt method is different from getComponentAt in
  1427. * that getComponentAt only searches the Container's immediate
  1428. * children; if the containing component is a Container,
  1429. * findComponentAt will search that child to find a nested component.
  1430. *
  1431. * @param p the point.
  1432. * @return null if the component does not contain the position.
  1433. * If there is no child component at the requested point and the
  1434. * point is within the bounds of the container the container itself
  1435. * is returned.
  1436. * @see Component#contains
  1437. * @see getComponentAt
  1438. * @since 1.2
  1439. */
  1440. public Component findComponentAt(Point p) {
  1441. return findComponentAt(p.x, p.y);
  1442. }
  1443. /**
  1444. * Makes this Container displayable by connecting it to
  1445. * a native screen resource. Making a container displayable will
  1446. * cause any of its children to be made displayable.
  1447. * This method is called internally by the toolkit and should
  1448. * not be called directly by programs.
  1449. * @see Component#isDisplayable
  1450. * @see #removeNotify
  1451. */
  1452. public void addNotify() {
  1453. synchronized (getTreeLock()) {
  1454. // addNotify() on the children may cause proxy event enabling
  1455. // on this instance, so we first call super.addNotify() and
  1456. // possibly create an lightweight event dispatcher before calling
  1457. // addNotify() on the children which may be lightweight.
  1458. super.addNotify();
  1459. if (! (peer instanceof java.awt.peer.LightweightPeer)) {
  1460. dispatcher = new LightweightDispatcher(this);
  1461. }
  1462. int ncomponents = this.ncomponents;
  1463. Component component[] = this.component;
  1464. for (int i = 0 ; i < ncomponents ; i++) {
  1465. component[i].addNotify();
  1466. }
  1467. }
  1468. }
  1469. /**
  1470. * Makes this Container undisplayable by removing its connection
  1471. * to its native screen resource. Make a container undisplayabl