~ubuntu-branches/ubuntu/trusty/libjgraph-java/trusty

« back to all changes in this revision

Viewing changes to src/org/jgraph/JGraph.java

  • Committer: Bazaar Package Importer
  • Author(s): gregor herrmann
  • Date: 2008-03-17 20:28:08 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080317202808-jol9tcnnn9lu0gc3
Tags: 5.12.0.4.dfsg-1
* New upstream release.
* Remove debian/dirs and create /usr/share/java directly from
  debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * @(#)JGraph.java
 
2
 * $Id: JGraph.java,v 1.78 2008/03/07 18:41:11 david Exp $
3
3
 *
4
 
 * Copyright (c) 2001-2006 Gaudenz Alder
 
4
 * Copyright (c) 2001-2008 Gaudenz Alder
5
5
 *
6
6
 */
7
7
package org.jgraph;
41
41
import javax.swing.Scrollable;
42
42
import javax.swing.SwingConstants;
43
43
 
 
44
import org.jgraph.event.GraphModelEvent;
44
45
import org.jgraph.event.GraphSelectionEvent;
45
46
import org.jgraph.event.GraphSelectionListener;
 
47
import org.jgraph.event.GraphLayoutCacheEvent.GraphLayoutCacheChange;
 
48
import org.jgraph.event.GraphModelEvent.GraphModelChange;
46
49
import org.jgraph.graph.AbstractCellView;
47
50
import org.jgraph.graph.AttributeMap;
48
51
import org.jgraph.graph.BasicMarqueeHandler;
183
186
                // org.jgraph.plaf.basic.TransferHandler.JAdapterComponent
184
187
                implements Scrollable, Accessible, Serializable {
185
188
 
186
 
        public static final String VERSION = "JGraph (v5.10.1.5)";
 
189
        public static final String VERSION = "JGraph (v5.12.0.4)";
187
190
 
188
191
        public static final int DOT_GRID_MODE = 0;
189
192
 
242
245
        /** Off screen image for double buffering */
243
246
        protected transient Image offscreen;
244
247
 
245
 
        /** Whether or not the current background image is correct */
246
 
        protected transient boolean offscreenValid = false;
247
 
 
248
248
        /** The bounds of the offscreen buffer */
249
249
        protected transient Rectangle2D offscreenBounds;
250
250
        
253
253
 
254
254
        /** Graphics object of off screen image */
255
255
        protected transient Graphics offgraphics;
 
256
        
 
257
        /** Whether or not the current background image is correct */
 
258
        protected transient Rectangle2D offscreenDirty = null;
256
259
 
257
260
        /**
258
261
         * The buffer around the offscreen graphics object that provides the
266
269
         * buffering. Volatile 
267
270
         */
268
271
        protected boolean volatileOffscreen = false;
 
272
        
 
273
        /** Stores whether the last double buffer allocation worked or not */
 
274
        protected boolean lastBufferAllocated = true;
269
275
 
270
276
        /** Holds the background image. */
271
277
        protected ImageIcon backgroundImage;
315
321
        /** True if the ports are scaled. Bound property. */
316
322
        protected boolean portsScaled = true;
317
323
 
 
324
        /** True if port are painted above all other cells. */
 
325
        protected boolean portsOnTop = true;
 
326
        
318
327
        /** True if the graph allows to move cells below zero. */
319
328
        protected boolean moveBelowZero = false;
320
329
        
1741
1750
                        scale = newValue;
1742
1751
                        boolean zoomIn = true;
1743
1752
                        Rectangle newView = null;
 
1753
                        clearOffscreen();
1744
1754
                        if (view != null) {
1745
1755
                                double scaleRatio = newValue / oldValue;
1746
1756
                                int newCenterX = (int) (center.getX() * scaleRatio);
1757
1767
                                        zoomIn = false;
1758
1768
                                }
1759
1769
                        }
1760
 
                        offscreenValid = false;
1761
1770
                        firePropertyChange(SCALE_PROPERTY, oldValue, newValue);
1762
1771
                        // When zooming in, do it after the revalidation otherwise
1763
1772
                        // it intermittently moves to the old co-ordinate system
1768
1777
        }
1769
1778
 
1770
1779
        /**
 
1780
         * Invalidate the offscreen region, do not just delete it, since if the new
 
1781
         * region is smaller than the old you may not wish to re-create the buffer
 
1782
         */
 
1783
        public void clearOffscreen() {
 
1784
 
 
1785
                if (offscreen != null) {
 
1786
                        int h = offscreen.getHeight(this);
 
1787
                        int w = offscreen.getWidth(this);
 
1788
                        Rectangle2D dirtyRegion = new Rectangle2D.Double(0, 0, w, h);
 
1789
                        fromScreen(dirtyRegion);
 
1790
                        addOffscreenDirty(dirtyRegion);
 
1791
                }
 
1792
        }
 
