/*
* Copyright 2008 Eckhart Arnold (eckhart_arnold@hotmail.com).
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.eckhartarnold.client;
//import java.lang.Iterable;
import java.util.HashMap;
//import java.util.Iterator;
//import java.util.NoSuchElementException;
//import com.google.gwt.user.client.DOM;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Image;
/**
* Administers a collection of thumbnail images.
*
* <p>The images are read upon instancing the class. Individual
* thumbnails can be
* picked from the collection with the method <code>get</code>; the number of
* thumbnails within the collection can be queried via <code>size</code>;
* finally, the sizes of all thumbnails can be adjusted with the method
* <code>adjustSize</code>. The index of each thumbnail is stored in the
* "id" field of the <code>\<img\></code>-Tag and can be queried via
* the <code>indexOf</code>-method. The "id"-field of the thumbnail image should
* should be considered as being "owned" by the <code>Thumbnail</code> object
* and should not be overwritten.
*
* @author ecki
*
*/
public class Thumbnails {
// private class Itr implements Iterator<Image> {
// int cursor = 0;
//
// public boolean hasNext() {
// return cursor < size();
// }
//
// public Image next() {
// if (hasNext()) {
// return get(cursor++);
// } else throw new NoSuchElementException();
// }
//
// public void remove() {
// assert false: "Thumbnail iterator does not allow removal of images!";
// }
// }
private static String[] cache_thumbnailURLs;
private static int[][] cache_thumbnailSizes;
private static ImageCollectionInfo cache_collection;
// /**
// * Determines the best ratio (width, height) for a given
// * array or thumbnail sizes. Uses a "quick and dirty" algorithm, where
// * the "best" ratio more or less reflects the frequency of ratios in
// * this array.
// *
// * @param thumbnailSizes the array of sizes of all thumbnails
// * @return an array of two integers where the first is the width
// * of the "best" ratio and the second its "height"
// */
// private static int[] determineBestRatio(int[][] thumbnailSizes) {
// int avW = 0, avH = 0;
// int ret[] = new int[2];
// for (int i = 0; i < thumbnailSizes.length; i++) {
// avW += thumbnailSizes[i][0];
// avH += thumbnailSizes[i][1];
// }
// avW /= thumbnailSizes.length;
// avH /= thumbnailSizes.length;
// ret[0] = thumbnailSizes[0][0];
// ret[1] = thumbnailSizes[0][1];
// int diff = Math.abs(avW - ret[0]) + Math.abs(avH - ret[1]);
// for (int i = 1; i < thumbnailSizes.length; i++) {
// int cmp = Math.abs(avW - thumbnailSizes[i][0]) +
// Math.abs(avH - thumbnailSizes[i][1]);
// if (cmp < diff) {
// ret[0] = thumbnailSizes[i][0];
// ret[1] = thumbnailSizes[i][1];
// diff = cmp;
// }
// }
// return ret;
// }
private Image[] imageList;
private int[][] thumbnailSizes;
private int[][] actualSizes;
// private int[] bestRatio;
/**
* Reads the thumbnails from the given image collection. It is assumed
* that the smallest version of each image in the collection is its
* thumbnail.
*
* @param collection the image collection from which the thumbnails are
* to be collected
*/
public Thumbnails(ImageCollectionInfo collection) {
String[] thumbnailURLs;
int[][] thumbnailSizes;
if (collection == cache_collection) {
thumbnailURLs = cache_thumbnailURLs;
thumbnailSizes = cache_thumbnailSizes;
} else {
String imageNames[] = collection.getImageNames();
HashMap<String, int[][]> imageSizes = collection.getImageSizes();
String thumbnailDir = collection.getDirectories()[0];
thumbnailURLs = new String[imageNames.length];
thumbnailSizes = new int[thumbnailURLs.length][2];
for (int i = 0; i < imageNames.length; i++) {
thumbnailURLs[i] = thumbnailDir + "/" + imageNames[i];
thumbnailSizes[i] = imageSizes.get(imageNames[i])[0];
}
cache_collection = collection;
cache_thumbnailURLs = thumbnailURLs;
cache_thumbnailSizes = thumbnailSizes;
}
init(thumbnailURLs, thumbnailSizes);
}
/**
* Collects the thumbnails the URLs of which are stored in the string array
* <code>thumnailsURLs</code>.
*
* @param thumbnailURLs the URLs of the thumbnails to be collected
* @param thumbnailSizes the respective sizes of the thumbnails
*/
public Thumbnails(String[] thumbnailURLs, int[][] thumbnailSizes) {
init(thumbnailURLs, thumbnailSizes);
}
/**
* Resizes all thumbnail images so they have the height
* <code>edgeHeight</code> whilst keeping the aspect ratio.
*
* @param edgeHeight the height to which the thumbnails shall
* be resized.
*/
public void adjustToHeight(int edgeHeight) {
for (int i = 0; i < imageList.length; i++) {
int tnW = thumbnailSizes[i][0];
int tnH = thumbnailSizes[i][1];
int w = tnW * edgeHeight / tnH;
actualSizes[i][0] = w;
actualSizes[i][1] = edgeHeight;
imageList[i].setPixelSize(w, edgeHeight);
}
}
/**
* Resizes the all thumbnails within the collection so that they fit in
* a rectangle of the size (<code>edgeWidth, edgeHeight</code>.
* The aspect ratio is preserved.
*
* @param edgeWidth the (maximum) with of the thumbnails
* @param edgeHeight the (maximum) height of the thumbnails
*/
public void adjustToRectangle(int edgeWidth, int edgeHeight) {
for (int i = 0; i < imageList.length; i++) {
int tnW = thumbnailSizes[i][0];
int tnH = thumbnailSizes[i][1];
int w, h;
if (tnW == 0) {
w = 0;
h = edgeHeight;
} else if (tnH == 0) {
w = edgeWidth;
h = 0;
} else {
w = edgeWidth;
h = tnH * edgeWidth / tnW;
if (h > edgeHeight) {
h = edgeHeight;
w = tnW * edgeHeight / tnH;
}
}
actualSizes[i][0] = w;
actualSizes[i][1] = h;
imageList[i].setPixelSize(w, h);
}
}
// /**
// * Returns the "best" height for adjusting the thumbnail sizes assuming that
// * the width is fixed.
// * @param edgeWidth the (fixed) width, the thumbnails shall be adjusted to
// * @return the associated height for the "best" width/height ratio
// */
// public int bestHeight(int edgeWidth) {
// return ((bestRatio[1]*edgeWidth) / bestRatio[0]);
// }
//
// /**
// * Returns the "best" width for adjusting the thumbnail sizes assuming that
// * the height is fixed.
// * @param edgeHeight the (fixed) height, the thumbnails shall be adjusted to
// * @return the associated width for the "best" width/height ratio
// */
// public int bestWidth(int edgeHeight) {
// return ((bestRatio[0]*edgeHeight) / bestRatio[1]);
// }
/**
* Get the thumbnail image with the index <code>i</code>
* @param index the index of the image to be collected
* @return the image corresponding to the given index
*/
public Image get(int index) {
assert index >= 0 && index < size();
return imageList[index];
}
/**
* Returns the actual size of image <code>img</code>. This is the size
* after <code>adjustSize</code> has been called.
* @param index the index of the image for which the size shall be determined
* @return the actual size of the image
*/
public int[] imageSize(int index) {
assert index >= 0 && index < size();
return actualSizes[index];
}
// public Iterator<Image> iterator() {
// return new Itr();
// }
/**
* Returns the index of the given thumbnail image. (Indices are stored
* as string representation in the "id" field of the thumbnail.)
* @return the index of the thumbnail
*/
public int indexOf(Image img) {
// String id = DOM.getElementAttribute(img.getElement(), "id");
String id = img.getElement().getAttribute("id");
int index = Integer.parseInt(id);
assert index >= 0 && index < size() :
"Image is not a thumbnail or \"id\" was manipulated!";
return index;
}
public void setHooverStyle(String style) {
}
/**
* Returns the number ot thumbnails within the collection.
* @return the number of thumbnails
*/
public int size() {
return imageList.length;
}
private void init(String[] thumbnailURLs, int[][] thumbnailSizes) {
assert thumbnailURLs.length == thumbnailSizes.length;
this.thumbnailSizes = thumbnailSizes;
imageList = new Image[thumbnailURLs.length];
actualSizes = new int[thumbnailURLs.length][2];
for (int i = 0; i < thumbnailURLs.length; i++) {
imageList[i] = new Image(thumbnailURLs[i]);
Element imgElement = imageList[i].getElement();
// DOM.setElementAttribute(imgElement, "id", String.valueOf(i));
imgElement.setAttribute("id", String.valueOf(i));
actualSizes[i][0] = thumbnailSizes[i][0];
actualSizes[i][1] = thumbnailSizes[i][1];
}
// bestRatio = determineBestRatio(thumbnailSizes);
}
}