Package com.aelitis.azureus.ui.swt.imageloader

Source Code of com.aelitis.azureus.ui.swt.imageloader.ImageLoader

/*
* Created on Jun 7, 2006 2:31:26 PM
* Copyright (C) 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*/
package com.aelitis.azureus.ui.swt.imageloader;

import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.ImageRepository;
import org.gudy.azureus2.ui.swt.Utils;

import com.aelitis.azureus.ui.skin.SkinProperties;
import com.aelitis.azureus.ui.skin.SkinPropertiesImpl;
import com.aelitis.azureus.ui.utils.ImageBytesDownloader;

/**
* Loads images from a skinProperty object. 
* <p>
* Will look for special suffixes (over, down, disabled) and try to
* load resources using base key and suffix. ie. loadImage("foo-over") when
* foo=image.png, will load image-over.png
* <p>
* Will also create own disabled images if base image found and no disabled
* image found.  Disabled opacity can be set via imageloader.disabled-opacity
* key
*
* @author TuxPaper
* @created Jun 7, 2006
*
*/
public class ImageLoader
  implements AEDiagnosticsEvidenceGenerator
{
  private static ImageLoader instance;

  private static final boolean DEBUG_UNLOAD = false;

  private static final boolean DEBUG_REFCOUNT = false;

  private static final int GC_INTERVAL = 60 * 1000;

  private final String[] sSuffixChecks = {
    "-over",
    "-down",
    "-disabled",
    "-selected",
    "-gray",
  };

  private Display display;

  public static Image noImage;

  private final ConcurrentHashMap<String, ImageLoaderRefInfo> mapImages;

  private final ArrayList<String> notFound;

  private CopyOnWriteArrayList<SkinProperties> skinProperties;

  //private final ClassLoader classLoader;

  private int disabledOpacity;

  private Set<String>    cached_resources = new HashSet<String>();
 
  private File cache_dir = new File(SystemProperties.getUserPath(), "cache" );
 

  public static ImageLoader getInstance() {
    if (ImageLoader.instance == null) {
      ImageLoader.instance = new ImageLoader(Display.getDefault(), null);
      // always add az2 icons to instance
      SkinPropertiesImpl skinProperties = new SkinPropertiesImpl(
          ImageRepository.class.getClassLoader(),
          "org/gudy/azureus2/ui/icons/", "icons.properties");
      ImageLoader.instance.addSkinProperties(skinProperties);
    }
    return ImageLoader.instance;
  }

  public ImageLoader(/*ClassLoader classLoader,*/Display display,
      SkinProperties skinProperties) {
    //this.classLoader = classLoader;
   
    File[]  files = cache_dir.listFiles();
   
    if ( files != null ){
      for (File f: files ){
        String  name = f.getName();
        if ( name.endsWith( ".ico" )){
          cached_resources.add( name );
        }
      }
    }
   
    mapImages = new ConcurrentHashMap<String, ImageLoaderRefInfo>();
    notFound = new ArrayList<String>();
    this.display = display;
    this.skinProperties = new CopyOnWriteArrayList<SkinProperties>();
    addSkinProperties(skinProperties);

    AEDiagnostics.addEvidenceGenerator(this);
    if (GC_INTERVAL > 0) {
      SimpleTimer.addPeriodicEvent("GC_ImageLoader", GC_INTERVAL,
          new TimerEventPerformer() {
            public void perform(TimerEvent event) {
              collectGarbage();
            }
          });
    }
  }

  /*
  private Image loadImage(Display display, String key) {
    for (SkinProperties sp : skinProperties) {
      String value = sp.getStringValue(key);
      if (value != null) {
        return loadImage(display, sp.getClassLoader(), value, key);
      }
    }
    return loadImage(display, null, null, key);
  }
  */

  private Image[] findResources(String sKey) {
    if (Collections.binarySearch(notFound, sKey) >= 0) {
      return null;
    }

    for (int i = 0; i < sSuffixChecks.length; i++) {
      String sSuffix = sSuffixChecks[i];

      if (sKey.endsWith(sSuffix)) {
        //System.out.println("YAY " + sSuffix + " for " + sKey);
        String sParentName = sKey.substring(0, sKey.length() - sSuffix.length());
        String[] sParentFiles = null;
        ClassLoader cl = null;
        for (SkinProperties sp : skinProperties) {
          sParentFiles = sp.getStringArray(sParentName);
          if (sParentFiles != null) {
            cl = sp.getClassLoader();
            break;
          }
        }
        if (sParentFiles != null) {
          boolean bFoundOne = false;
          Image[] images = parseValuesString(cl, sKey, sParentFiles, sSuffix);
          if (images != null) {
            for (int j = 0; j < images.length; j++) {
              Image image = images[j];
              if (isRealImage(image)) {
                bFoundOne = true;
              }
            }
            if (!bFoundOne) {
              for (int j = 0; j < images.length; j++) {
                Image image = images[j];
                if (isRealImage(image)) {
                  image.dispose();
                }
              }
            } else {
              return images;
            }
          }
        } else {
          // maybe there's another suffix..
          Image[] images = findResources(sParentName);
          if (images != null) {
            return images;
          }
        }
      }
    }

    int i = Collections.binarySearch(notFound, sKey) * -1 - 1;
    if (i >= 0) {
      notFound.add(i, sKey);
    }
    return null;
  }

  /**
   * @param values
   * @param suffix
   * @return
   *
   * @since 3.1.1.1
   */
  private Image[] parseValuesString(ClassLoader cl, String sKey,
      String[] values, String suffix) {
    Image[] images = null;

    int splitX = 0;
    int locationStart = 0;
    int useIndex = -1; // all
    if (values[0].equals("multi") && values.length > 2) {
      splitX = Integer.parseInt(values[1]);
      locationStart = 2;
    } else if (values[0].equals("multi-index") && values.length > 3) {
      splitX = Integer.parseInt(values[1]);
      useIndex = Integer.parseInt(values[2]);
      locationStart = 3;
    }

    if (locationStart == 0 || splitX <= 0) {
      images = new Image[values.length];
      for (int i = 0; i < values.length; i++) {
        int index = values[i].lastIndexOf('.');
        if (index > 0) {
          String sTryFile = values[i].substring(0, index) + suffix
              + values[i].substring(index);
          images[i] = loadImage(display, cl, sTryFile, sKey);

          if (images[i] == null) {
            sTryFile = values[i].substring(0, index) + suffix.replace('-', '_')
                + values[i].substring(index);
            images[i] = loadImage(display, cl, sTryFile, sKey);
          }
        }

        if (images[i] == null) {
          images[i] = getNoImage();
        }
      }
    } else {
      Image image = null;
      String fullImageKey = null;

      String origFile = values[locationStart];
      int index = origFile.lastIndexOf('.');
      if (index > 0) {
        if (useIndex == -1) {
          String sTryFile = origFile.substring(0, index) + suffix
              + origFile.substring(index);
          image = loadImage(display, cl, sTryFile, sKey);

          if (image == null) {
            sTryFile = origFile.substring(0, index) + suffix.replace('-', '_')
                + origFile.substring(index);
            image = loadImage(display, cl, sTryFile, sKey);
          }
        } else {
          String sTryFile = origFile.substring(0, index) + suffix
              + origFile.substring(index);

          // check the cache to see if full image is in there
          image = getImageFromMap(sTryFile);
          if (image == null) {
            image = loadImage(display, cl, sTryFile, sTryFile);
            boolean haveRealImage = isRealImage(image);
            if (haveRealImage) {
              fullImageKey = sTryFile;
              addImage(fullImageKey, image);
            } else if (sTryFile.matches(".*[-_]disabled.*")) {
              String sTryFileNonDisabled = sTryFile.replaceAll("[-_]disabled", "");
              image = getImageFromMap(sTryFileNonDisabled);
              if (image == null) {
                image = loadImage(display, cl, sTryFileNonDisabled,
                    sTryFileNonDisabled);
              }
              if (isRealImage(image)) {
                releaseImage(sTryFileNonDisabled);
                image = fadeImage(image);
                fullImageKey = sTryFile;
                addImage(fullImageKey, image);
              }
            }
          } else {
            fullImageKey = sTryFile;
          }
        }
      }
      if (image == null) {
        image = loadImage(display, cl, values[locationStart], sKey);
      }


      if (isRealImage(image)) {
        Rectangle bounds = image.getBounds();
        if (useIndex == -1) {
          images = new Image[(bounds.width + splitX - 1) / splitX];
          for (int i = 0; i < images.length; i++) {
            Image imgBG = Utils.createAlphaImage(display, splitX, bounds.height,
                (byte) 0);
            int pos = i * splitX;
            try {
            images[i] = Utils.blitImage(display, image, new Rectangle(pos, 0,
                Math.min(splitX, bounds.width - pos), bounds.height), imgBG,
                new Point(0, 0));
            } catch (Exception e) {
              Debug.out(e);
            }
            imgBG.dispose();
          }
        } else {
          images = new Image[1];
          Image imgBG = Utils.createAlphaImage(display, splitX, bounds.height, (byte) 0);
          try {
            int pos = useIndex * splitX;
            images[0] = Utils.blitImage(display, image, new Rectangle(pos, 0,
                Math.min(splitX, bounds.width - pos), bounds.height), imgBG,
                new Point(0, 0));
            } catch (Exception e) {
              Debug.out(e);
            }
        }

        if (fullImageKey != null) {
          releaseImage(fullImageKey);
        }
      }
    }

    return images;
  }

  private Image loadImage(Display display, ClassLoader cl, String res,
      String sKey) {
    Image img = null;
   
    //System.out.println("LoadImage " + sKey + " - " + res);
    if (res == null) {
      for (int i = 0; i < sSuffixChecks.length; i++) {
        String sSuffix = sSuffixChecks[i];

        if (sKey.endsWith(sSuffix)) {
          //System.out.println("Yay " + sSuffix + " for " + sKey);
          String sParentName = sKey.substring(0, sKey.length()
              - sSuffix.length());
          String sParentFile = null;
          for (SkinProperties sp : skinProperties) {
            sParentFile = sp.getStringValue(sParentName);
            if (sParentFile != null) {
              if (cl == null) {
                cl = sp.getClassLoader();
              }
              break;
            }
          }
          if (sParentFile != null) {
            int index = sParentFile.lastIndexOf('.');
            if (index > 0) {
              String sTryFile = sParentFile.substring(0, index) + sSuffix
                  + sParentFile.substring(index);
              img = loadImage(display, cl, sTryFile, sKey);

              if (img != null) {
                break;
              }

              sTryFile = sParentFile.substring(0, index)
                  + sSuffix.replace('-', '_') + sParentFile.substring(index);
              img = loadImage(display, cl, sTryFile, sKey);

              if (img != null) {
                break;
              }
            }
          }
        }
      }
    }

    if (img == null) {
      try {
        if (cl != null) {
          InputStream is = cl.getResourceAsStream(res);
          if (is != null) {
            img = new Image(display, is);
           
            //System.out.println("Loaded image from " + res + " via " + Debug.getCompressedStackTrace());
            is.close();
          }
        }

        if (img == null) {
          // don't do on sKey.endsWith("-disabled") because caller parseValueString
          // requires a failure so it can retry with _disabled.  If that fails,
          // we'll get here (stupid, I know)
          if (res.contains("_disabled.")) {
            String id = sKey.substring(0, sKey.length() - 9);
            Image imgToFade = getImage(id);
            if (isRealImage(imgToFade)) {
              img = fadeImage(imgToFade);
            }
            releaseImage(id);
          }else if (sKey.endsWith("-gray")) {
            String id = sKey.substring(0, sKey.length() - 5);
            Image imgToGray = getImage(id);
            if (isRealImage(imgToGray)) {
              img = new Image( display, imgToGray, SWT.IMAGE_GRAY );
            }
            releaseImage(id);
          }
          //System.err.println("ImageRepository:loadImage:: Resource not found: " + res);
        }
      } catch (Throwable e) {
        System.err.println("ImageRepository:loadImage:: Resource not found: "
            + res + "\n" + e);
      }
    }

    return img;
  }

  private Image fadeImage(Image imgToFade) {
    ImageData imageData = imgToFade.getImageData();
    Image img;
    // decrease alpha
    if (imageData.alphaData != null) {
      if (disabledOpacity == -1) {
        for (int i = 0; i < imageData.alphaData.length; i++) {
          imageData.alphaData[i] = (byte) ((imageData.alphaData[i] & 0xff) >> 3);
        }
      } else {
        for (int i = 0; i < imageData.alphaData.length; i++) {
          imageData.alphaData[i] = (byte) ((imageData.alphaData[i] & 0xff)
              * disabledOpacity / 100);
        }
      }
      img = new Image(display, imageData);
    } else {
      Rectangle bounds = imgToFade.getBounds();
      Image bg = Utils.createAlphaImage(display, bounds.width,
          bounds.height, (byte) 0);

      img = Utils.renderTransparency(display, bg, imgToFade,
          new Point(0, 0), disabledOpacity == -1 ? 64
              : disabledOpacity * 255 / 100);
      bg.dispose();
    }
    return img;
  }

  public void unLoadImages() {
    if (DEBUG_UNLOAD) {
      for (String key : mapImages.keySet()) {
        Image[] images = mapImages.get(key).getImages();
        if (images != null) {
          for (int i = 0; i < images.length; i++) {
            Image image = images[i];
            if (isRealImage(image)) {
              System.out.println("dispose " + image + ";" + key);
              image.dispose();
            }
          }
        }
      }
    } else {
      for (ImageLoaderRefInfo imageInfo : mapImages.values()) {
        Image[] images = imageInfo.getImages();
        if (images != null) {
          for (int i = 0; i < images.length; i++) {
            Image image = images[i];
            if (isRealImage(image)) {
              image.dispose();
            }
          }
        }
      }
    }
  }

  protected Image getImageFromMap(String sKey) {
    Image[] imagesFromMap = getImagesFromMap(sKey);
    if (imagesFromMap.length == 0) {
      return null;
    }
    return imagesFromMap[0];
  }

  protected Image[] getImagesFromMap(String sKey) {
    if (sKey == null) {
      return new Image[0];
    }

    ImageLoaderRefInfo imageInfo = mapImages.get(sKey);
    if (imageInfo != null && imageInfo.getImages() != null) {
      imageInfo.addref();
      if (DEBUG_REFCOUNT) {
        System.out.println("ImageLoader: ++ refcount to "
            + imageInfo.getRefCount() + " for " + sKey + " via "
            + Debug.getCompressedStackTrace());
      }
      return imageInfo.getImages();
    }

    return new Image[0];
  }

  public Image[] getImages(String sKey) {
    if (!Utils.isThisThreadSWT()) {
      Debug.out("getImages called on non-SWT thread");
      return new Image[0];
    }
    //System.out.println("getImages " + sKey);
    if (sKey == null) {
      return new Image[0];
    }

    ImageLoaderRefInfo imageInfo = mapImages.get(sKey);
    if (imageInfo != null && imageInfo.getImages() != null) {
      imageInfo.addref();
      if (DEBUG_REFCOUNT) {
        System.out.println("ImageLoader: ++ refcount to "
            + imageInfo.getRefCount() + " for " + sKey + " via "
            + Debug.getCompressedStackTrace());
      }
      return imageInfo.getImages();
    }

    Image[] images;
    String[] locations = null;
    ClassLoader cl = null;
    for (SkinProperties sp : skinProperties) {
      locations = sp.getStringArray(sKey);
      if (locations != null && locations.length > 0) {
        cl = sp.getClassLoader();
        break;
      }
    }
    //    System.out.println(sKey + "=" + properties.getStringValue(sKey)
    //        + ";" + ((locations == null) ? "null" : "" + locations.length));
    if (locations == null || locations.length == 0) {
      images = findResources(sKey);

      if (images == null) {
        String  cache_key = sKey.hashCode() + ".ico";
        if ( cached_resources.contains( cache_key )){
          File cache = new File( cache_dir, cache_key );
          if (cache.exists()) {
            try {
              FileInputStream fis = new FileInputStream(cache);
 
              try {
                byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis);
                InputStream is = new ByteArrayInputStream(imageBytes);
 
                org.eclipse.swt.graphics.ImageLoader swtImageLoader = new org.eclipse.swt.graphics.ImageLoader();
                ImageData[] imageDatas = swtImageLoader.load(is);
                images = new Image[imageDatas.length];
                for (int i = 0; i < imageDatas.length; i++) {
                  images[i] = new Image(Display.getCurrent(), imageDatas[i]);
                }
 
                try {
                  is.close();
                } catch (IOException e) {
                }
              } finally {
                fis.close();
              }
            } catch (Throwable e) {
              Debug.printStackTrace(e);
            }
          }
        }else{
          cached_resources.remove( cache_key );
        }

        if (images == null) {
          images = new Image[0];
        }
      }

      for (int i = 0; i < images.length; i++) {
        if (images[i] == null) {
          images[i] = getNoImage();
        }
      }
    } else {
      images = parseValuesString(cl, sKey, locations, "");
    }

    mapImages.put(sKey, new ImageLoaderRefInfo(images));
    if (DEBUG_REFCOUNT) {
      System.out.println("ImageLoader: ++ refcount to "
          + "1 for " + sKey + " via "
          + Debug.getCompressedStackTrace());
    }

    return images;
  }

  public Image getImage(String sKey) {
    Image[] images = getImages(sKey);
    if (images == null || images.length == 0 || images[0].isDisposed()) {
      return getNoImage();
    }
    return images[0];
  }

  public long releaseImage(String sKey) {
    if (sKey == null) {
      return 0;
    }
    ImageLoaderRefInfo imageInfo = mapImages.get(sKey);
    if (imageInfo != null) {
      imageInfo.unref();
      if (false && imageInfo.getRefCount() < 0) {
        Image[] images = imageInfo.getImages();
        System.out.println("ImageLoader refcount < 0 for "
            + sKey
            + " by "
            + Debug.getCompressedStackTrace()
            + "\n  "
            + (images == null ? "null"
                : ("" + images.length + ";" + (images.length == 0 ? "0" : ""
                    + (images[0] == noImage)))));
      }
      if (DEBUG_REFCOUNT) {
        System.out.println("ImageLoader: -- refcount to "
            + imageInfo.getRefCount() + " for " + sKey + " via "
            + Debug.getCompressedStackTrace());
      }
      return imageInfo.getRefCount();
      // TODO: cleanup?
    }
    return 0;
  }

  /**
   * Adds image to repository.  refcount will be 1, or if key already exists,
   * refcount will increase.
   *
   * @param key
   * @param image
   *
   * @since 4.0.0.5
   */
  public void addImage(String key, Image image) {
    if (!Utils.isThisThreadSWT()) {
      Debug.out("addImage called on non-SWT thread");
      return;
    }
    ImageLoaderRefInfo existing = mapImages.putIfAbsent(key,
        new ImageLoaderRefInfo(image));
    if (existing != null) {
      // should probably fail if refcount > 0
      existing.setImages(new Image[] {
        image
      });
      existing.addref();
      if (DEBUG_REFCOUNT) {
        System.out.println("ImageLoader: ++ refcount to "
            + existing.getRefCount() + " for " + key + " via "
            + Debug.getCompressedStackTrace());
      }
    }
  }

  public void addImage(String key, Image[] images) {
    if (!Utils.isThisThreadSWT()) {
      Debug.out("addImage called on non-SWT thread");
      return;
    }
    ImageLoaderRefInfo existing = mapImages.putIfAbsent(key,
        new ImageLoaderRefInfo(images));
    if (existing != null) {
      // should probably fail if refcount > 0
      existing.setImages(images);
      existing.addref();
      if (DEBUG_REFCOUNT) {
        System.out.println("ImageLoader: ++ refcount to "
            + existing.getRefCount() + " for " + key + " via "
            + Debug.getCompressedStackTrace());
      }
    }
  }
 
  public void removeImage(String key) {
    // EEP!
    mapImages.remove(key);
  }

  public void addImageNoDipose(String key, Image image) {
    if (!Utils.isThisThreadSWT()) {
      Debug.out("addImageNoDispose called on non-SWT thread");
      return;
    }
    ImageLoaderRefInfo existing = mapImages.putIfAbsent(key,
        new ImageLoaderRefInfo(image));
    if (existing != null) {
      existing.setNonDisposable();
      // should probably fail if refcount > 0
      existing.setImages(new Image[] {
        image
      });
      existing.addref();
      if (DEBUG_REFCOUNT) {
        System.out.println("ImageLoader: ++ refcount to "
            + existing.getRefCount() + " for " + key + " via "
            + Debug.getCompressedStackTrace());
      }
    }
  }

  private static Image getNoImage() {
    if (noImage == null) {
      Display display = Display.getDefault();
      final int SIZE = 10;
      noImage = new Image(display, SIZE, SIZE);
      GC gc = new GC(noImage);
      gc.setBackground(display.getSystemColor(SWT.COLOR_YELLOW));
      gc.fillRectangle(0, 0, SIZE, SIZE);
      gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
      gc.drawRectangle(0, 0, SIZE - 1, SIZE - 1);
      gc.dispose();
    }
    return noImage;
  }

  public boolean imageExists(String name) {
    boolean exists = isRealImage(getImage(name));
    if (exists) {
      releaseImage(name);
    }
    return exists;
  }

  public boolean imageAdded(String name) {
    Image[] images = getImages(name);
    boolean added = images != null && images.length > 0;
    releaseImage(name);
    return added;
  }

  public static boolean isRealImage(Image image) {
    return image != null && image != getNoImage() && !image.isDisposed();
  }

  public int getAnimationDelay(String sKey) {
    for (SkinProperties sp : skinProperties) {
      int delay = sp.getIntValue(sKey + ".delay", -1);
      if (delay >= 0) {
        return delay;
      }
    }
    return 100;
  }

  public Image getUrlImage(final String url, final ImageDownloaderListener l) {
    if (!Utils.isThisThreadSWT()) {
      Debug.out("getUrlImage called on non-SWT thread");
      return null;
    }
    if (l == null || url == null) {
      return null;
    }

    if (imageExists(url)) {
      Image image = getImage(url);
      l.imageDownloaded(image, true);
      return image;
    }

    final String cache_key = url.hashCode() + ".ico";
   
    final File cache_file = new File( cache_dir, cache_key );

    if ( cached_resources.contains( cache_key )){
     
      if ( cache_file.exists()){
        try {
          FileInputStream fis = new FileInputStream(cache_file);
 
          try {
            byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis);
            InputStream is = new ByteArrayInputStream(imageBytes);
            Image image = new Image(Display.getCurrent(), is);
            try {
              is.close();
            } catch (IOException e) {
            }
            mapImages.put(url, new ImageLoaderRefInfo(image));
            l.imageDownloaded(image, true);
            return image;
          } finally {
            fis.close();
          }
        } catch (Throwable e) {
          Debug.printStackTrace(e);
        }
      }else{
       
        cached_resources.remove( cache_key );
      }
    }

    ImageBytesDownloader.loadImage(url,
        new ImageBytesDownloader.ImageDownloaderListener() {
          public void imageDownloaded(final byte[] imageBytes) {
            Utils.execSWTThread(new AERunnable() {
              public void runSupport() {
                FileUtil.writeBytesAsFile(cache_file.getAbsolutePath(), imageBytes);
                cached_resources.add( cache_key );
                InputStream is = new ByteArrayInputStream(imageBytes);
                Image image = new Image(Display.getCurrent(), is);
                try {
                  is.close();
                } catch (IOException e) {
                }
                mapImages.put(url, new ImageLoaderRefInfo(image));
                l.imageDownloaded(image, false);
              }
            });
          }
        });
    return null;
  }

  public static interface ImageDownloaderListener
  {
    public void imageDownloaded(Image image, boolean returnedImmediately);
  }

  // @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter)
  public void generate(IndentWriter writer) {

    writer.println("ImageLoader for " + skinProperties);
    writer.indent();
    long[] sizeCouldBeFree = {
      0
    };
    long[] totalSizeEstimate = {
      0
    };
    try {
      writer.indent();
      try {
        writer.println("Non-Disposable:");
        writer.indent();
        for (String key : mapImages.keySet()) {
          ImageLoaderRefInfo info = mapImages.get(key);
          if (!info.isNonDisposable()) {
            continue;
          }
          writeEvidenceLine(writer, key, info, totalSizeEstimate,
              sizeCouldBeFree);
        }
        writer.exdent();
        writer.println("Disposable:");
        writer.indent();
        for (String key : mapImages.keySet()) {
          ImageLoaderRefInfo info = mapImages.get(key);
          if (info.isNonDisposable()) {
            continue;
          }
          writeEvidenceLine(writer, key, info, totalSizeEstimate,
              sizeCouldBeFree);
        }
        writer.exdent();
      } finally {
        writer.exdent();
      }
      if (totalSizeEstimate[0] > 0) {
        writer.println((totalSizeEstimate[0] / 1024)
            + "k estimated used for images");
      }
      if (sizeCouldBeFree[0] > 0) {
        writer.println((sizeCouldBeFree[0] / 1024) + "k could be freed");
      }
    } finally {
      writer.exdent();
    }
  }

  /**
   * @param writer
   * @param info
   */
  private void writeEvidenceLine(IndentWriter writer, String key,
      ImageLoaderRefInfo info, long[] totalSizeEstimate, long[] sizeCouldBeFree) {
    String line = info.getRefCount() + "] " + key;
    if (Utils.isThisThreadSWT()) {
      long sizeEstimate = 0;
      Image[] images = info.getImages();
      for (int i = 0; i < images.length; i++) {
        Image img = images[i];
        if (img != null) {
          if (img.isDisposed()) {
            line += "; *DISPOSED*";
          } else {
            Rectangle bounds = img.getBounds();
            long est = bounds.width * bounds.height * 4l;
            sizeEstimate += est;
            totalSizeEstimate[0] += est;
            if (info.canDispose()) {
              sizeCouldBeFree[0] += est;
            }
          }
        }
      }
      line += "; est " + sizeEstimate + " bytes";
    }
    writer.println(line);
  }

  public void addSkinProperties(SkinProperties skinProperties) {
    if (skinProperties == null) {
      return;
    }
    this.skinProperties.add(skinProperties);
    disabledOpacity = skinProperties.getIntValue(
        "imageloader.disabled-opacity", -1);
    notFound.clear();
  }

  /**
   *
   *
   * @since 4.0.0.5
   */
  public void collectGarbage() {
    Utils.execSWTThread(new AERunnable() {
      public void runSupport() {
        int numRemoved = 0;
        for (Iterator<String> iter = mapImages.keySet().iterator(); iter.hasNext();) {
          String key = iter.next();
          ImageLoaderRefInfo info = mapImages.get(key);

          // no one can addref in between canDispose and dispose because
          // all our addrefs are in SWT threads.
          if (info != null && info.canDispose()) {
            if (DEBUG_UNLOAD) {
              System.out.println("dispose " + key);
            }
            iter.remove();
            numRemoved++;

            Image[] images = info.getImages();
            for (int j = 0; j < images.length; j++) {
              Image image = images[j];
              if (isRealImage(image)) {
                image.dispose();
              }
            }
          }
        }
        //System.out.println("ImageLoader: GC'd " + numRemoved);
      }
    });
  }

  /**
   * @param label
   * @param key
   *
   * @since 4.0.0.5
   */
  public void setLabelImage(Label label, final String key) {
    Image bg = getImage(key);
    label.setImage(bg);
    label.addDisposeListener(new DisposeListener() {
      public void widgetDisposed(DisposeEvent e) {
        releaseImage(key);
      }
    });
  }

  public void setButtonImage(Button btn, final String key) {
    Image bg = getImage(key);
    btn.setImage(bg);
    btn.addDisposeListener(new DisposeListener() {
      public void widgetDisposed(DisposeEvent e) {
        releaseImage(key);
      }
    });
  }

  public void setBackgroundImage(Control control, final String key) {
    Image bg = getImage(key);
    control.setBackgroundImage(bg);
    control.addDisposeListener(new DisposeListener() {
      public void widgetDisposed(DisposeEvent e) {
        releaseImage(key);
      }
    });
  }

  public SkinProperties[] getSkinProperties() {
    return skinProperties.toArray(new SkinProperties[0]);
  }

}
TOP

Related Classes of com.aelitis.azureus.ui.swt.imageloader.ImageLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
etElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');