001/* Canvas.java -- 002 Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package java.awt; 040 041import java.awt.image.BufferStrategy; 042import java.awt.peer.ComponentPeer; 043import java.io.Serializable; 044 045import javax.accessibility.Accessible; 046import javax.accessibility.AccessibleContext; 047import javax.accessibility.AccessibleRole; 048 049/** 050 * The <code>Canvas</code> component provides a blank rectangular 051 * area, which the client application can use for drawing and for 052 * capturing events. By overriding the <code>paint()</code> method, 053 * the canvas can be used for anything from simple line drawings to 054 * full-scale custom components. 055 * 056 * @author Original author unknown 057 * @author Tom Tromey (tromey@redhat.com) 058 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 059 * @since 1.0 060 */ 061 062public class Canvas 063 extends Component 064 implements Serializable, Accessible 065{ 066 067 /** 068 * Compatible with Sun's JDK. 069 */ 070 private static final long serialVersionUID = -2284879212465893870L; 071 072 /** 073 * The number used to generate the name returned by getName. 074 */ 075 private static transient long next_canvas_number; 076 077 /** 078 * The buffer strategy associated with this canvas. 079 */ 080 transient BufferStrategy bufferStrategy; 081 082 /** 083 * Initializes a new instance of <code>Canvas</code>. 084 */ 085 public Canvas() 086 { 087 } 088 089 /** 090 * Initializes a new instance of <code>Canvas</code> 091 * with the supplied graphics configuration. 092 * 093 * @param graphicsConfiguration the graphics configuration to use 094 * for this particular canvas. 095 */ 096 public Canvas(GraphicsConfiguration graphicsConfiguration) 097 { 098 this.graphicsConfig = graphicsConfiguration; 099 } 100 101 /** 102 * Creates the native peer for this object. 103 */ 104 public void addNotify() 105 { 106 if (peer == null) 107 peer = (ComponentPeer) getToolkit().createCanvas(this); 108 super.addNotify(); 109 } 110 111 /** 112 * Repaints the canvas window. This method should be overridden by 113 * a subclass to do something useful, as this method simply paints 114 * the window with the background color. 115 * 116 * @param gfx the <code>Graphics</code> to use for painting 117 */ 118 public void paint(Graphics gfx) 119 { 120 /* This implementation doesn't make much sense since the filling 121 of background color is guaranteed for heavyweight components 122 such as this. But there's no need to worry, since paint() is 123 usually overridden anyway. */ 124 gfx.setColor(getBackground()); 125 Dimension size = getSize(); 126 gfx.fillRect(0, 0, size.width, size.height); 127 } 128 129 /** 130 * This class provides accessibility support for the canvas. 131 */ 132 protected class AccessibleAWTCanvas 133 extends AccessibleAWTComponent 134 { 135 /** 136 * For compatability with Sun's JDK 137 */ 138 private static final long serialVersionUID = -6325592262103146699L; 139 140 /** 141 * Constructor for the accessible canvas. 142 */ 143 protected AccessibleAWTCanvas() 144 { 145 } 146 147 /** 148 * Returns the accessible role for the canvas. 149 * 150 * @return an instance of <code>AccessibleRole</code>, describing 151 * the role of the canvas. 152 */ 153 public AccessibleRole getAccessibleRole() 154 { 155 return AccessibleRole.CANVAS; 156 } 157 158 } 159 160 /** 161 * Gets the AccessibleContext associated with this <code>Canvas</code>. 162 * The context is created, if necessary. 163 * 164 * @return the associated context 165 */ 166 public AccessibleContext getAccessibleContext() 167 { 168 /* Create the context if this is the first request */ 169 if (accessibleContext == null) 170 accessibleContext = new AccessibleAWTCanvas(); 171 return accessibleContext; 172 } 173 174 /** 175 * A BltBufferStrategy for canvases. 176 */ 177 private class CanvasBltBufferStrategy extends BltBufferStrategy 178 { 179 /** 180 * Creates a block transfer strategy for this canvas. 181 * 182 * @param numBuffers the number of buffers in this strategy 183 * @param accelerated true if the buffer should be accelerated, 184 * false otherwise 185 */ 186 CanvasBltBufferStrategy(int numBuffers, boolean accelerated) 187 { 188 super(numBuffers, 189 new BufferCapabilities(new ImageCapabilities(accelerated), 190 new ImageCapabilities(accelerated), 191 BufferCapabilities.FlipContents.COPIED)); 192 } 193 } 194 195 /** 196 * A FlipBufferStrategy for canvases. 197 */ 198 private class CanvasFlipBufferStrategy extends FlipBufferStrategy 199 { 200 /** 201 * Creates a flip buffer strategy for this canvas. 202 * 203 * @param numBuffers the number of buffers in this strategy 204 * 205 * @throws AWTException if the requested number of buffers is not 206 * supported 207 */ 208 CanvasFlipBufferStrategy(int numBuffers) 209 throws AWTException 210 { 211 super(numBuffers, 212 new BufferCapabilities(new ImageCapabilities(true), 213 new ImageCapabilities(true), 214 BufferCapabilities.FlipContents.COPIED)); 215 } 216 } 217 218 /** 219 * Creates a buffering strategy that manages how this canvas is 220 * repainted. This method attempts to create the optimum strategy 221 * based on the desired number of buffers. Hardware or software 222 * acceleration may be used. 223 * 224 * createBufferStrategy attempts different levels of optimization, 225 * but guarantees that some strategy with the requested number of 226 * buffers will be created even if it is not optimal. First it 227 * attempts to create a page flipping strategy, then an accelerated 228 * blitting strategy, then an unaccelerated blitting strategy. 229 * 230 * Calling this method causes any existing buffer strategy to be 231 * destroyed. 232 * 233 * @param numBuffers the number of buffers in this strategy 234 * 235 * @throws IllegalArgumentException if requested number of buffers 236 * is less than one 237 * @throws IllegalStateException if this canvas is not displayable 238 * 239 * @since 1.4 240 */ 241 public void createBufferStrategy(int numBuffers) 242 { 243 if (numBuffers < 1) 244 throw new IllegalArgumentException("Canvas.createBufferStrategy: number" 245 + " of buffers is less than one"); 246 247 if (!isDisplayable()) 248 throw new IllegalStateException("Canvas.createBufferStrategy: canvas is" 249 + " not displayable"); 250 251 BufferStrategy newStrategy = null; 252 253 // try a flipping strategy 254 try 255 { 256 newStrategy = new CanvasFlipBufferStrategy(numBuffers); 257 } 258 catch (AWTException e) 259 { 260 } 261 262 // fall back to an accelerated blitting strategy 263 if (newStrategy == null) 264 newStrategy = new CanvasBltBufferStrategy(numBuffers, true); 265 266 bufferStrategy = newStrategy; 267 } 268 269 /** 270 * Creates a buffering strategy that manages how this canvas is 271 * repainted. This method attempts to create a strategy based on 272 * the specified capabilities and throws an exception if the 273 * requested strategy is not supported. 274 * 275 * Calling this method causes any existing buffer strategy to be 276 * destroyed. 277 * 278 * @param numBuffers the number of buffers in this strategy 279 * @param caps the requested buffering capabilities 280 * 281 * @throws AWTException if the requested capabilities are not 282 * supported 283 * @throws IllegalArgumentException if requested number of buffers 284 * is less than one or if caps is null 285 * 286 * @since 1.4 287 */ 288 public void createBufferStrategy(int numBuffers, BufferCapabilities caps) 289 throws AWTException 290 { 291 if (numBuffers < 1) 292 throw new IllegalArgumentException("Canvas.createBufferStrategy: number" 293 + " of buffers is less than one"); 294 295 if (caps == null) 296 throw new IllegalArgumentException("Canvas.createBufferStrategy:" 297 + " capabilities object is null"); 298 299 // a flipping strategy was requested 300 if (caps.isPageFlipping()) 301 bufferStrategy = new CanvasFlipBufferStrategy(numBuffers); 302 else 303 bufferStrategy = new CanvasBltBufferStrategy(numBuffers, true); 304 } 305 306 /** 307 * Returns the buffer strategy used by the canvas. 308 * 309 * @return the buffer strategy. 310 * @since 1.4 311 */ 312 public BufferStrategy getBufferStrategy() 313 { 314 return bufferStrategy; 315 } 316 317 /** 318 * Updates the canvas in response to a request to 319 * <code>repaint()</code> it. The canvas is cleared 320 * with the current background colour, before <code>paint()</code> 321 * is called to add the new contents. Subclasses 322 * which override this method should either call this 323 * method via <code>super.update(graphics)</code> or re-implement 324 * this behaviour, so as to ensure that the canvas is 325 * clear before painting takes place. 326 * 327 * @param graphics the graphics context. 328 */ 329 public void update(Graphics graphics) 330 { 331 Dimension size; 332 333 /* Clear the canvas */ 334 size = getSize(); 335 graphics.clearRect(0, 0, size.width, size.height); 336 /* Call the paint method */ 337 paint(graphics); 338 } 339 340 /** 341 * Generate a unique name for this <code>Canvas</code>. 342 * 343 * @return A unique name for this <code>Canvas</code>. 344 */ 345 String generateName() 346 { 347 return "canvas" + getUniqueLong(); 348 } 349 350 private static synchronized long getUniqueLong() 351 { 352 return next_canvas_number++; 353 } 354}