1. /*
  2. * @(#)SystemEventQueueUtilities.java 1.37 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.awt.image.*;
  11. import java.util.*;
  12. import java.lang.reflect.InvocationTargetException;
  13. import sun.awt.AppContext;
  14. /**
  15. * Swing internal utilities for dealing with the AWT system event
  16. * queue. Four methods are exported, see the individual method javadoc
  17. * for more information: addRunnableCanvas(), removeRunnableCanvas(),
  18. * postRunnable(), queueComponentWorkRequest().
  19. *
  20. * Note: most of the code in this class is no longer needed since
  21. * we're no longer supporting Swing in 1.1.x VM's and in 1.2 we're
  22. * guaranteed access to the AWT event queue. However all of the entry
  23. * points, save postRunnable(), are still used.
  24. *
  25. * @see RepaintManager
  26. * @see JRootPane
  27. */
  28. class SystemEventQueueUtilities
  29. {
  30. private static final Object classLock = new Object();
  31. private static final Object rootTableKey = new Object() {
  32. public String toString() {
  33. return "SystemEventQueueUtilties.rootTableKey";
  34. }
  35. };
  36. private static Map getRootTable() {
  37. Map rt = (Map)AppContext.getAppContext().get(rootTableKey);
  38. if (rt == null) {
  39. synchronized (rootTableKey) {
  40. rt = (Map)AppContext.getAppContext().get(rootTableKey);
  41. if (rt == null) {
  42. rt = new WeakHashMap(4);
  43. AppContext.getAppContext().put(rootTableKey, rt);
  44. }
  45. }
  46. }
  47. return rt;
  48. }
  49. /**
  50. * SystemEventQueue class. This private class just exists to
  51. * encapsulate the details of getting at the System Event queue
  52. * in the Java 2 platform. The rest of the SystemEventQueueUtilities
  53. * class just uses SystemEventQueue.get() to access the event queue.
  54. */
  55. private static class SystemEventQueue
  56. {
  57. // If the AWT system event queue is accessible then return it.
  58. // otherwise return null.
  59. static EventQueue get() {
  60. EventQueue retValue;
  61. try {
  62. retValue = Toolkit.getDefaultToolkit().getSystemEventQueue();
  63. }
  64. catch (SecurityException se) {
  65. // Should never happen.
  66. retValue = null;
  67. }
  68. return retValue;
  69. }
  70. // If the AWT system event queue is accessible then return it.
  71. // otherwise return null.
  72. static EventQueue get(JRootPane rootPane) {
  73. return get();
  74. }
  75. }
  76. /**
  77. * A Runnable with a component. If we need to post this
  78. * runnable to the AWT system event queue, we'll find it's
  79. * JRootPane ancestor and use that as the key to the table
  80. * of RunnableCanvas's.
  81. *
  82. * @see RunnableCanvas
  83. */
  84. private static class ComponentWorkRequest implements Runnable
  85. {
  86. boolean isPending;
  87. Component component;
  88. ComponentWorkRequest(Component c) {
  89. /* As of 1.2, the component field is no longer used. It was
  90. * used by the RunnableCanvas class to find the JRootPane
  91. * associated with a ComponentWorkRequest for JDK1.1.x.
  92. */
  93. // component = c;
  94. }
  95. public void run() {
  96. RepaintManager rm;
  97. synchronized (this) {
  98. rm = RepaintManager.currentManager(component /*null*/);
  99. isPending = false;
  100. }
  101. rm.validateInvalidComponents();
  102. rm.paintDirtyRegions();
  103. }
  104. }
  105. /**
  106. * This method is used by RepaintManager to queue a ComponentWorkRequest
  107. * with invokeLater(). It assumes that the root argument is either
  108. * and Applet or a Window, the root passed in obtained in a
  109. * slightly different manner than see SwingUtilities.getRoot(). If this
  110. * called with the root obtained in a different way than RepaintManager
  111. * currently uses, be sure to also tweak removeRunnableCanvas.
  112. */
  113. static void queueComponentWorkRequest(Component root)
  114. {
  115. ComponentWorkRequest req = (ComponentWorkRequest)(getRootTable().get(root));
  116. boolean newWorkRequest = (req == null);
  117. if (newWorkRequest) {
  118. req = new ComponentWorkRequest(root);
  119. }
  120. /* At this point the ComponentWorkRequest may be accessible from
  121. * an event dispatching thread so before updating it further
  122. * we synchronize access to it.
  123. */
  124. synchronized(req) {
  125. if (newWorkRequest) {
  126. getRootTable().put(root, req);
  127. }
  128. if (!req.isPending) {
  129. SwingUtilities.invokeLater(req);
  130. req.isPending = true;
  131. }
  132. }
  133. }
  134. /**
  135. * Associate a RunnableCanvas and a JRootPane to enable queuing
  136. * events for the root pane's parent window's event dispatching thread.
  137. * Adds a 1x1 RunnableCanvas to the root pane's layered pane.
  138. * <p>
  139. * Called by JRootPane.addNotify() to set up the RunnableCanvas.
  140. *
  141. * @see RunnableCanvas
  142. * @see JRootPane#addNotify
  143. */
  144. static void addRunnableCanvas(JRootPane rootPane)
  145. {
  146. synchronized (classLock) {
  147. /* If we have access to the system event queue, we don't bother
  148. * with a RunnableCanvas
  149. */
  150. if (SystemEventQueue.get(rootPane) != null) {
  151. return;
  152. }
  153. JLayeredPane layeredPane = rootPane.getLayeredPane();
  154. if (layeredPane != null) {
  155. RunnableCanvas rc = new RunnableCanvas(rootPane);
  156. layeredPane.add(rc);
  157. }
  158. }
  159. }
  160. /**
  161. * Remove the RunnableCanvas from the JRootPane and clear the
  162. * internal bookeeping associated with it.
  163. * <p>
  164. * Called by JRootPane.removeNotify()
  165. *
  166. * @see RunnableCanvas
  167. */
  168. static void removeRunnableCanvas(JRootPane rootPane) {
  169. synchronized (classLock) {
  170. // We don't use SwingUtilities.getRoot, as it has different
  171. // behavior then the RepaintManager call to add the initial root.
  172. Component root = null;
  173. for (Component c = rootPane; c != null; c = c.getParent()) {
  174. if ((c instanceof Window) ||
  175. (c instanceof java.applet.Applet)) {
  176. root = c;
  177. break;
  178. }
  179. }
  180. if (root != null) {
  181. getRootTable().remove(root);
  182. }
  183. RunnableCanvas.remove(rootPane);
  184. }
  185. }
  186. /**
  187. * Post an event to the AWT System event queue that, when dispatched,
  188. * will invoke the specified Runnable. If lock is non-null this call
  189. * blocks (by waiting on the lock) until the doRun() method returns,
  190. * otherwise we return as soon as the event has been enqueued. An
  191. * exception is only returned if lock is non-null, i.e. if we're
  192. * being called from invokeAndWait().
  193. * <p>
  194. * This method is only intended to support SwingUtilities.invokeLater()
  195. * and SwingUtilities.invokeAndWait().
  196. */
  197. static Exception postRunnable(Runnable doRun, Object lock)
  198. {
  199. EventQueue systemEventQueue = SystemEventQueue.get();
  200. RunnableEvent event = new RunnableEvent(doRun, lock);
  201. if (systemEventQueue != null) {
  202. systemEventQueue.postEvent(event);
  203. }
  204. else {
  205. postRunnableCanvasEvent(event);
  206. }
  207. return event.exception;
  208. }
  209. /**
  210. * Adds a RunnableEvent to all the remaining RunnableCanvases to restart
  211. * the TimerQueues thread.
  212. *
  213. * @see RunnableCanvas#postRunnableEventToAll
  214. */
  215. static void restartTimerQueueThread() {
  216. synchronized (classLock) {
  217. if (SystemEventQueue.get() == null) {
  218. Runnable restarter = new TimerQueueRestart();
  219. RunnableEvent event = new RunnableEvent(restarter, null);
  220. RunnableCanvas.postRunnableEventToAll(event);
  221. }
  222. }
  223. }
  224. /**
  225. * Runnable that will message the shared instance of the Timer Queue
  226. * to restart.
  227. *
  228. * @see #restartTimerQueueThread
  229. */
  230. private static class TimerQueueRestart implements Runnable {
  231. boolean attemptedStart;
  232. public synchronized void run() {
  233. // Only try and restart the q once.
  234. if(!attemptedStart) {
  235. TimerQueue q = TimerQueue.sharedInstance();
  236. synchronized(q) {
  237. if(!q.running)
  238. q.start();
  239. }
  240. attemptedStart = true;
  241. }
  242. }
  243. }
  244. /**
  245. * Event type used for dispatching runnable objects for
  246. * SwingUtilities.invokeLater() and SwingUtilities.invokeAndWait().
  247. *
  248. * @see #postRunnable
  249. */
  250. private static class RunnableEvent extends AWTEvent {
  251. static final int EVENT_ID = AWTEvent.RESERVED_ID_MAX + 1000;
  252. static final Component target = new RunnableTarget();
  253. final Runnable doRun;
  254. final Object lock;
  255. Exception exception;
  256. RunnableEvent(Runnable doRun, Object lock) {
  257. super(target, EVENT_ID);
  258. this.doRun = doRun;
  259. this.lock = lock;
  260. }
  261. }
  262. /**
  263. * Calls RunnableEvent.doRun.run(). If RunnableEvent.lock is non
  264. * null then we synchronize the run() call and save the exception
  265. * (if any) in the RunnableEvent.exception field.
  266. */
  267. private static void processRunnableEvent(RunnableEvent runnableEvent)
  268. {
  269. Object lock = runnableEvent.lock;
  270. if (lock == null) {
  271. runnableEvent.doRun.run();
  272. }
  273. else {
  274. synchronized(lock) {
  275. try {
  276. runnableEvent.doRun.run();
  277. }
  278. catch (Exception e) {
  279. runnableEvent.exception = e;
  280. }
  281. finally {
  282. if (runnableEvent.lock != null) {
  283. runnableEvent.lock.notify();
  284. }
  285. }
  286. }
  287. }
  288. }
  289. /**
  290. * A dummy Component subclass that (only) handles RunnableEvents. If the
  291. * AWT System event queue is accessible (i.e. we're running as
  292. * an application or as trusted code), RunnableEvents are dispatched
  293. * to this component.
  294. *
  295. * @see #processRunnableEvent
  296. */
  297. private static class RunnableTarget extends Component
  298. {
  299. RunnableTarget() {
  300. super();
  301. enableEvents(RunnableEvent.EVENT_ID);
  302. }
  303. protected void processEvent(AWTEvent event) {
  304. if (event instanceof RunnableEvent) {
  305. processRunnableEvent((RunnableEvent)event);
  306. }
  307. }
  308. }
  309. /**
  310. * Synchronized entry point to the applet support for AWT System
  311. * event queue access. This method adds the event to the appropriate
  312. * runnable canvas's queue and then has the canvas repaint(). Note
  313. * that by the time the event dispatching thread gets to handling
  314. * the repaint() (by calling runnableCanvas.update()), many runnable
  315. * events may have been queued up.
  316. *
  317. * @see RunnableCanvas#addRunnableEvent
  318. * @see RunnableCanvas#update
  319. */
  320. private static void postRunnableCanvasEvent(RunnableEvent e) {
  321. synchronized (classLock) {
  322. RunnableCanvas runnableCanvas = RunnableCanvas.lookup(e);
  323. if (runnableCanvas == null) {
  324. /* If this is a ComponentWorkRequest and we were unable to
  325. * queue it, then clear the pending flag.
  326. */
  327. if (e.doRun instanceof ComponentWorkRequest) {
  328. ComponentWorkRequest req = (ComponentWorkRequest)e.doRun;
  329. synchronized(req) {
  330. req.isPending = false;
  331. }
  332. }
  333. /* If this is a Timer event let it know that it didn't fire.
  334. */
  335. if(e.doRun instanceof Timer.DoPostEvent) {
  336. ((Timer.DoPostEvent)e.doRun).getTimer().cancelEvent();
  337. }
  338. /* We are unable to queue this event on a system event queue. Make
  339. * sure that any code that's waiting for the runnable to finish
  340. * doesn't hang.
  341. */
  342. if (e.lock != null) {
  343. e.lock.notify();
  344. }
  345. return;
  346. }
  347. runnableCanvas.addRunnableEvent(e);
  348. runnableCanvas.repaint();
  349. }
  350. }
  351. /**
  352. * Return the current threads ThreadGroup, even on IE4.0.
  353. * IE4.0 throws a SecurityException if you apply getThreadGroup()
  354. * to the event dispatching thread. However a child of the
  355. * event dispatching thread (same thread group) is OK.
  356. */
  357. private static ThreadGroup getThreadGroupSafely() {
  358. return new Thread().getThreadGroup();
  359. }
  360. /**
  361. * Applets don't have direct access to the AWT SystemEvent queue. To
  362. * work around this we call RunnableCanvas.repaint() on a per applet
  363. * instance of this class. The AWT deals with this by queuing a
  364. * java.awt.PaintEvent for the event dispatching thread which
  365. * is dispatched (Component.dispatchEvent()) the usual way.
  366. * Component.dispatchEvent() handles PaintEvents by calling our update()
  367. * method (on the event dispatching thread) which processes
  368. * the RunnableEvents stashed in the runnableEvents vector.
  369. */
  370. private static class RunnableCanvas extends Canvas
  371. {
  372. private static final Graphics nullGraphics = new RunnableCanvasGraphics();
  373. private static Hashtable runnableCanvasTable = new Hashtable(1);
  374. private Vector runnableEvents = new Vector(2);
  375. private boolean isRegistered = false;
  376. RunnableCanvas(JRootPane rootPane) {
  377. super();
  378. setBounds(0, 0, 1, 1);
  379. /* Remember the mapping from the current thread (and the current
  380. * thread group) to this RunnableCanvas. Note that if a mapping
  381. * has already been defined, e.g. this rootPane belongs to an
  382. * existing applet, then leave the table alone. We're assuming that
  383. * an applets addNotify method will always run before the addNotify
  384. * method in any subsidiary windows the applet creates can run.
  385. */
  386. if (runnableCanvasTable.get(Thread.currentThread()) == null) {
  387. try {
  388. runnableCanvasTable.put(Thread.currentThread(), this);
  389. runnableCanvasTable.put(getThreadGroupSafely(), this);
  390. if (SwingUtilities.isEventDispatchThread()) {
  391. isRegistered = true;
  392. }
  393. }
  394. catch(Exception e) {
  395. System.err.println("Can't register RunnableCanvas");
  396. e.printStackTrace();
  397. }
  398. }
  399. runnableCanvasTable.put(rootPane, this);
  400. maybeRegisterEventDispatchThread();
  401. }
  402. /**
  403. * If called on an event dispatching thread that we haven't seen
  404. * before then make two hashtable entries in the runnableCanvasTable:
  405. * <pre>
  406. * current thread => this RunnableCanvas
  407. * current thread group => this RunnableCanvas
  408. * </pre>
  409. * @see #lookup
  410. */
  411. private void maybeRegisterEventDispatchThread() {
  412. /* Avoid the cost of a synchronized block (or method) in the
  413. * common case, since this method is called each time paint is called.
  414. */
  415. if (!isRegistered) {
  416. synchronized(this) {
  417. if (!isRegistered && SwingUtilities.isEventDispatchThread()) {
  418. Thread currentThread = Thread.currentThread();
  419. /* If this event dispatching thread is already mapped to
  420. * a runnableCanvas then don't replace the mapping (which
  421. * we expect to be generated by the applet).
  422. */
  423. if (runnableCanvasTable.get(currentThread) != null) {
  424. isRegistered = true;
  425. }
  426. else {
  427. runnableCanvasTable.put(currentThread, this);
  428. runnableCanvasTable.put(getThreadGroupSafely(), this);
  429. isRegistered = true;
  430. }
  431. }
  432. }
  433. }
  434. }
  435. /**
  436. * If we're running on the event dispatching thread then lookup
  437. * the canvas with the current thread itself, otherwise use the
  438. * current threads thread group. If there is no match for the
  439. * ThreadGroup, the first visible RunnableCanvas is returned.
  440. */
  441. static RunnableCanvas lookup(RunnableEvent e)
  442. {
  443. /* If this is a ComponentWorkRequest, find the components
  444. * JRootPane ancestor and use that as the index into the
  445. * runnableCanvasTable. This case occurs when any thread,
  446. * other than the event dispatching thead, calls repaint
  447. */
  448. if (e.doRun instanceof ComponentWorkRequest) {
  449. ComponentWorkRequest req = (ComponentWorkRequest)e.doRun;
  450. synchronized(req) {
  451. JRootPane rootPane = SwingUtilities.getRootPane(req.component);
  452. if(rootPane != null) {
  453. return (RunnableCanvas)(runnableCanvasTable.get(rootPane));
  454. }
  455. /* Failure. There doesn't appear to be a RunnableCanvas to use
  456. * so indicate that a new request will need to be queued, see
  457. * RepaintManager.queueWorkRequest().
  458. */
  459. req.isPending = false;
  460. return null;
  461. }
  462. }
  463. /* If the current thread is in the runnableCanvasTable
  464. * (e.g. we're on the event dispatching thread) we're done.
  465. */
  466. Object rv = runnableCanvasTable.get(Thread.currentThread());
  467. if (rv != null) {
  468. return (RunnableCanvas)rv;
  469. }
  470. /* At this point we're assuming that the calling thread isn't
  471. * a system thread (like an image observer thread), so it's safe
  472. * to lookup via the current threads ThreadGroup.
  473. */
  474. Object threadGroup;
  475. try {
  476. threadGroup = Thread.currentThread().getThreadGroup();
  477. }
  478. catch (SecurityException exc) {
  479. return null;
  480. }
  481. RunnableCanvas rc = (RunnableCanvas)runnableCanvasTable.get(threadGroup);
  482. /* There's no RunnableCanvas associated with this thread group
  483. * (so punt). Return the first visible RunnableCanvas.
  484. */
  485. if(rc == null) {
  486. Enumeration keys = runnableCanvasTable.keys();
  487. if(keys == null) {
  488. return null;
  489. }
  490. while(keys.hasMoreElements()) {
  491. Object key = keys.nextElement();
  492. if ((key instanceof JRootPane) && ((JRootPane)key).isShowing()) {
  493. return (RunnableCanvas)runnableCanvasTable.get(key);
  494. }
  495. }
  496. }
  497. return rc;
  498. }
  499. /**
  500. * Adds the event to all the RunnableCanvases.
  501. *
  502. * @see #restartTimerQueueThread
  503. */
  504. static void postRunnableEventToAll(RunnableEvent e) {
  505. // Determine the RunnableCanvas for the current thread. It
  506. // may be null.
  507. RunnableCanvas currentThreadCanvas;
  508. ThreadGroup tg;
  509. try {
  510. tg = new Thread().getThreadGroup();
  511. }
  512. catch (SecurityException se) {
  513. tg = null;
  514. }
  515. if(tg != null) {
  516. currentThreadCanvas = (RunnableCanvas)runnableCanvasTable.
  517. get(tg);
  518. }
  519. else
  520. currentThreadCanvas = null;
  521. // Add the event to all canvases, except the current one.
  522. // Presumably the current one is no longer valid and will be
  523. // going away shortly.
  524. Enumeration keys = runnableCanvasTable.keys();
  525. while(keys.hasMoreElements()) {
  526. Object key = keys.nextElement();
  527. if(key instanceof JRootPane) {
  528. Object canvas = runnableCanvasTable.get(key);
  529. if(canvas != currentThreadCanvas) {
  530. RunnableCanvas rc = (RunnableCanvas)canvas;
  531. rc.addRunnableEvent(e);
  532. rc.repaint();
  533. }
  534. }
  535. }
  536. }
  537. /**
  538. * Remove the RunnableCanvas associated with this applet from the
  539. * applets Layered pane and clear all of the runnableCanvasTable
  540. * entries that point at it.
  541. */
  542. static void remove(JRootPane rootPane) {
  543. RunnableCanvas rc = (RunnableCanvas)(runnableCanvasTable.get(rootPane));
  544. if (rc != null) {
  545. RunnableCanvas nextCanvas = null;
  546. JLayeredPane layeredPane = rootPane.getLayeredPane();
  547. layeredPane.remove((Component)rc);
  548. Enumeration keys = runnableCanvasTable.keys();
  549. while(keys.hasMoreElements()) {
  550. Object key = keys.nextElement();
  551. Object next = runnableCanvasTable.get(key);
  552. if (rc == next) {
  553. runnableCanvasTable.remove(key);
  554. }
  555. else if(nextCanvas == null) {
  556. nextCanvas = (RunnableCanvas)next;
  557. }
  558. }
  559. // If there are still events, either move them to another
  560. // canvas, or mark the Timer type events as not having
  561. // fired.
  562. RunnableEvent[] events = rc.getRunnableCanvasEvents();
  563. int numEvents = (events == null) ? 0 : events.length;
  564. if(numEvents > 0) {
  565. if(nextCanvas != null) {
  566. for(int counter = 0; counter < numEvents; counter++) {
  567. RunnableEvent e = events[counter];
  568. if(e.doRun instanceof Timer.DoPostEvent)
  569. nextCanvas.addRunnableEvent(e);
  570. }
  571. nextCanvas.repaint();
  572. }
  573. else {
  574. // Mark all Timer type event as not having fired.
  575. for(int counter = 0; counter < numEvents; counter++) {
  576. RunnableEvent event = events[counter];
  577. if(event.doRun instanceof Timer.DoPostEvent) {
  578. ((Timer.DoPostEvent)event.doRun).getTimer().
  579. cancelEvent();
  580. }
  581. }
  582. }
  583. }
  584. }
  585. }
  586. /**
  587. * If there are events to be processed then we're showing. Note
  588. * that the AWT code that dispatches paint events short circuits
  589. * (does nothing) if isShowing() returns false.
  590. */
  591. public boolean isShowing() {
  592. return runnableEvents.size() > 0;
  593. }
  594. /**
  595. * Reduce the cost of repainting (since we're not going to draw
  596. * anything) by returning a constant no-op graphics object.
  597. */
  598. public Graphics getGraphics() {
  599. return nullGraphics;
  600. }
  601. /**
  602. * Testing purposes only. This method shouldn't be called;
  603. * the parent of this component should have a null layout
  604. * manager.
  605. */
  606. public Dimension getPreferredSize() {
  607. return new Dimension(1, 1);
  608. }
  609. /**
  610. * Add a RunnableEvent to the queue that will be dispatched
  611. * when this component is repainted.
  612. * @see #update
  613. */
  614. synchronized void addRunnableEvent(RunnableEvent e) {
  615. runnableEvents.addElement(e);
  616. }
  617. /**
  618. * Return an (array) copy of the runnableEvents vector or
  619. * null if the vector is empty. The update method processes
  620. * a copy of the vector so that we don't have to hold
  621. * the synchronized lock while calling processRunnableEvent().
  622. * @see #update
  623. */
  624. private synchronized RunnableEvent[] getRunnableCanvasEvents() {
  625. int n = runnableEvents.size();
  626. if (n == 0) {
  627. return null;
  628. }
  629. else {
  630. RunnableEvent[] rv = new RunnableEvent[n];
  631. for(int i = 0; i < n; i++) {
  632. rv[i] = (RunnableEvent)(runnableEvents.elementAt(i));
  633. }
  634. runnableEvents.removeAllElements();
  635. return rv;
  636. }
  637. }
  638. public void paint(Graphics g) {
  639. maybeRegisterEventDispatchThread();
  640. }
  641. /**
  642. * Process all of the RunnableEvents that have accumulated
  643. * since RunnableCanvas.repaint() was called.
  644. */
  645. public void update(Graphics g) {
  646. RunnableEvent[] events = getRunnableCanvasEvents();
  647. if (events != null) {
  648. for(int i = 0; i < events.length; i++) {
  649. processRunnableEvent(events[i]);
  650. }
  651. }
  652. }
  653. }
  654. /**
  655. * A no-op Graphics object for the RunnableCanvas component.
  656. * Most AWT Component implementations handle update events
  657. * like this:
  658. * <pre>
  659. * Graphics g = getGraphics();
  660. * Rectangle r = ((PaintEvent)e).getUpdateRect();
  661. * g.clipRect(r.x, r.y, r.width, r.height);
  662. * update(g)
  663. * g.dispose();
  664. * </pre>
  665. * Since the RunnableCanvas component isn't really going to do
  666. * any painting we don't bother with creating/disposing real
  667. * graphics objects, or setting any of the properties.
  668. *
  669. */
  670. private static class RunnableCanvasGraphics extends Graphics
  671. {
  672. public Graphics create() {
  673. return this;
  674. }
  675. /* We don't expect any of the following methods to be called but
  676. * we still return marginally valid values for the get methods
  677. * just in case.
  678. */
  679. public Rectangle getClipBounds() {
  680. return new Rectangle(0, 0, Short.MAX_VALUE, Short.MAX_VALUE);
  681. }
  682. public Shape getClip() {
  683. return (Shape)(getClipBounds());
  684. }
  685. public void dispose() {}
  686. public void translate(int x, int y) {}
  687. public Color getColor() { return Color.black; }
  688. public void setColor(Color c) {}
  689. public void setPaintMode() {}
  690. public void setXORMode(Color c) {}
  691. public Font getFont() { return null; }
  692. public void setFont(Font font) {}
  693. public FontMetrics getFontMetrics(Font f) { return null; }
  694. public void clipRect(int x, int y, int width, int height) {}
  695. public void setClip(int x, int y, int width, int height) {}
  696. public void setClip(Shape clip) {}
  697. public void copyArea(int x, int y, int w, int h, int dx, int dy) {}
  698. public void drawLine(int x1, int y1, int x2, int y2) {}
  699. public void fillRect(int x, int y, int width, int height) {}
  700. public void clearRect(int x, int y, int width, int height) {}
  701. public void drawRoundRect(int x, int y, int w, int h, int aw, int ah) {}
  702. public void fillRoundRect(int x, int y, int w, int h, int aw, int ah) {}
  703. public void drawOval(int x, int y, int w, int h) {}
  704. public void fillOval(int x, int y, int w, int h) {}
  705. public void drawArc(int x, int y, int w, int h, int sa, int aa) {}
  706. public void fillArc(int x, int y, int w, int h, int sa, int aa) {}
  707. public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {}
  708. public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {}
  709. public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {}
  710. public void drawString(String str, int x, int y) {}
  711. public void drawString(java.text.AttributedCharacterIterator iterator, int x, int y) {}
  712. public boolean drawImage(Image i, int x, int y, ImageObserver o) { return false; }
  713. public boolean drawImage(Image i, int x, int y, int w, int h, ImageObserver o) { return false; }
  714. public boolean drawImage(Image i, int x, int y, Color bgcolor, ImageObserver o) { return false; }
  715. public boolean drawImage(Image i, int x, int y, int w, int h, Color c, ImageObserver o) { return false; }
  716. public boolean drawImage(Image i,
  717. int dx1, int dy1, int dx2, int dy2,
  718. int sx1, int sy1, int sx2, int sy2, ImageObserver o)
  719. { return false; }
  720. public boolean drawImage(Image i,
  721. int dx1, int dy1, int dx2, int dy2,
  722. int sx1, int sy1, int sx2, int sy2, Color c, ImageObserver o)
  723. { return false; }
  724. }
  725. }