Home » openjdk-7 » sun » swing » [javadoc | source]

    1   /*
    2    * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package sun.swing;
   26   
   27   import java.awt;
   28   import java.awt.image;
   29   import java.util;
   30   
   31   /**
   32    * A base class used for icons or images that are expensive to paint.
   33    * A subclass will do the following:
   34    * <ol>
   35    * <li>Invoke <code>paint</code> when you want to paint the image,
   36    *     if you are implementing <code>Icon</code> you'll invoke this from
   37    *     <code>paintIcon</code>.
   38    *     The args argument is useful when additional state is needed.
   39    * <li>Override <code>paintToImage</code> to render the image.  The code that
   40    *     lives here is equivalent to what previously would go in
   41    *     <code>paintIcon</code>, for an <code>Icon</code>.
   42    * </ol>
   43    * The two ways to use this class are:
   44    * <ol>
   45    * <li>Invoke <code>paint</code> to draw the cached reprensentation at
   46    *     the specified location.
   47    * <li>Invoke <code>getImage</code> to get the cached reprensentation and
   48    *     draw the image yourself.  This is primarly useful when you are not
   49    *     using <code>VolatileImage</code>.
   50    * </ol>
   51    *
   52    *
   53    */
   54   public abstract class CachedPainter {
   55       // CacheMap maps from class to ImageCache.
   56       private static final Map<Object,ImageCache> cacheMap =
   57                      new HashMap<Object,ImageCache>();
   58   
   59   
   60       private static ImageCache getCache(Object key) {
   61           synchronized(CachedPainter.class) {
   62               ImageCache cache = cacheMap.get(key);
   63               if (cache == null) {
   64                   cache = new ImageCache(1);
   65                   cacheMap.put(key, cache);
   66               }
   67               return cache;
   68           }
   69       }
   70   
   71       /**
   72        * Creates an instance of <code>CachedPainter</code> that will cache up
   73        * to <code>cacheCount</code> images of this class.
   74        *
   75        * @param cacheCount Max number of images to cache
   76        */
   77       public CachedPainter(int cacheCount) {
   78           getCache(getClass()).setMaxCount(cacheCount);
   79       }
   80   
   81       /**
   82        * Renders the cached image to the the passed in <code>Graphic</code>.
   83        * If there is no cached image <code>paintToImage</code> will be invoked.
   84        * <code>paintImage</code> is invoked to paint the cached image.
   85        *
   86        * @param c Component rendering to, this may be null.
   87        * @param g Graphics to paint to
   88        * @param x X-coordinate to render to
   89        * @param y Y-coordinate to render to
   90        * @param w Width to render in
   91        * @param h Height to render in
   92        * @param arg Variable arguments that will be passed to paintToImage
   93        */
   94       public void paint(Component c, Graphics g, int x,
   95                            int y, int w, int h, Object... args) {
   96           if (w <= 0 || h <= 0) {
   97               return;
   98           }
   99           if (c != null) {
  100               synchronized(c.getTreeLock()) {
  101                   synchronized(CachedPainter.class) {
  102                       // If c is non-null, synchronize on the tree lock.
  103                       // This is necessary because asking for the
  104                       // GraphicsConfiguration will grab a tree lock.
  105                       paint0(c, g, x, y, w, h, args);
  106                   }
  107               }
  108           }
  109           else {
  110               synchronized(CachedPainter.class) {
  111                   paint0(c, g, x, y, w, h, args);
  112               }
  113           }
  114       }
  115   
  116       private void paint0(Component c, Graphics g, int x,
  117                            int y, int w, int h, Object... args) {
  118           Object key = getClass();
  119           GraphicsConfiguration config = getGraphicsConfiguration(c);
  120           ImageCache cache = getCache(key);
  121           Image image = cache.getImage(key, config, w, h, args);
  122           int attempts = 0;
  123           do {
  124               boolean draw = false;
  125               if (image instanceof VolatileImage) {
  126                   // See if we need to recreate the image
  127                   switch (((VolatileImage)image).validate(config)) {
  128                   case VolatileImage.IMAGE_INCOMPATIBLE:
  129                       ((VolatileImage)image).flush();
  130                       image = null;
  131                       break;
  132                   case VolatileImage.IMAGE_RESTORED:
  133                       draw = true;
  134                       break;
  135                   }
  136               }
  137               if (image == null) {
  138                   // Recreate the image
  139                   image = createImage(c, w, h, config, args);
  140                   cache.setImage(key, config, w, h, args, image);
  141                   draw = true;
  142               }
  143               if (draw) {
  144                   // Render to the Image
  145                   Graphics g2 = image.getGraphics();
  146                   paintToImage(c, image, g2, w, h, args);
  147                   g2.dispose();
  148               }
  149   
  150               // Render to the passed in Graphics
  151               paintImage(c, g, x, y, w, h, image, args);
  152   
  153               // If we did this 3 times and the contents are still lost
  154               // assume we're painting to a VolatileImage that is bogus and
  155               // give up.  Presumably we'll be called again to paint.
  156           } while ((image instanceof VolatileImage) &&
  157                    ((VolatileImage)image).contentsLost() && ++attempts < 3);
  158       }
  159   
  160       /**
  161        * Paints the representation to cache to the supplied Graphics.
  162        *
  163        * @param c Component painting to, may be null.
  164        * @param image Image to paint to
  165        * @param g Graphics to paint to, obtained from the passed in Image.
  166        * @param w Width to paint to
  167        * @param h Height to paint to
  168        * @param args Arguments supplied to <code>paint</code>
  169        */
  170       protected abstract void paintToImage(Component c, Image image, Graphics g,
  171                                            int w, int h, Object[] args);
  172   
  173   
  174       /**
  175        * Paints the image to the specified location.
  176        *
  177        * @param c Component painting to
  178        * @param g Graphics to paint to
  179        * @param x X coordinate to paint to
  180        * @param y Y coordinate to paint to
  181        * @param w Width to paint to
  182        * @param h Height to paint to
  183        * @param image Image to paint
  184        * @param args Arguments supplied to <code>paint</code>
  185        */
  186       protected void paintImage(Component c, Graphics g,
  187                                 int x, int y, int w, int h, Image image,
  188                                 Object[] args) {
  189           g.drawImage(image, x, y, null);
  190       }
  191   
  192       /**
  193        * Creates the image to cache.  This returns an opaque image, subclasses
  194        * that require translucency or transparency will need to override this
  195        * method.
  196        *
  197        * @param c Component painting to
  198        * @param w Width of image to create
  199        * @param h Height to image to create
  200        * @param config GraphicsConfiguration that will be
  201        *        rendered to, this may be null.
  202        * @param args Arguments passed to paint
  203        */
  204       protected Image createImage(Component c, int w, int h,
  205                                   GraphicsConfiguration config, Object[] args) {
  206           if (config == null) {
  207               return new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
  208           }
  209           return config.createCompatibleVolatileImage(w, h);
  210       }
  211   
  212       /**
  213        * Clear the image cache
  214        */
  215       protected void flush() {
  216           synchronized(CachedPainter.class) {
  217               getCache(getClass()).flush();
  218           }
  219       }
  220   
  221       private GraphicsConfiguration getGraphicsConfiguration(Component c) {
  222           if (c == null) {
  223               return null;
  224           }
  225           return c.getGraphicsConfiguration();
  226       }
  227   }

Home » openjdk-7 » sun » swing » [javadoc | source]