001    /* Canvas.java --
002       Copyright (C) 1999, 2000, 2002, 2004  Free Software Foundation
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.awt;
040    
041    import java.awt.image.BufferStrategy;
042    import java.awt.peer.ComponentPeer;
043    import java.io.Serializable;
044    
045    import javax.accessibility.Accessible;
046    import javax.accessibility.AccessibleContext;
047    import 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    
062    public 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    }