// License: GPL. For details, see LICENSE file.
package org.insignificant.josm.plugins.imagewaypoint;
import java.awt.Image;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.insignificant.josm.plugins.imagewaypoint.ImageEntry.IImageReadyListener;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.gpx.WayPoint;
import org.openstreetmap.josm.gui.layer.GpxLayer;
import org.openstreetmap.josm.gui.layer.Layer;
public final class ImageEntries {
private static final class ImageReadyListener implements
IImageReadyListener {
private final ImageEntries imageEntries;
ImageReadyListener(final ImageEntries imageEntries) {
this.imageEntries = imageEntries;
}
@Override
public void onImageReady(final ImageEntry imageEntry,
final Image image) {
this.imageEntries.setCurrentImage(imageEntry, image);
}
}
private static final ImageEntries INSTANCE = new ImageEntries();
private final List<ImageEntry> images;
private final List<ImageEntry> locatedImages;
private final List<IImageChangeListener> listeners;
private final IImageReadyListener listener;
private ImageEntry currentImageEntry;
private Image currentImage;
private ImageEntries() {
this.images = new ArrayList<>();
this.locatedImages = new ArrayList<>();
this.listeners = new ArrayList<>();
this.listener = new ImageReadyListener(this);
this.currentImageEntry = null;
this.currentImage = null;
}
public static ImageEntries getInstance() {
return ImageEntries.INSTANCE;
}
public void addListener(final IImageChangeListener listener) {
this.listeners.add(listener);
}
public void removeListener(final IImageChangeListener listener) {
this.listeners.remove(listener);
}
public void add(final File[] imageFiles) {
if (null != imageFiles) {
for (int index = 0; index < imageFiles.length; index++) {
this.images.add(new ImageEntry(imageFiles[index]));
}
this.associateAllLayers();
}
}
public void associateAllLayers() {
for (int index = 0; index < this.images.size(); index++) {
this.images.get(index).setWayPoint(null);
}
this.locatedImages.clear();
final Collection<Layer> layerCollection = Main.getLayerManager().getLayers();
final Layer[] layers = layerCollection.toArray(new Layer[layerCollection.size()]);
for (int index = 0; index < layers.length; index++) {
if (layers[index] instanceof GpxLayer
&& null != ((GpxLayer) layers[index]).data
&& !((GpxLayer) layers[index]).data.fromServer) {
this.doAssociateLayer((GpxLayer) layers[index]);
}
}
for (IImageChangeListener listener : this.listeners) {
listener.onSelectedImageEntryChanged(this);
}
}
private void doAssociateLayer(final GpxLayer gpxLayer) {
if (null != gpxLayer && null != gpxLayer.data
&& !gpxLayer.data.fromServer) {
for (WayPoint wayPoint : gpxLayer.data.waypoints) {
final List<String> texts = this.getTextContentsFromWayPoint(wayPoint);
for (String text : texts) {
final ImageEntry image = this.findImageEntryWithFileName(text);
if (null != image) {
image.setWayPoint(wayPoint);
this.locatedImages.add(image);
}
}
}
}
}
private List<String> getTextContentsFromWayPoint(
final WayPoint wayPoint) {
final List<String> texts = new ArrayList<>();
for (String s : new String[]{"name", "cmt", "desc"}) {
String t = wayPoint.getString(s);
if (null != t && 0 < t.length())
texts.add(t);
}
return texts;
}
// private final String getFileNameFromWayPointAttribute(
// final String attributeValue) {
// return null != attributeValue
// && (attributeValue.toLowerCase().endsWith(".jpg")
// || attributeValue.toLowerCase().endsWith(".jpeg")
// || attributeValue.toLowerCase().endsWith(".png") ||
// attributeValue.toLowerCase()
// .endsWith(".gif")) ? attributeValue : null;
// }
private ImageEntry findImageEntryWithFileName(final String fileName) {
ImageEntry foundimage = null;
for (int index = 0; index < this.images.size() && null == foundimage; index++) {
final ImageEntry image = this.images.get(index);
if (null == image.getWayPoint()
&& image.getFileName().startsWith(fileName)) {
foundimage = image;
}
}
return foundimage;
}
private void setCurrentImage(final ImageEntry imageEntry, final Image image) {
if (imageEntry == this.currentImageEntry) {
this.currentImage = image;
}
for (IImageChangeListener listener : this.listeners) {
listener.onSelectedImageEntryChanged(this);
}
}
public ImageEntry[] getImages() {
return this.locatedImages.toArray(new ImageEntry[this.locatedImages.size()]);
}
public ImageEntry getCurrentImageEntry() {
return this.currentImageEntry;
}
public Image getCurrentImage() {
return this.currentImage;
}
public boolean hasNext() {
return null != this.currentImageEntry
&& this.locatedImages.indexOf(this.currentImageEntry) < this.locatedImages.size() - 1;
}
public boolean hasPrevious() {
return null != this.currentImageEntry
&& this.locatedImages.indexOf(this.currentImageEntry) > 0;
}
public void next() {
if (null != this.currentImageEntry
&& this.locatedImages.indexOf(this.currentImageEntry) < this.locatedImages.size() - 1) {
this.setCurrentImageEntry(this.locatedImages.get(this.locatedImages.indexOf(this.currentImageEntry) + 1));
}
}
public void previous() {
if (null != this.currentImageEntry
&& this.locatedImages.indexOf(this.currentImageEntry) > 0) {
this.setCurrentImageEntry(this.locatedImages.get(this.locatedImages.indexOf(this.currentImageEntry) - 1));
}
}
public void rotateCurrentImageLeft() {
if (null != this.currentImageEntry) {
this.currentImageEntry.setOrientation(this.currentImageEntry.getOrientation()
.rotateLeft());
}
this.setCurrentImageEntry(this.currentImageEntry);
}
public void rotateCurrentImageRight() {
if (null != this.currentImageEntry) {
this.currentImageEntry.setOrientation(this.currentImageEntry.getOrientation()
.rotateRight());
}
this.setCurrentImageEntry(this.currentImageEntry);
}
public void setCurrentImageEntry(final ImageEntry imageEntry) {
if (null == imageEntry || this.locatedImages.contains(imageEntry)) {
if (null != this.currentImageEntry)
this.currentImageEntry.flush();
this.currentImageEntry = imageEntry;
this.currentImage = null;
for (IImageChangeListener listener : this.listeners) {
listener.onSelectedImageEntryChanged(this);
}
if (imageEntry != null) // now try to get the image
this.currentImageEntry.requestImage(this.listener);
}
}
}