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