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 }