//
// Triple Play - utilities for use in PlayN-based games
// Copyright (c) 2011-2014, Three Rings Design, Inc. - All rights reserved.
// http://github.com/threerings/tripleplay/blob/master/LICENSE

package tripleplay.ui;

import playn.core.GroupLayer;
import playn.core.Image;
import playn.core.Layer;
import playn.core.PlayN;
import playn.core.util.Callback;
import static playn.core.PlayN.graphics;

/**
 * Contains icon related utility classes and methods, mostly basic icon factories.
 */
public class Icons
{
    /**
     * A simple icon that uses an {@code Image} to get its dimensions and a simple image layer when
     * rendered. The the caller must ensure the image is loaded prior to invoking {@link Icon}
     * methods.
     */
    public static class Preloaded implements Icon {
        /** The image. */
        public final Image image;

        /** Creates a new icon for the given image. */
        public Preloaded (Image image) { this.image = image; }

        @Override public float width () { return getReady().width(); }
        @Override public float height () { return getReady().height(); }
        @Override public Layer render () { return graphics().createImageLayer(getReady()); }

        @Override public void addCallback (final Callback<? super Icon> callback) {
            // delegate to the image's callback
            image.addCallback(new Callback<Image>() {
                @Override public void onSuccess (Image result) {
                    callback.onSuccess(Preloaded.this);
                }
                @Override public void onFailure (Throwable cause) {
                    callback.onFailure(cause);
                }
            });
        }

        protected Image getReady () {
            if (!image.isReady()) {
                // issue a warning since this will normally cause display artifacts
                // TODO: remove and use assert(isReady())?
                Log.log.warning("Rendering image icon that isn't ready",
                    "icon", this, "image", image);
            }
            return image;
        }
    }

    /**
     * An icon that supports asynchronous images.
     */
    public static class Loader extends Preloaded
    {
        /** The dimensions. */
        public final float width, height;

        /**
         * Creates a new icon with the given image and dimensions. The image dimensions are
         * ignored. If the image is not yet loaded at render time, a blank layer will be returned
         * that will be automatically updated once the image is loaded.
         */
        public Loader (Image image, float width, float height) {
            super(image);
            this.width = width;
            this.height = height;
        }

        @Override public float width () { return width; }
        @Override public float height () { return height; }

        @Override public Layer render () {
            if (image.isReady()) return super.render();
            final GroupLayer gl = PlayN.graphics().createGroupLayer();
            image.addCallback(new Callback<Image>() {
                @Override public void onSuccess (Image result) {
                    if (!gl.destroyed()) { gl.add(Loader.super.render()); }
                }

                @Override public void onFailure (Throwable cause) {}
            });
            return gl;
        }
    }

    /**
     * Creates an icon using the supplied image. The the caller must ensure the image is loaded
     * prior to invoking {@link Icon} methods. See {@link Preloaded}.
     */
    public static Icon image (Image image) {
        return new Preloaded(image);
    }

    /**
     * Creates an icon using the supplied image and dimensions. If the icon is rendered prior to
     * the image being ready, a blank layer is returned that will automatically be populated
     * once the image is loaded.
     */
    public static Icon loader (Image image, float width, float height) {
        return new Loader(image, width, height);
    }
}

@@ -271,16 +271,46 @@
 .Image;%0A
+import playn.core.ImageLayer;%0A
 import p
@@ -384,16 +384,17 @@
 llback;%0A
+%0A
 import s
@@ -558,210 +558,75 @@
   * 
-A simple icon that uses an %7B@code Image%7D to get its dimensions and a simple image layer when%0A     * rendered. The the caller must ensure the image is loaded prior to invoking %7B@link Icon%7D%0A     * methods
+Base class for image icons just handling the image and the callback
 .%0A  
@@ -653,23 +653,32 @@
 tic 
-class Preloaded
+abstract class ImageIcon
  imp
@@ -823,25 +823,25 @@
  public 
-Preloaded
+ImageIcon
  (Image 
@@ -876,246 +876,8 @@
  %7D%0A%0A
-        @Override public float width () %7B return getReady().width(); %7D%0A        @Override public float height () %7B return getReady().height(); %7D%0A        @Override public Layer render () %7B return graphics().createImageLayer(getReady()); %7D%0A%0A
     
@@ -1162,25 +1162,25 @@
 Success(
-Preloaded
+ImageIcon
 .this);%0A
@@ -1347,32 +1347,670 @@
    %7D);%0A        %7D
+%0A    %7D%0A%0A    /**%0A     * A simple icon that uses an %7B@code Image%7D to get its dimensions and a simple image layer when%0A     * rendered. The the caller must ensure the image is loaded prior to invoking %7B@link Icon%7D%0A     * methods.%0A     */%0A    public static class Preloaded extends ImageIcon %7B%0A        /** Creates a new icon for the given image. */%0A        public Preloaded (Image image) %7B super(image); %7D%0A%0A        @Override public float width () %7B return getReady().width(); %7D%0A        @Override public float height () %7B return getReady().height(); %7D%0A        @Override public Layer render () %7B return graphics().createImageLayer(getReady()); %7D
 %0A%0A        protec
@@ -2498,25 +2498,25 @@
 extends 
-Preloaded
+ImageIcon
 %0A    %7B%0A 
@@ -3244,28 +3244,27 @@
  return 
-super.
 render
+Image
 ();%0A    
@@ -3503,27 +3503,19 @@
 add(
-Loader.super.
 render
+Image
 ());
@@ -3645,32 +3645,221 @@
 rn gl;%0A        %7D
+%0A%0A        protected ImageLayer renderImage () %7B%0A            ImageLayer il = PlayN.graphics().createImageLayer(image);%0A            il.setSize(width, height);%0A            return il;%0A        %7D
 %0A    %7D%0A%0A    /**%0A

Set the size for Icons.Loader ImageLayer's.