1793
 
 
1794
        /**
1771
1795
         * Returns the center of the component relative to the parent viewport's
1772
1796
         * position.
1773
1797
         */
1901
1925
                firePropertyChange(PORTS_SCALED_PROPERTY, oldValue, flag);
1902
1926
        }
1903
1927
 
 
1928
        public boolean isPortsOnTop() {
 
1929
                return portsOnTop;
 
1930
        }
 
1931
 
 
1932
        public void setPortsOnTop(boolean portsOnTop) {
 
1933
                this.portsOnTop = portsOnTop;
 
1934
        }
 
1935
 
1904
1936
        /**
1905
1937
         * Returns true if the graph will be anti aliased.
1906
1938
         * 
2075
2107
                        }
2076
2108
                        offscreen = null;
2077
2109
                        offgraphics = null;
 
2110
                        Runtime runtime = Runtime.getRuntime();
 
2111
                        long maxMemory = runtime.maxMemory();
 
2112
                        long allocatedMemory = runtime.totalMemory();
 
2113
                        long freeMemory = runtime.freeMemory();
 
2114
                        long totalFreeMemory = (freeMemory + (maxMemory - allocatedMemory)) / 1024;
 
2115
                        // Calculate size of buffer required (assuming TYPE_INT_RGB which
 
2116
                        // stores each pixel in a 32-bit int )
 
2117
                        long memoryRequired = width*height*4/1024;
 
2118
                        if (memoryRequired > totalFreeMemory) {
 
2119
                                if (lastBufferAllocated) {
 
2120
                                        // If the last attempt to allocate a buffer worked it might
 
2121
                                        // be we need to reclaim the memory before the next one
 
2122
                                        // will work
 
2123
                                        System.gc();
 
2124
                                }
 
2125
                                lastBufferAllocated = false;
 
2126
                                return null;
 
2127
                        }
2078
2128
                        if (offscreen == null && volatileOffscreen) {
2079
2129
                                try {
2080
2130
                                        offscreen = createVolatileImage(width, height);
2093
2143
                                // of it, might also be faster to calculate in
2094
2144
                                // advance whether they is enough memory to create image
2095
2145
                                // rather than let it try and throw error.
 
2146
                                lastBufferAllocated = false;
2096
2147
                                return null;
2097
2148
                        }
 
2149
                        lastBufferAllocated = true;
2098
2150
                        setupOffScreen(x, y, width, height, newOffscreenBuffer);
2099
2151
                } else if (offscreen instanceof VolatileImage) {
2100
2152
                        int valCode = ((VolatileImage) offscreen)
2118
2170
                                }
2119
2171
                                setupOffScreen(x, y, width, height, newOffscreenBuffer);
2120
2172
                        } else if (valCode == VolatileImage.IMAGE_RESTORED) {
2121
 
                                setOffscreenValid(false);
 
2173
                                addOffscreenDirty((Rectangle2D)getBounds().clone());
2122
2174
                        }
2123
2175
                }
2124
 
                if (!isOffscreenValid()) {
 
2176
                Rectangle2D offscreenDirty = getOffscreenDirty();
 
2177
                if (offscreenDirty != null) {
2125
2178
                        offgraphics.setColor(getBackground());
2126
2179
                        offgraphics.setPaintMode();
2127
 
                        offgraphics.fillRect(0, 0, (int) graphBounds.getWidth(), (int) graphBounds
2128
 
                                        .getHeight());
2129
 
                        ((BasicGraphUI)getUI()).drawGraph(offgraphics, null);
2130
 
                        offscreenValid = true;
 
2180
                        toScreen(offscreenDirty);
 
2181
                        offscreenDirty.setRect(offscreenDirty.getX()
 
2182
                                        - (getHandleSize() + 1), offscreenDirty.getY()
 
2183
                                        - (getHandleSize() + 1), offscreenDirty.getWidth()
 
2184
                                        + (getHandleSize() + 1) * 2, offscreenDirty.getHeight()
 
2185
                                        + (getHandleSize() + 1) * 2);
 
2186
                        offgraphics.fillRect((int) offscreenDirty.getX(),
 
2187
                                        (int) offscreenDirty.getY(), (int) offscreenDirty
 
2188
                                                        .getWidth(), (int) offscreenDirty.getHeight());
 
2189
                        ((BasicGraphUI) getUI()).drawGraph(offgraphics, offscreenDirty);
 
2190
                        clearOffscreenDirty();
2131
2191
                }
2132
2192
                return offgraphics;
2133
2193
        }
2168
2228
         */
