Source Code Cross Referenced for DisplayCanvas.java in  » Science » jcm1-source » edu » hws » jcm » draw » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » jcm1 source » edu.hws.jcm.draw 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*************************************************************************
002:         *                                                                        *
003:         *   1) This source code file, in unmodified form, and compiled classes   *
004:         *      derived from it can be used and distributed without restriction,  *
005:         *      including for commercial use.  (Attribution is not required       *
006:         *      but is appreciated.)                                              *
007:         *                                                                        *
008:         *    2) Modified versions of this file can be made and distributed       *
009:         *       provided:  the modified versions are put into a Java package     *
010:         *       different from the original package, edu.hws;  modified          *
011:         *       versions are distributed under the same terms as the original;   *
012:         *       and the modifications are documented in comments.  (Modification *
013:         *       here does not include simply making subclasses that belong to    *
014:         *       a package other than edu.hws, which can be done without any      *
015:         *       restriction.)                                                    *
016:         *                                                                        *
017:         *   David J. Eck                                                         *
018:         *   Department of Mathematics and Computer Science                       *
019:         *   Hobart and William Smith Colleges                                    *
020:         *   Geneva, New York 14456,   USA                                        *
021:         *   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
022:         *                                                                        *
023:         *************************************************************************/package edu.hws.jcm.draw;
024:
025:        import edu.hws.jcm.awt.*;
026:        import java.util.StringTokenizer;
027:        import java.util.Vector;
028:        import java.awt.*;
029:        import java.awt.event.*;
030:
031:        /**
032:         * A DisplayCanvas is a drawing area that can contain one or more CoordinateRects.  
033:         * Each CoordinateRect can, in turn, contain Drawable items.  If you only want
034:         * one CoordinateRect that fills the whole canvas, you can for the most part
035:         * ignore the CoordinateRect and work only with the canvas.
036:         * The option of using an offscreen image for double buffering is provided.
037:         * By default, this option is on.  
038:         * <p>If a DisplayCanvas is added to a
039:         * Controller, then it will take care of calling the checkInput()
040:         * and compute() methods of the InputObjects and Computables that
041:         * it contains, so there is no need to add them individually to
042:         * the Controller.  If the DisplayCanvas is added to a JCMPanel, it
043:         * is automatically added to the Controller for that JCMPanel.
044:         * (On the other hand, if a DisplayCanvas is added to a Controller,
045:         * this means that all the
046:         * items in the DisplayCanvas will be recomputed, even if only some
047:         * of them need to be.)
048:         * <p>The canvas can display an error message that goes away
049:         * when the canvas is clicked or when clearErrorMessage()
050:         * is called.  This allows the Canvas to be used as an 
051:         * ErrorReporter for a Controller or LimitControlPanel.
052:         * <p>When any changes are made to the contents of the Canvas,
053:         * doRedraw() must be called for those changes to take effect.  
054:         * Normally, doRedraw() is called by the CoordinateRect or by
055:         * one of the Drawables in a CoordinateRect.  Use doRedraw(CoordinateRect c) 
056:         * or doRedraw(int index) to redraw a single CoordinateRect. Note that
057:         * repainting the canvas is not enough, because this will not automatically
058:         * refresh the off-screen image.
059:         *
060:         */
061:
062:        public class DisplayCanvas extends Canvas implements  ErrorReporter,
063:                InputObject, Computable {
064:
065:            private Vector coordinateRects;
066:            // Contains all the CoordinateRects that have been added to this canvas.
067:            // The elements are members of the private static nested class CRData.
068:
069:            private boolean useOffscreenCanvas = true; // If true, double buffering is used.
070:
071:            private boolean handleMouseZooms = false; // If true, clicking on a CoordinateRect
072:
073:            //   will zoom in on the clicked point, or
074:            //   will zoom out if the shift key is down.
075:
076:            /**
077:             * Create a DisplayCanvas with a white background containing no CoordinateRects.
078:             */
079:            public DisplayCanvas() {
080:                setBackground(Color.white);
081:                enableEvents(AWTEvent.MOUSE_EVENT_MASK
082:                        | AWTEvent.MOUSE_MOTION_EVENT_MASK);
083:            }
084:
085:            /**
086:             * Create a DisplayCanvas with a white background and containing the
087:             * specified CoordinateRect.  The CoordinateRect fills the entire canvas.
088:             *
089:             * @param c The CoordinateRect that will fill the canvas.  If c is null, no CoordinateRect is added to the canvas.
090:             */
091:            public DisplayCanvas(CoordinateRect c) {
092:                this ();
093:                if (c != null)
094:                    addCoordinateRect(c);
095:            }
096:
097:            /**
098:             * Release the memory used the by the off-screen image, if any, that is used for
099:             * double-buffering.  It's a good idea to call this if the DisplayCanvas is in
100:             * an applet and the applet is stopped.
101:             */
102:            public void releaseResources() {
103:                OSC = null;
104:                OSG = null;
105:            }
106:
107:            /**
108:             * Set the "handleMouseZooms" property of this DisplayCanvas.  IF the value is true,
109:             * then clicking on the canvas will zoom in on the point that is clicked and shift-clicking
110:             * will zoom out from that point.  Only the CoordinateRect, if any, that contains the point
111:             * is zoomed.  Furthermore, if the user clicks-and-drags, a rectangle
112:             * is drawn.  When the mouse is released, the interior of the rectangle is zoomed to fill
113:             * the CoordinateRect.  This property is false by default.
114:             */
115:            public void setHandleMouseZooms(boolean handle) {
116:                handleMouseZooms = handle;
117:            }
118:
119:            /**
120:             * Get the "handleMouseZooms" property of this DisplayCanvas, which determines whether the
121:             * canvas reacts to mouse events by zooming the CoordinateRect that is clicked.
122:             */
123:            public boolean getHandleMouseZooms() {
124:                return handleMouseZooms;
125:            }
126:
127:            /**
128:             * Set the "useOffscreenCanvas" property of this DisplayCanvas.  IF the value is true,
129:             * an off-screen image is used for double buffering.  This property is true by default.
130:             */
131:            public boolean getUseOffscreenCanvas() {
132:                return useOffscreenCanvas;
133:            }
134:
135:            /**
136:             * Get the "useOffscreenCanvas" property of this DisplayCanvas, which determines whether
137:             * double-buffering is used.
138:             */
139:            public void setUseOffscreenCanvas(boolean use) {
140:                useOffscreenCanvas = use;
141:                if (!use) {
142:                    OSC = null;
143:                    OSG = null;
144:                }
145:            }
146:
147:            // ----------- For managing CoordinateRects ------------------------
148:
149:            /**
150:             * This private subclass of DisplayCanvas holds the data for one CoordinateRect 
151:             * contained in a DisplayCanvas.
152:             */
153:            private static class CRData implements  java.io.Serializable {
154:                // Data for one coordinate rect
155:                CoordinateRect coords;
156:                double xmin, xmax, ymin, ymax;
157:                // Values between 0 and 1 that
158:                // specify the region of the canvas occupied by this
159:                // CoordinateRect.
160:                Color background; // Color to fill area with before drawing.
161:                // If it's null, no fill is done.  (The display color
162:                // of the Canvas shows through.)
163:            }
164:
165:            /**
166:             * Add the specified Drawable item to the first CoordinateRect in this DisplayCanvas.
167:             * If no CoordinateRect is associated with the canvas, one is created to fill the
168:             * entire canvas.
169:             */
170:            public void add(Drawable d) {
171:                if (coordinateRects == null)
172:                    addCoordinateRect(new CoordinateRect());
173:                CoordinateRect c = ((CRData) coordinateRects.elementAt(0)).coords;
174:                c.add(d);
175:            }
176:
177:            /**
178:             * Add a Drawable item to one of the CoordinateRects associated with the Canvas.
179:             *
180:             * @param d The Drawable item to be added to a CoordinateRect
181:             * @param coordRectIndex The index of the CoordinateRect, where the index of the first
182:             *    CoordinateRect that was added to the cavas is zero, the index of the second is one,
183:             *    and so on.  A CoordinateRect with the specified index must already exist in the
184:             *    canvas, or an IllegalArgumentException is thrown.
185:             */
186:            public void add(Drawable d, int coordRectIndex) {
187:                if (coordinateRects == null || coordRectIndex < 0
188:                        || coordRectIndex >= coordinateRects.size())
189:                    throw new IllegalArgumentException(
190:                            "Internal programming error:  CoordinateRect index ("
191:                                    + coordRectIndex + ")out of range.");
192:                CoordinateRect c = ((CRData) coordinateRects
193:                        .elementAt(coordRectIndex)).coords;
194:                c.add(d);
195:            }
196:
197:            /**
198:             * Add the specified CoordinateRect to this DisplayCanvas, filling the entire canvas,
199:             * and with background color equal to the background color of the canvas.
200:             * 
201:             * @param c the CoordinateRect to be added.  If null, an IllegalArgumentException is thrown.
202:             */
203:            public void addCoordinateRect(CoordinateRect c) {
204:                addCoordinateRect(c, 0, 1, 0, 1, null);
205:            }
206:
207:            /**
208:             * Add a CoordinateRect to the canvas, occupying a specified region of the canvas.
209:             *
210:             * @param coords The CoordinateRect to be added.  If this is null, an IllegalArgumentExceptionis thrown.
211:             * @param hmin Specifies the left edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
212:             *             This must be in the range form 0 to 1, or an IllegalArgumentException is thrown.
213:             * @param hmax Specifies the right edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
214:             *             This must be in the range form 0 to 1 and must be strictly greater than hmin, or an IllegalArgumentException is thrown.
215:             * @param vmin Specifies the top edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
216:             *             This must be in the range form 0 to 1, or an IllegalArgumentException is thrown.
217:             * @param vmax Specifies the bottom edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
218:             *             This must be in the range form 0 to 1 and must be strictly greater than vmin, or an IllegalArgumentException is thrown.
219:             * @param background The background color of the CoordinateRect.  The CoordinateRect is filled with this color
220:             *             before the Drawables that it contains are drawn.  If background is null, no filling takes place
221:             *             and the canvas shows through.
222:             */
223:            public void addCoordinateRect(CoordinateRect coords, double hmin,
224:                    double hmax, double vmin, double vmax, Color background) {
225:                if (hmin < 0 || hmin > 1 || hmax < 0 || hmax > 1
226:                        || hmin >= hmax || vmin < 0 || vmin > 1 || vmax < 0
227:                        || vmax > 1 || vmin >= vmax)
228:                    throw new IllegalArgumentException(
229:                            "Illegal values for area covered by CoordinateRect.");
230:                if (coords == null)
231:                    throw new IllegalArgumentException(
232:                            "Can't add null CoordinateRect to DisplayCanvas.");
233:                CRData c = new CRData();
234:                c.coords = coords;
235:                c.xmin = hmin;
236:                c.xmax = hmax;
237:                c.ymin = vmin;
238:                c.ymax = vmax;
239:                c.background = background;
240:                if (coordinateRects == null)
241:                    coordinateRects = new Vector();
242:                coordinateRects.addElement(c);
243:                coords.setOwner(this );
244:            }
245:
246:            /**
247:             * Add a newly created CoordinateRect covering the specified section of
248:             * the canvas.  hmin, hmax, vmin, vmax must be in the range 0 to 1.
249:             * The index of the new CoordinateRect is returned.
250:             */
251:            public int addNewCoordinateRect(double hmin, double hmax,
252:                    double vmin, double vmax) {
253:                CoordinateRect c = new CoordinateRect();
254:                addCoordinateRect(c, hmin, hmax, vmin, vmax, null);
255:                return coordinateRects.size() - 1;
256:            }
257:
258:            /**
259:             * Add a newly created CoordinateRect covering the specified section of
260:             * the canvas, with the specfied background color.  hmin, hmax, vmin, vmax must be in the range 0 to 1.
261:             * The index of the new CoordinateRect is returned.
262:             */
263:            public int addNewCoordinateRect(double hmin, double hmax,
264:                    double vmin, double vmax, Color background) {
265:                CoordinateRect c = new CoordinateRect();
266:                addCoordinateRect(c, hmin, hmax, vmin, vmax, background);
267:                return coordinateRects.size() - 1;
268:            }
269:
270:            /**
271:             * Get the first CoordinateRect in this canvas.  (If none exists, one is created and
272:             * added to the canvas.)
273:             */
274:            public CoordinateRect getCoordinateRect() {
275:                return getCoordinateRect(0);
276:            }
277:
278:            /**
279:             * Get the i-th CoordinateRect in this DisplayCanvas.  They are numbered staring from zero.
280:             * If there is no i-th rect, null is returned, except that if there
281:             * are NO coordinate rects and a request for rect 0 is received,
282:             * then a new CoordinateRect is added to fill the entire canvas.
283:             */
284:            public CoordinateRect getCoordinateRect(int i) {
285:                if (i == 0
286:                        && (coordinateRects == null || coordinateRects.size() == 0))
287:                    addNewCoordinateRect(0, 1, 0, 1);
288:                if (coordinateRects == null || i < 0
289:                        || i >= coordinateRects.size())
290:                    return null;
291:                else
292:                    return ((CRData) coordinateRects.elementAt(i)).coords;
293:            }
294:
295:            /**  
296:             * Return CoordinateRect that contains the specified pixel, or
297:             * null if there is none.  The CoordinateRects are searched in
298:             * reverse order, so that the "top" CoordinateRect at that point is
299:             * returned.  Note that this method only makes sense if the canvas
300:             * has already been displayed.
301:             * (Mostly, this is for internal use in this class.)
302:             */
303:            public CoordinateRect findCoordinateRectAt(int pixelX, int pixelY) {
304:                if (coordinateRects == null)
305:                    return null;
306:                for (int i = coordinateRects.size() - 1; i >= 0; i--) {
307:                    CRData c = (CRData) coordinateRects.elementAt(i);
308:                    int width = getSize().width;
309:                    if (width <= 0)
310:                        return null;
311:                    int height = getSize().height;
312:                    int x = (int) (c.xmin * width);
313:                    int y = (int) (c.ymin * height);
314:                    int r = (int) (c.xmax * width);
315:                    int b = (int) (c.ymax * height);
316:                    if (pixelX >= x && pixelX < r && pixelY >= y && pixelY < b)
317:                        return c.coords;
318:                }
319:                return null;
320:            }
321:
322:            /**
323:             * Should be called whenever the contents of the canvas have changed and so
324:             * it needs to need to be redrawn.  (This causes the off-screen image to be redrawn.
325:             * A simple call to repaint() does not do this.)
326:             * If only one CoordinateRect needs to be repainted, you can call doRedraw(int i) or
327:             * or doRedraw(CoordinateRect c), which can be more efficient than redrawing the whole canvas.
328:             * If an error message is displayed, it will be cleared.
329:             */
330:            synchronized public void doRedraw() {
331:                // Should be called whenever the coordinate rects need to be repainted.
332:                // If only one needs to be repainted, you can call doRedraw(int i) or
333:                // or doRedraw(CoordinateRect c), which can be more efficient.
334:                // If an error message is displayed, this will not take effect until
335:                // the error message is cleared.
336:                OSCvalid = false;
337:                if (errorMessage != null)
338:                    clearErrorMessage(); // does repaint
339:                else
340:                    repaint();
341:            }
342:
343:            /**
344:             * To be called when the contents of one of the CordinateRects have changed and so
345:             * it needs to need to be redrawn.  (This causes the off-screen image to be redrawn.
346:             * A simple call to repaint() does not do this.)
347:             * If an error message is displayed, it will be cleared.
348:             *
349:             * @param coordRectIndex The index of the CoordinateRect to be redrawn, where the first CoordinateRect is at index zero.
350:             *        If there is no such CoordinateRect, then nothing is done.
351:             */
352:            synchronized public void doRedraw(int coordRectIndex) {
353:                if (coordinateRects != null && coordRectIndex >= 0
354:                        && coordRectIndex < coordinateRects.size()) {
355:                    CRData c = (CRData) coordinateRects
356:                            .elementAt(coordRectIndex);
357:                    OSCvalid = false;
358:                    if (errorMessage != null)
359:                        clearErrorMessage(); // does repaint
360:                    else {
361:                        int width = getSize().width;
362:                        int height = getSize().height;
363:                        int x = (int) (c.xmin * width);
364:                        int y = (int) (c.ymin * height);
365:                        int w = (int) (c.xmax * width) - x;
366:                        int h = (int) (c.ymax * height) - y;
367:                        repaint(x, y, w, h);
368:                    }
369:                }
370:            }
371:
372:            /**
373:             * To be called when the contents of one of the CordinateRects have changed and so
374:             * it needs to need to be redrawn.  (This causes the off-screen image to be redrawn.
375:             * A simple call to repaint() does not do this.)
376:             * If an error message is displayed, it will be cleared.
377:             *
378:             * @param coords The CoordinateRect to be redrawn.  If coords is not in this DisplayCanvas, nothing is done.
379:             */
380:            synchronized public void doRedraw(CoordinateRect coords) {
381:                int size = (coordinateRects == null) ? -1 : coordinateRects
382:                        .size();
383:                for (int i = 0; i < size; i++)
384:                    if (((CRData) coordinateRects.elementAt(i)).coords == coords) {
385:                        doRedraw(i);
386:                        break;
387:                    }
388:            }
389:
390:            //------------------- InputObject/Computable interfaces ---------------------
391:
392:            /**
393:             * This is generally called by a Controller.  It calls the checkInput() method of
394:             * any InputObject displayed on this Canvas.
395:             */
396:            synchronized public void checkInput() {
397:                if (coordinateRects != null) {
398:                    int top = coordinateRects.size();
399:                    for (int i = 0; i < top; i++)
400:                        ((CRData) coordinateRects.elementAt(i)).coords
401:                                .checkInput();
402:                }
403:            }
404:
405:            /**
406:             * This is generally called by a Controller.  It calls the compute() method of
407:             * any InputObject displayed on this Canvas.
408:             */
409:            synchronized public void compute() {
410:                if (coordinateRects != null) {
411:                    int top = coordinateRects.size();
412:                    for (int i = 0; i < top; i++)
413:                        ((CRData) coordinateRects.elementAt(i)).coords
414:                                .compute();
415:                }
416:            }
417:
418:            /**
419:             * Method required by InputObject interface; in this class, calls the same method
420:             * recursively on any CoordinateRects contained in this DisplayCanvas.  This is meant to 
421:             * be called by JCMPanel.gatherInputs().
422:             */
423:            public void notifyControllerOnChange(Controller c) {
424:                if (coordinateRects != null) {
425:                    int top = coordinateRects.size();
426:                    for (int i = 0; i < top; i++)
427:                        ((CRData) coordinateRects.elementAt(i)).coords
428:                                .notifyControllerOnChange(c);
429:                }
430:            }
431:
432:            //-------------------- Error Reporter Stuff ------------------------------------
433:
434:            /** 
435:             * Get color that is used as a background when the canvas displays an error message.
436:             */
437:            public Color getErrorBackground() {
438:                return errorBackground;
439:            }
440:
441:            /** 
442:             * Set color to be used as a background when the canvas displays an error message.
443:             * The default is a light green.  If the specified Color value is null, nothing is done.
444:             */
445:            public void setErrorBackground(Color c) {
446:                if (c != null)
447:                    errorBackground = c;
448:            }
449:
450:            /** 
451:             * Get color that is used for the text when the canvas displays an error message.
452:             */
453:            public Color getErrorForeground() {
454:                return errorForeground;
455:            }
456:
457:            /** 
458:             * Set color to be used for the text when the canvas displays an error message.
459:             * The default is a dark green.  If the specified Color value is null, nothing is done.
460:             */
461:            public void setErrorForeground(Color c) {
462:                if (c != null)
463:                    errorForeground = c;
464:            }
465:
466:            /**
467:             * Get the error message that is currently displayed on the canvas.  If no error
468:             * is displyed, the return value is null.
469:             */
470:            synchronized public String getErrorMessage() {
471:                return errorMessage;
472:            }
473:
474:            /**
475:             * Set an error message to be displayed on the canvas.  This method is generally called by
476:             * a Controller or a LimitControlPanel.  If you call it directly, use null as the first parameter.
477:             * 
478:             * @param c The Controller, if any, that is calling this routine.  This controller will be notified
479:             *             when the error message is cleared.  If the method is not being called by a contrller, this
480:             *             parameter should be set to null.
481:             * @param message The error message to be displayed.  If the value is null or is a blank string, 
482:             *                the current message, if any, is cleared.
483:             */
484:            synchronized public void setErrorMessage(Controller c,
485:                    String message) {
486:                if (message == null || message.trim().length() == 0) {
487:                    if (errorMessage != null) {
488:                        clearErrorMessage();
489:                        if (errorSource != c)
490:                            errorSource.errorCleared();
491:                        repaint();
492:                    }
493:                } else {
494:                    errorMessage = message.trim();
495:                    errorSource = c;
496:                    OSCvalid = false;
497:                    repaint();
498:                }
499:            }
500:
501:            /**
502:             * Clear the error message, if any, that is currently displayed on the canvas.
503:             */
504:            synchronized public void clearErrorMessage() {
505:                if (errorMessage == null)
506:                    return;
507:                errorMessage = null;
508:                if (errorSource != null)
509:                    errorSource.errorCleared();
510:                errorSource = null;
511:                repaint();
512:            }
513:
514:            // ---------------------- ErrorReporter Implementation ----------------------------
515:
516:            private Color errorBackground = new Color(220, 255, 220);
517:            private Color errorForeground = new Color(0, 120, 0);
518:            private String errorMessage;
519:            private Controller errorSource;
520:            private Draggable dragged; // The draggable object, if any, that is being dragged.
521:
522:            /**
523:             * This has been overridden to handle the mouse zoom feature.
524:             * Not meant to be called directly.
525:             */
526:            public void processMouseEvent(MouseEvent evt) {
527:                // If an error message is displayed, get rid of it and
528:                // ignore the mouse click.
529:                if (evt.getID() == MouseEvent.MOUSE_PRESSED) {
530:                    dragging = false; // Shouldn't be possible, but some old, buggy versions of Java made it so.
531:                    dragged = null;
532:                    if (errorMessage != null) {
533:                        if (errorSource != null)
534:                            errorSource.errorCleared();
535:                        errorSource = null;
536:                        errorMessage = null;
537:                        repaint();
538:                        evt.consume();
539:                        return;
540:                    }
541:                    CoordinateRect c = findCoords(evt);
542:                    if (c != null)
543:                        dragged = c.checkDraggables(evt);
544:                    if (dragged != null)
545:                        return;
546:                    if (handleMouseZooms
547:                            && !(evt.getClickCount() > 1 || evt.isAltDown()
548:                                    || evt.isMetaDown() || evt.isControlDown())) {
549:                        super .processMouseEvent(evt);
550:                        if (!evt.isConsumed())
551:                            doMouseZoom_pressed(evt);
552:                        return;
553:                    }
554:                } else if (evt.getID() == MouseEvent.MOUSE_RELEASED
555:                        && handleMouseZooms && dragged != null) {
556:                    dragged.finishDrag(evt);
557:                    dragged = null;
558:                    return;
559:                } else if (evt.getID() == MouseEvent.MOUSE_RELEASED
560:                        && handleMouseZooms && dragging) {
561:                    doMouseZoom_released(evt);
562:                    return;
563:                }
564:                super .processMouseEvent(evt);
565:            }
566:
567:            /**
568:             * This has been overridden to handle the mouse zoom feature.
569:             * Not meant to be called directly.
570:             */
571:            public void processMouseMotionEvent(MouseEvent evt) {
572:                if (dragged != null && evt.getID() == MouseEvent.MOUSE_DRAGGED)
573:                    dragged.continueDrag(evt);
574:                else if (dragging && evt.getID() == MouseEvent.MOUSE_DRAGGED)
575:                    doMouseZoom_moved(evt);
576:                else
577:                    super .processMouseMotionEvent(evt);
578:            }
579:
580:            private void drawErrorMessage(Graphics g) {
581:                if (errorMessage == null)
582:                    return;
583:
584:                Font font = new Font("Helvetica", Font.BOLD, 12);
585:                FontMetrics fm = g.getFontMetrics(font);
586:
587:                int width = getSize().width;
588:                int height = getSize().height;
589:                int lineHeight = fm.getHeight();
590:                int leading = fm.getLeading();
591:                int messageWidth = width - 80;
592:                int left = 30;
593:                int maxLines = (height - 60 - lineHeight) / lineHeight;
594:                if (maxLines <= 0)
595:                    maxLines = 1;
596:
597:                StringTokenizer t = new StringTokenizer(errorMessage, " \t\r\n");
598:                int lineCt = 0;
599:                String[] errorMessageList = new String[maxLines];
600:                String line = "   "; // indent first line
601:                while (t.hasMoreTokens()) {
602:                    String word = t.nextToken();
603:                    if (fm.stringWidth(word) > messageWidth) {
604:                        String w = "";
605:                        int dots = fm.stringWidth("...");
606:                        for (int c = 0; c < word.length(); c++) {
607:                            w += word.charAt(c);
608:                            if (fm.stringWidth(w) + dots > messageWidth)
609:                                break;
610:                        }
611:                        word = w;
612:                    }
613:                    String linePlusWord = line + " " + word;
614:                    if (fm.stringWidth(linePlusWord) > messageWidth) {
615:                        errorMessageList[lineCt] = line;
616:                        lineCt++;
617:                        if (lineCt == maxLines)
618:                            break;
619:                        line = word;
620:                    } else {
621:                        line = linePlusWord;
622:                    }
623:                }
624:                if (lineCt < maxLines) {
625:                    errorMessageList[lineCt] = line;
626:                    lineCt++;
627:                }
628:                if (lineCt == 1)
629:                    errorMessageList[0] += "    "; // for proper centering
630:
631:                int boxWidth = width - 60;
632:                int boxHeight = (lineCt + 1) * lineHeight + 50;
633:                int top = height / 2 - boxHeight / 2;
634:                if (top < 0)
635:                    top = 0;
636:
637:                g.setColor(getBackground());
638:                g.fillRect(0, 0, width, height);
639:                g.setColor(errorBackground);
640:                g.fillRect(left, top, boxWidth, boxHeight);
641:                g.setColor(errorForeground);
642:                g.drawRect(left, top, boxWidth, boxHeight);
643:                g.drawRect(left + 1, top + 1, boxWidth - 2, boxHeight - 2);
644:                g.drawLine(left, top + 23 + lineHeight, left + boxWidth - 2,
645:                        top + 23 + lineHeight);
646:                g.drawLine(left, top + 24 + lineHeight, left + boxWidth - 2,
647:                        top + 24 + lineHeight);
648:                g.setFont(font);
649:                g.drawString("ERROR MESSAGE", width / 2
650:                        - fm.stringWidth("(Error Message)") / 2, top + 10
651:                        + lineHeight);
652:                if (lineCt == 1)
653:                    g.drawString(errorMessageList[0], width / 2
654:                            - fm.stringWidth(errorMessageList[0]) / 2, top + 35
655:                            + 2 * lineHeight);
656:                else {
657:                    for (int i = 0; i < lineCt; i++) {
658:                        g.drawString(errorMessageList[i], left + 10, top + 35
659:                                + (i + 2) * lineHeight - leading);
660:                    }
661:                }
662:            } // end drawErrorMessage();
663:
664:            // ------------ Handle Mouse Zooming -----------------------------------------
665:
666:            private transient boolean dragging, draggingZoomWindow;
667:            private transient CRData draggingInRect;
668:            private transient int dragXmax, dragXmin, dragYmax, dragYmin;
669:            private transient int lastX, lastY, startX, startY;
670:
671:            private CoordinateRect findCoords(MouseEvent evt) {
672:                // Find coord rect containing the mouse.
673:                int xMouse = evt.getX();
674:                int yMouse = evt.getY();
675:                int size = (coordinateRects == null) ? -1 : coordinateRects
676:                        .size();
677:                int width = getSize().width;
678:                int height = getSize().height;
679:                for (int i = size - 1; i >= 0; i--) {
680:                    CRData c = (CRData) coordinateRects.elementAt(i);
681:                    double xmin = (int) (c.xmin * width);
682:                    double ymin = (int) (c.ymin * height);
683:                    double xmax = (int) (c.xmax * width) - 1;
684:                    double ymax = (int) (c.ymax * height) - 1;
685:                    if (xMouse >= xmin && xMouse <= xmax && yMouse >= ymin
686:                            && yMouse <= ymax)
687:                        return c.coords;
688:                }
689:                return null;
690:            }
691:
692:            private synchronized void doMouseZoom_pressed(MouseEvent evt) {
693:                // Called from processMouseEvent, above.
694:                // Ignore multiple clicks and clicks with other than button 1
695:                // and clicks modified with any key except shift.
696:                if (evt.getClickCount() > 1 || evt.isAltDown()
697:                        || evt.isMetaDown() || evt.isControlDown())
698:                    return;
699:                int xMouse = evt.getX();
700:                int yMouse = evt.getY();
701:                int size = (coordinateRects == null) ? -1 : coordinateRects
702:                        .size();
703:                int width = getSize().width;
704:                int height = getSize().height;
705:                for (int i = size - 1; i >= 0; i--) {
706:                    CRData c = (CRData) coordinateRects.elementAt(i);
707:                    dragXmin = (int) (c.xmin * width);
708:                    dragYmin = (int) (c.ymin * height);
709:                    dragXmax = (int) (c.xmax * width) - 1;
710:                    dragYmax = (int) (c.ymax * height) - 1;
711:                    if (xMouse >= dragXmin && xMouse <= dragXmax
712:                            && yMouse >= dragYmin && yMouse <= dragYmax) {
713:                        dragging = true;
714:                        draggingZoomWindow = false;
715:                        draggingInRect = c;
716:                        startX = xMouse;
717:                        startY = yMouse;
718:                        lastX = xMouse;
719:                        lastY = yMouse;
720:                        break;
721:                    }
722:                }
723:            }
724:
725:            private synchronized void doMouseZoom_released(MouseEvent evt) {
726:                Graphics g = getGraphics();
727:                putDragRect(g);
728:                g.dispose();
729:                CoordinateRect c = draggingInRect.coords;
730:                if ((Math.abs(lastX - startX) < 4 && Math.abs(lastY - startY) < 4)
731:                        || Math.abs(startX - lastX) < 2
732:                        || Math.abs(startY - lastY) < 2) {
733:                    if (draggingZoomWindow)
734:                        return;
735:                    if (evt.isShiftDown())
736:                        c.zoomOutFromPixel(startX, startY);
737:                    else
738:                        c.zoomInOnPixel(startX, startY);
739:                } else {
740:                    c.setLimits(c.pixelToX(startX), c.pixelToX(lastX), c
741:                            .pixelToY(startY), c.pixelToY(lastY));
742:                }
743:                dragging = false;
744:            }
745:
746:            private synchronized void doMouseZoom_moved(MouseEvent evt) {
747:                Graphics g = getGraphics();
748:                putDragRect(g);
749:                lastX = evt.getX();
750:                lastY = evt.getY();
751:                putDragRect(g);
752:                g.dispose();
753:            }
754:
755:            private void putDragRect(Graphics g) { // (Assume dragging = true)
756:                if (lastX < dragXmin)
757:                    lastX = dragXmin;
758:                if (lastX > dragXmax)
759:                    lastX = dragXmax;
760:                if (lastY < dragYmin)
761:                    lastY = dragYmin;
762:                if (lastY > dragYmax)
763:                    lastY = dragYmax;
764:                if ((Math.abs(startX - lastX) < 4 && Math.abs(startY - lastY) < 4)
765:                        || Math.abs(startX - lastX) < 2
766:                        || Math.abs(startY - lastY) < 2)
767:                    return;
768:                draggingZoomWindow = true;
769:                Color bc = draggingInRect.background;
770:                if (bc == null)
771:                    bc = getBackground();
772:                g.setXORMode(bc);
773:                if (bc.getRed() <= 100 && bc.getGreen() <= 100
774:                        && bc.getBlue() <= 150)
775:                    g.setColor(Color.white);
776:                else
777:                    g.setColor(Color.black);
778:                int x, y, w, h;
779:                if (startX < lastX) {
780:                    x = startX;
781:                    w = lastX - startX;
782:                } else {
783:                    x = lastX;
784:                    w = startX - lastX;
785:                }
786:                if (startY < lastY) {
787:                    y = startY;
788:                    h = lastY - startY;
789:                } else {
790:                    y = lastY;
791:                    h = startY - lastY;
792:                }
793:                g.drawRect(x, y, w, h);
794:                g.setPaintMode();
795:            }
796:
797:            //--------- More implementation details... ----------------------------------
798:
799:            /**
800:             * This has been overridden to return a default size of 350-by-350 pixels.
801:             * Not usually called directly.
802:             */
803:            public Dimension getPreferredSize() {
804:                return new Dimension(350, 350);
805:            }
806:
807:            private transient Image OSC;
808:            private transient Graphics OSG;
809:            private transient boolean OSCvalid;
810:            private transient int OSCwidth = -1, OSCheight = -1;
811:
812:            private void drawCoordinateRects(Graphics g, int width, int height,
813:                    Rectangle clip) {
814:                g.setColor(getBackground());
815:                g.fillRect(0, 0, width, height);
816:                int count = (coordinateRects == null) ? -1 : coordinateRects
817:                        .size();
818:                try {
819:                    for (int i = 0; i < count; i++) {
820:                        CRData c = (CRData) coordinateRects.elementAt(i);
821:                        Rectangle bounds = new Rectangle();
822:                        bounds.x = (int) (c.xmin * width);
823:                        bounds.y = (int) (c.ymin * height);
824:                        bounds.width = (int) (c.xmax * width) - bounds.x;
825:                        bounds.height = (int) (c.ymax * height) - bounds.y;
826:                        Rectangle clipThisRect = (clip == null) ? bounds
827:                                : bounds.intersection(clip);
828:                        if (clip == null || !clipThisRect.isEmpty()) {
829:                            g.setClip(clipThisRect);
830:                            if (c.background != null) {
831:                                g.setColor(c.background);
832:                                g.fillRect(bounds.x, bounds.y, bounds.width,
833:                                        bounds.height);
834:                            }
835:                            c.coords.draw(g, bounds.x, bounds.y, bounds.width,
836:                                    bounds.height);
837:                        }
838:                    }
839:                } finally {
840:                    g.setClip(clip);
841:                }
842:            }
843:
844:            /**
845:             * This has been overridden to implemnt double-buffering.
846:             * Not meant to be called directly.
847:             */
848:            public void update(Graphics g) {
849:                paint(g);
850:            }
851:
852:            /**
853:             * Draw the contents of the DisplayCanvas.
854:             * Not usually called directly.
855:             */
856:            synchronized public void paint(Graphics g) {
857:                if (errorMessage == null) {
858:                    try {
859:                        checkOSC();
860:                        if (OSC != null)
861:                            g.drawImage(OSC, 0, 0, this );
862:                        else
863:                            drawCoordinateRects(g, getSize().width,
864:                                    getSize().height, g.getClipBounds());
865:                        if (dragging)
866:                            putDragRect(g);
867:                    } catch (RuntimeException e) {
868:                        errorMessage = "Internal Error? (stack trace on System.out):  "
869:                                + e.toString();
870:                        e.printStackTrace();
871:                        g.setClip(0, 0, getSize().width, getSize().height);
872:                    }
873:                }
874:                if (errorMessage != null) {
875:                    drawErrorMessage(g);
876:                    OSCvalid = false;
877:                    return;
878:                }
879:            }
880:
881:            /**
882:             * Draws the specified item in the first CoordinateRect in this canvas.
883:             * It is drawn on screen and on the off-screen canvas, if there is one.
884:             * However, no information is kept about this item, so the drawing will
885:             * disappear the next time the off-screen canvas is re-drawn (if there
886:             * is an off-screen canvas) or the next time the canvas is repainted
887:             * (is there is no off-screen canvas).  If the canvas contains no
888:             * CoordinateRect when this is called, a new one is added.  Note that
889:             * this method should only be called after the canvas has appeared on 
890:             * the screen.
891:             */
892:            public void drawTemp(DrawTemp drawItem) {
893:                if (coordinateRects == null || coordinateRects.size() == 0)
894:                    addCoordinateRect(new CoordinateRect());
895:                drawTemp(drawItem, 0);
896:            }
897:
898:            /**
899:             * Draws the specified item in the specified CoordinateRect in this canvas.
900:             * It is drawn on screen and on the off-screen canvas, if there is one.
901:             * However, no information is kept about this item, so the drawing will
902:             * disappear the next time the off-screen canvas is re-drawn (if there
903:             * is an off-screen canvas) or the next time the canvas is repainted
904:             * (is there is no off-screen canvas).   Note that
905:             * this method should only be called after the canvas has appeared on 
906:             * the screen.
907:             *
908:             * @param drawItem The non-null object that is to be drawn
909:             * @param coordRectIndex The index of the CoordinateRect in which it 
910:             *        is to be drawn, where the index of the fist CoordinateRect
911:             *        added to the canvas is zero, and so on.  If there is
912:             *        no CoordinateRect with the specified index, an IllegalArgumentException
913:             *        is thrown.
914:             */
915:            synchronized public void drawTemp(DrawTemp drawItem,
916:                    int coordRectIndex) {
917:                if (coordRectIndex < 0
918:                        || coordRectIndex >= coordinateRects.size())
919:                    throw new IllegalArgumentException(
920:                            "Invalid CoordinateRect index, " + coordRectIndex);
921:                Graphics g = getGraphics();
922:                if (g == null)
923:                    return;
924:                CRData c = (CRData) coordinateRects.elementAt(coordRectIndex);
925:                Rectangle bounds = new Rectangle();
926:                bounds.x = (int) (c.xmin * getSize().width);
927:                bounds.y = (int) (c.ymin * getSize().height);
928:                bounds.width = (int) (c.xmax * getSize().width) - bounds.x;
929:                bounds.height = (int) (c.ymax * getSize().height) - bounds.y;
930:                g.setClip(bounds);
931:                drawItem.draw(g, c.coords);
932:                g.dispose();
933:                if (useOffscreenCanvas && OSCvalid && OSC != null) {
934:                    g = OSC.getGraphics();
935:                    g.setClip(bounds);
936:                    drawItem.draw(g, c.coords);
937:                    g.dispose();
938:                }
939:            }
940:
941:            synchronized private void checkOSC() { // make off-screen image, if necessary
942:                if (!useOffscreenCanvas
943:                        || (OSCvalid == true && OSC != null
944:                                && OSCwidth == getSize().width && OSCheight == getSize().height))
945:                    return;
946:                int width = getSize().width;
947:                int height = getSize().height;
948:                if (OSC == null || width != OSCwidth || height != OSCheight) {
949:                    OSCvalid = false;
950:                    OSCwidth = width;
951:                    OSCheight = height;
952:                    try {
953:                        OSC = createImage(OSCwidth, OSCheight);
954:                        OSG = OSC.getGraphics();
955:                    } catch (OutOfMemoryError e) {
956:                        OSC = null;
957:                        OSG = null;
958:                    }
959:                }
960:                if (OSC == null || OSCvalid)
961:                    return;
962:                OSCvalid = true;
963:                OSG.setClip(0, 0, width, height);
964:                drawCoordinateRects(OSG, width, height, null);
965:            }
966:
967:        } // end class DisplayCanvas
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.