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