2169
2229
        protected void setupOffScreen(int x, int y, int width, int height, Rectangle2D newOffscreenBuffer) {
2170
2230
                offgraphics = offscreen.getGraphics();
2171
 
                setOffscreenValid(false);
2172
2231
                offgraphics.setColor(getBackground());
2173
2232
                offgraphics.setPaintMode();
2174
2233
                offgraphics.fillRect(0, 0, width, height);
 
2234
                ((BasicGraphUI)getUI()).drawGraph(offgraphics, null);
2175
2235
                offscreenBounds = newOffscreenBuffer;
2176
2236
                offscreenOffset = new Point2D.Double(x, y);
 
2237
                // Clear the offscreen, we've just drawn the whole thing
 
2238
                clearOffscreenDirty();
2177
2239
        }
2178
2240
 
2179
2241
        /**
2183
2245
                return offscreen;
2184
2246
        }
2185
2247
 
 
2248
        public Rectangle2D getOffscreenDirty() {
 
2249
                return offscreenDirty;
 
2250
        }
 
2251
 
 
2252
        public void addOffscreenDirty(Rectangle2D offscreenDirty) {
 
2253
                if (this.offscreenDirty == null && offscreenDirty != null){
 
2254
                        this.offscreenDirty = (Rectangle2D)offscreenDirty.clone();
 
2255
                } else if (offscreenDirty != null){
 
2256
                        this.offscreenDirty.add(offscreenDirty);
 
2257
                }
 
2258
                
 
2259
        }
 
2260
 
 
2261
        public void clearOffscreenDirty() {
 
2262
                offscreenDirty = null;
 
2263
        }
 
2264
        
2186
2265
        /**
2187
2266
         * Utility method to draw the off screen buffer
2188
2267
         * 
2226
2305
                return getGraphics().drawImage(offscreen, rect.x, rect.y,
2227
2306
                                rect.x + rect.width, rect.y + rect.height, rect.x, rect.y,
2228
2307
                                rect.x + rect.width, rect.y + rect.height, this);
 
2308
 
2229
2309
        }
2230
2310
 
2231
2311
        /**
2247
2327
        public void setBackgroundImage(ImageIcon backgroundImage) {
2248
2328
                ImageIcon oldValue = this.backgroundImage;
2249
2329
                this.backgroundImage = backgroundImage;
 
2330
                clearOffscreen();
2250
2331
                firePropertyChange(PROPERTY_BACKGROUNDIMAGE, oldValue, backgroundImage);
2251
2332
        }
2252
2333
 
2253
2334
        /**
 
2335
         * Override parent to clear offscreen double buffer
 
2336
         */
 
2337
        public void setBackground(Color bg) {
 
2338
                clearOffscreen();
 
2339
                super.setBackground(bg);
 
2340
        }
 
2341
 
 
2342
        /**
2254
2343
         * @return the backgroundScaled
2255
2344
         */
2256
2345
        public boolean isBackgroundScaled() {
2258
2347
        }
2259
2348
 
2260
2349
        /**
2261
 
         * @return the offscreenValid
2262
 
         */
2263
 
        public boolean isOffscreenValid() {
2264
 
                return offscreenValid;
2265
 
        }
2266
 
 
2267
 
        /**
2268
 
         * @param offscreenValid
2269
 
         *            the offscreenValid to set
2270
 
         */
2271
 
        public void setOffscreenValid(boolean offscreenValid) {
2272
 
                this.offscreenValid = offscreenValid;
2273
 
        }
2274
 
 
2275
 
        /**
2276
2350
         * @return the offscreenOffset
2277
2351
         */
