JGraphAbstractIconAnimator.java :  » Graphic-Library » jgraph » org » jgraph » example » Java Open Source

Java Open Source » Graphic Library » jgraph 
jgraph » org » jgraph » example » JGraphAbstractIconAnimator.java
/** Copyright (c) 2005 Timothy Wall, All Rights Reserved.
 Permission granted for any use, this notice must not
 be removed or modified.
 twall@users.sf.net
 */
package org.jgraph.example;

import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.util.Map;
import javax.swing.*;

/**
 * Provides animated {@link ImageIcon}s for <code>Component</code> s which
 * have CellRenderer-like functionality. Ordinarily, you'd get no animation with
 * ordinary {@link javax.swing.tree.TreeCellRenderer}or
 * {@link javax.swing.table.TableCellRenderer}since a single component is used
 * to paint multiple locations on the <code>Component</code>. Animated icons
 * must be tracked independently, one per animated cell. This class provides for
 * maintaining a number of independently animated icons for a given
 * {@link Component}context. A key must be provided which must be unique across
 * all elements of substructure (a table might provide "row x col", while a tree
 * might provide the actual value in a row).
 * <p>
 * Subclasses should be instantiated near the <code>Component</code> context
 * and override the {@link #getRepaintRect(Component,Object)}method to trigger
 * a refresh of its corresponding <code>Component</code> substructure
 * location.
 * <p>
 * Subclasses should take care to invoke {@link #stop()}when you want to stop
 * the animation on a particular location.
 * <p>
 * This class assumes that all operations will take place on the event dispatch
 * thread, thus there is no class-level synchronization.
 * 
 * @see javax.swing.tree.TreeCellRenderer
 * @see javax.swing.tree.DefaultTreeCellRenderer
 * @see javax.swing.table.TableCellRenderer
 * @see javax.swing.table.DefaultTableCellRenderer
 */
// TODO: Figure out how labels update their animation. They don't seem to
// use addImageObserver...
public abstract class JGraphAbstractIconAnimator {

  private static final Map contexts = new WeakHashMap();

  /**
   * Return whether the given icon is animated. Currently assumes the original
   * filename ends with "animated.gif".
   */
  public static boolean isAnimated(Icon icon) {
    // Kind of a hack... can we see if it's an animated GIF by looking
    // inside the ImageIcon some other way?
    if (icon instanceof ImageIcon) {
      // NOTE: icon.toString() may return null!
      String label = icon.toString();
      if (label != null && label.indexOf("animated.gif") != -1)
        return true;
    }
    return false;
  }

  /**
   * Return any existing, cached animator for the given context/key, or
   * <code>null</code> if there is none.
   */
  public static JGraphAbstractIconAnimator get(Component context, Object key) {
    Map map = (Map) contexts.get(context);
    if (map != null) {
      return (JGraphAbstractIconAnimator) map.get(key);
    }
    return null;
  }

  private final ImageIcon icon;

  private final Component context;

  private final Object key;

  /**
   * Create an object to animate <code>icon</code> on the given
   * <code>Component</code> at the substructure location represented by the
   * <code>key</code>.
   * 
   * @param context
   *            Component on which the animation is to be painted
   * @param key
   *            Substructure location identifier
   * @param icon
   *            The animated icon
   */
  public JGraphAbstractIconAnimator(final Component context,
      final Object key, ImageIcon icon) {
    this.context = context;
    this.key = key;
    // Make a copy, since the original icon may be used repeatedly.
    this.icon = new ImageIcon(icon.getImage());
    this.icon.setImageObserver(new ImageObserver() {
      public boolean imageUpdate(Image image, int flags, int x, int y,
          int w, int h) {
        if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
          repaint(context, key);
        }
        return (flags & (ALLBITS | ABORT)) == 0;
      }
    });
    Map map = (Map) contexts.get(context);
    if (map == null) {
      map = new HashMap();
      contexts.put(context, map);
    }
    map.put(key, this);
  }

  /**
   * Invoked when the animated icon indicates that it is time for a repaint.
   * 
   * @param context
   *            Component to refresh
   * @param key
   *            Substructure identification key
   */
  protected void repaint(Component context, Object key) {
    Rectangle rect = getRepaintRect(context, key);
    if (rect != null) {
      context.repaint(rect.x, rect.y, rect.width, rect.height);
    }
  }

  /**
   * Based on the <code>Component</code> context and key, return the
   * <code>Component</code> -relative rectangle to be repainted.
   */
  public abstract Rectangle getRepaintRect(Component context, Object key);

  /** Stop animating this instance of <code>AbstractIconAnimator</code>. */
  public void stop() {
    icon.setImageObserver(null);
    icon.getImage().flush();
    Map map = (Map) contexts.get(context);
    if (map != null) {
      map.remove(key);
      if (map.size() == 0)
        contexts.remove(context);
    }
  }

  /**
   * Returns the icon to be used for the renderer corresponding to this
   * <code>AbstractIconAnimator</code>.
   */
  public Icon getIcon() {
    return icon;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.