001    /*
002     * ImageCanvas
003     * 
004     * Copyright (c) 2000, 2001, 2002, 2003 Marco Schmidt.
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.gui.awt;
009    
010    import java.awt.Canvas;
011    import java.awt.Dimension;
012    import java.awt.Graphics;
013    //import java.awt.Graphics2D;
014    import java.awt.Image;
015    import java.awt.Rectangle;
016    //import java.awt.RenderingHints;
017    import java.awt.ScrollPane;
018    import net.sourceforge.jiu.apps.EditorState;
019    
020    /**
021     * An AWT canvas that displays an {@link java.awt.Image} object.
022     * Capable to display at arbitrary zooming levels.
023     * Does not use rendering hints because they require Java 1.2 or higher
024     * (although bilinear and bicubic interpolation usually improve display quality
025     * when zooming at the cost of slowing down image drawing).
026     *
027     * @author Marco Schmidt
028     */
029    public class ImageCanvas extends Canvas
030    {
031            private Image image;
032            private int width;
033            private int height;
034            private Object interpolation;
035            private int scaledWidth;
036            private int scaledHeight;
037            private double zoomFactorX = 1.0;
038            private double zoomFactorY = 1.0;
039            private boolean zoomToFit;
040            private ScrollPane myScrollPane;
041    
042            public ImageCanvas(ScrollPane scrollPane)
043            {
044                    myScrollPane = scrollPane;
045                    //interpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
046            }
047    
048            public void computeZoomToFitSize()
049            {
050                    if (!zoomToFit || myScrollPane == null)
051                    {
052                            return;
053                    }
054                    Dimension scrollPaneSize = myScrollPane.getSize();
055                    int maxWidth = scrollPaneSize.width;
056                    int maxHeight = scrollPaneSize.height;
057                    double paneRatio = (double)maxWidth / (double)maxHeight;
058                    double imageRatio = (double)width / (double)height;
059                    if (paneRatio < imageRatio)
060                    {
061                            scaledWidth = maxWidth;
062                            scaledHeight = (int)(scaledWidth * imageRatio);
063                    }
064                    else
065                    {
066                            scaledHeight = maxHeight;
067                            scaledWidth = (int)(scaledHeight * imageRatio);
068                    }
069                    scaledHeight--;
070                    scaledWidth--;
071                    zoomFactorX = (double)scaledWidth / (double)width;
072                    zoomFactorY = zoomFactorX;
073            }
074    
075            public int getZoomPercentageX()
076            {
077                    return (int)(zoomFactorX * 100.0);
078            }
079    
080            public int getZoomPercentageY()
081            {
082                    return (int)(zoomFactorY * 100.0);
083            }
084    
085            public Dimension getPreferredSize()
086            {
087                    return new Dimension(scaledWidth, scaledHeight);
088            }
089    
090            /**
091             * Draws image to upper left corner.
092             */
093            public void paint(Graphics g)
094            {
095                    if (image == null)
096                    {
097                            super.paint(g);
098                    }
099                    else
100                    {
101                            Rectangle rect = getBounds();
102                            int canvasWidth = rect.width;
103                            int canvasHeight = rect.height;
104                            int x1 = 0;
105                            int y1 = 0;
106                            if (canvasWidth > scaledWidth)
107                            {
108                                    x1 = (canvasWidth - scaledWidth) / 2;
109                            }
110                            if (canvasHeight > scaledHeight)
111                            {
112                                    y1 = (canvasHeight - scaledHeight) / 2;
113                            }
114                            if (canvasHeight > canvasWidth || canvasHeight > scaledHeight)
115                            {
116                                    super.paint(g);
117                            }
118                            /* commented because Graphics2D requires Java 1.2+
119                            if (g instanceof Graphics2D)
120                            {
121                                    ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation);
122                            }
123                            */
124                            g.drawImage(image, x1, y1, scaledWidth, scaledHeight, this);
125                    }
126            }
127    
128            /**
129             * Specifies a new Image object to be displayed in this canvas.
130             * @param newImage the new Image object, potentially null
131             */
132            public void setImage(Image newImage)
133            {
134                    image = newImage;
135                    width = image.getWidth(this);
136                    height = image.getHeight(this);
137                    scaledWidth = (int)(width * zoomFactorX);
138                    scaledHeight = (int)(height * zoomFactorY);
139                    /*zoomFactorX = 1.0;
140                    zoomFactorY = 1.0;*/
141                    setSize(scaledWidth, scaledHeight);
142                    validate();
143            }
144    
145            /**
146             * Sets both zoom factors to <code>1.0</code>.
147             */
148            public void setOriginalSize()
149            {
150                    setZoomFactor(1.0);
151            }
152    
153            public double getZoomFactorX()
154            {
155                    return zoomFactorX;
156            }
157    
158            public double getZoomFactorY()
159            {
160                    return zoomFactorY;
161            }
162    
163            /**
164             * Sets the interpolation type used for drawing to the argument
165             * (must be one of the
166             * INTERPOLATION_xyz constants of EditorState), but does not
167             * do a redraw.
168             */
169            public void setInterpolation(int newType)
170            {
171                    switch(newType)
172                    {
173                            case(EditorState.INTERPOLATION_BICUBIC):
174                            {
175                                    //interpolation = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
176                                    break;
177                            }
178                            case(EditorState.INTERPOLATION_BILINEAR):
179                            {
180                                    //interpolation = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
181                                    break;
182                            }
183                            case(EditorState.INTERPOLATION_NEAREST_NEIGHBOR):
184                            {
185                                    //interpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
186                                    break;
187                            }
188                    }
189            }
190    
191            public void setZoomFactor(double newZoomFactor)
192            {
193                    setZoomFactors(newZoomFactor, newZoomFactor);
194            }
195    
196            public void setZoomFactors(double newZoomFactorX, double newZoomFactorY)
197            {
198                    if (newZoomFactorX <= 0.0 || newZoomFactorY <= 0.0)
199                    {
200                            throw new IllegalArgumentException("Zoom factors must be larger than 0.0.");
201                    }
202                    zoomFactorX = newZoomFactorX;
203                    zoomFactorY = newZoomFactorY;
204                    scaledWidth = (int)(width * zoomFactorX);
205                    scaledHeight = (int)(height * zoomFactorY);
206                    setSize(scaledWidth, scaledHeight);
207                    myScrollPane.validate();
208            }
209    
210            public void setZoomToFit(boolean newValue)
211            {
212                    zoomToFit = newValue;
213                    validate();
214            }
215    
216            /**
217             * Simply calls {@link #paint(Graphics)} with the argument.
218             * @param g Graphics context
219             */
220            public void update(Graphics g)
221            {
222                    paint(g);
223            }
224    }