2278
2352
        public Point2D getOffscreenOffset() {
2320
2394
         *            the backgroundComponent to set
2321
2395
         */
2322
2396
        public void setBackgroundComponent(Component backgroundComponent) {
 
2397
                clearOffscreen();
2323
2398
                this.backgroundComponent = backgroundComponent;
2324
2399
        }
2325
2400
 
 
2401
        /*
 
2402
         * Overriden to change painting style for opaque components
 
2403
         * @see javax.swing.JComponent#setOpaque(boolean)
 
2404
         */
 
2405
        public void setOpaque(boolean opaque) {
 
2406
                super.setOpaque(opaque);
 
2407
        }
 
2408
 
2326
2409
        /**
2327
2410
         * Returns the <code>GraphModel</code> that is providing the data.
2328
2411
         * 
2345
2428
        public void setModel(GraphModel newModel) {
2346
2429
                GraphModel oldModel = graphModel;
2347
2430
                graphModel = newModel;
 
2431
                clearOffscreen();
2348
2432
                firePropertyChange(GRAPH_MODEL_PROPERTY, oldModel, graphModel);
2349
2433
                // FIX: Use Listener
2350
2434
                if (graphLayoutCache != null
2379
2463
        public void setGraphLayoutCache(GraphLayoutCache newLayoutCache) {
2380
2464
                GraphLayoutCache oldLayoutCache = graphLayoutCache;
2381
2465
                graphLayoutCache = newLayoutCache;
 
2466
                clearOffscreen();
2382
2467
                firePropertyChange(GRAPH_LAYOUT_CACHE_PROPERTY, oldLayoutCache,
2383
2468
                                graphLayoutCache);
2384
2469
                if (graphLayoutCache != null
2852
2937
                repaint();
2853
2938
        }
2854
2939
 
2855
 
        /**
2856
 
         * You should not call this method directly on a JGraph if you are using
2857
 
         * double buffering.
2858
 
         * 
2859
 
         * @see javax.swing.JComponent#repaint(long, int, int, int, int)
2860
 
         */
2861
 
        public void repaint(long tm, int x, int y, int width, int height) {
2862
 
                super.repaint(tm, x, y, width, height);
2863
 
        }
2864
 
 
2865
 
        /*
2866
 
         * (non-Javadoc)
2867
 
         * 
2868
 
         * @see javax.swing.JComponent#repaint(java.awt.Rectangle)
2869
 
         */
2870
 
        public void repaint(Rectangle r) {
2871
 
                offscreenValid = false;
2872
 
                super.repaint(r);
2873
 
        }
2874
 
 
2875
 
        /*
2876
 
         * (non-Javadoc)
2877
 
         * 
2878
 
         * @see java.awt.Component#repaint()
2879
 
         */
2880
 
        public void repaint() {
2881
 
                offscreenValid = false;
2882
 
                super.repaint();
2883
 
        }
2884
 
 
2885
 
        /*
2886
 
         * (non-Javadoc)
2887
 
         * 
2888
 
         * @see java.awt.Component#repaint(int, int, int, int)
2889
 
         */
2890
 
        public void repaint(int x, int y, int width, int height) {
2891
 
                offscreenValid = false;
2892
 
                super.repaint(x, y, width, height);
2893
 
        }
2894
 
 
2895
 
        /*
2896
 
         * (non-Javadoc)
2897
 
         * 
2898
 
         * @see java.awt.Component#repaint(long)
2899
 
         */
2900
 
        public void repaint(long tm) {
2901
 
                offscreenValid = false;
2902
 
                super.repaint(tm);
2903
 
        }
2904
 
 
2905
2940
        // /* (non-Javadoc)
2906
2941
        // * @see javax.swing.JComponent#isOptimizedDrawingEnabled()
2907
2942
        // */
2961
2996
        }
2962
2997
 
2963
2998
        /**
 
2999
         * Calculates the clip 
 
3000
         * @param change
 
3001
         * @return the total region dirty as a result of this change
 
3002
         */
 
3003
        public Rectangle2D getClipRectangle(GraphLayoutCacheChange change) {
 
3004
                List removed = DefaultGraphModel.getDescendants(getModel(), change.getRemoved());
 
3005
                Rectangle2D removedBounds = (removed != null && !removed.isEmpty()) ? getCellBounds(removed.toArray()) : null;
 
3006
                List inserted = DefaultGraphModel.getDescendants(getModel(), change.getInserted());
 
3007
                Rectangle2D insertedBounds = (inserted != null && !inserted.isEmpty()) ? getCellBounds(inserted.toArray()) : null;
 
3008
                List changed = DefaultGraphModel.getDescendants(getModel(), change.getChanged());
 
3009
                Rectangle2D changedBounds = (changed != null && !changed.isEmpty()) ? getCellBounds(changed.toArray()) : null;
 
3010
                List context = DefaultGraphModel.getDescendants(getModel(), change.getContext());
 
3011
                Rectangle2D contextBounds = (context != null && !context.isEmpty()) ? getCellBounds(context.toArray()) : null;
 
3012
 
 
3013
                Rectangle2D clip = removedBounds;
 
3014
 
 
3015
                if (clip == null) {
 
3016
                        clip = insertedBounds;
 
3017
                } else if (insertedBounds != null) {
 
3018
                        clip.add(insertedBounds);
 
3019
                }
 
3020
 
 
3021
                if (clip == null) {
 
3022
                        clip = changedBounds;
 
3023
                } else if (changedBounds != null) {
 
3024
                        clip.add(changedBounds);
 
3025
                }
 
3026
 
 
3027
                if (clip == null) {
 
3028
                        clip = contextBounds;
 
3029
                } else if (contextBounds != null) {
 
3030
                        clip.add(contextBounds);
 
3031
                }
 
3032
 
 
3033
                return clip;
 
3034
        }
 
3035
 
 
3036
        /**
2964
3037
         * Serialization support.
2965
3038
         */
2966
3039
        private void writeObject(ObjectOutputStream s) throws IOException {