/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.cids.custom.switchon.objectrenderer;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import de.cismet.cids.dynamics.CidsBean;
import de.cismet.cids.dynamics.CidsBeanStore;
import de.cismet.security.WebAccessManager;
/**
* DOCUMENT ME!
*
* @author Gilles Baatz
* @version $Revision$, $Date$
*/
public class RepresentationPreview extends javax.swing.JPanel implements CidsBeanStore, ComponentListener {
//~ Static fields/initializers ---------------------------------------------
public static BufferedImage ERROR_IMAGE;
private static final transient org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
RepresentationPreview.class);
private static final int CACHE_SIZE = 100;
private static final Map<URL, SoftReference<Image>> IMAGE_CACHE = new LinkedHashMap<URL, SoftReference<Image>>(
CACHE_SIZE) {
@Override
protected boolean removeEldestEntry(final Map.Entry<URL, SoftReference<Image>> eldest) {
return size() >= CACHE_SIZE;
}
};
static {
try {
ERROR_IMAGE = ImageIO.read(RepresentationPreview.class.getResource(
"/de/cismet/cids/custom/switchon/objectrenderer/no_image.png"));
} catch (IOException ex) {
LOG.error("Could not fetch ERROR_IMAGE", ex);
}
}
//~ Instance fields --------------------------------------------------------
CidsBean representation;
private JComponent sizeReference;
private final Timer timer = new Timer(30, new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (originalImage != null) {
scaledimage = adjustScale(originalImage, 20, 20);
lblPicture.setIcon(new ImageIcon(scaledimage));
}
}
});
private Image scaledimage;
private Image originalImage;
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel jPanel4;
private org.jdesktop.swingx.JXBusyLabel lblBusy;
private javax.swing.JLabel lblPicture;
private javax.swing.JPanel pnlPicture;
// End of variables declaration//GEN-END:variables
//~ Constructors -----------------------------------------------------------
/**
* Creates new form RepresentationPreview.
*/
public RepresentationPreview() {
initComponents();
timer.setRepeats(false);
this.addComponentListener(this);
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param wait DOCUMENT ME!
*/
private void showWait(final boolean wait) {
if (wait) {
if (!lblBusy.isBusy()) {
((CardLayout)pnlPicture.getLayout()).show(pnlPicture, "busy");
lblBusy.setBusy(true);
}
} else {
((CardLayout)pnlPicture.getLayout()).show(pnlPicture, "image");
lblBusy.setBusy(false);
}
}
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The
* content of this method is always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
pnlPicture = new javax.swing.JPanel();
lblBusy = new org.jdesktop.swingx.JXBusyLabel(new Dimension(75, 75));
jPanel4 = new javax.swing.JPanel();
lblPicture = new javax.swing.JLabel();
setLayout(new java.awt.GridBagLayout());
pnlPicture.setLayout(new java.awt.CardLayout());
lblBusy.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
lblBusy.setMaximumSize(new java.awt.Dimension(140, 40));
lblBusy.setMinimumSize(new java.awt.Dimension(140, 60));
lblBusy.setPreferredSize(new java.awt.Dimension(140, 60));
pnlPicture.add(lblBusy, "busy");
jPanel4.setOpaque(false);
jPanel4.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(
lblPicture,
org.openide.util.NbBundle.getMessage(RepresentationPreview.class, "RepresentationPreview.lblPicture.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
jPanel4.add(lblPicture, gridBagConstraints);
pnlPicture.add(jPanel4, "image");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(pnlPicture, gridBagConstraints);
} // </editor-fold>//GEN-END:initComponents
/**
* DOCUMENT ME!
*
* @param tooltip DOCUMENT ME!
*/
public void indicateNotAvailable(final String tooltip) {
indicateNotAvailable(tooltip, new ImageIcon(ERROR_IMAGE), "Kein Vorschaubild vorhanden.");
}
/**
* DOCUMENT ME!
*
* @param tooltip DOCUMENT ME!
* @param icon DOCUMENT ME!
* @param text DOCUMENT ME!
*/
public void indicateNotAvailable(final String tooltip, final Icon icon, final String text) {
lblPicture.setIcon(icon);
lblPicture.setText(text);
lblPicture.setToolTipText(tooltip);
showWait(false);
}
/**
* DOCUMENT ME!
*
* @param tooltip DOCUMENT ME!
*/
private void indicateError(final String tooltip) {
lblPicture.setIcon(new ImageIcon(ERROR_IMAGE));
lblPicture.setText("Fehler beim Übertragen des Bildes!");
lblPicture.setToolTipText(tooltip);
showWait(false);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Override
public CidsBean getCidsBean() {
return representation;
}
/**
* DOCUMENT ME!
*
* @param cidsBean DOCUMENT ME!
*/
@Override
public void setCidsBean(final CidsBean cidsBean) {
representation = cidsBean;
final String urlString = (String)representation.getProperty("contentlocation");
try {
final URL url = new URL(urlString);
new LoadSelectedImageWorker(url).execute();
} catch (MalformedURLException ex) {
LOG.error(ex, ex);
}
}
/**
* DOCUMENT ME!
*
* @param imageUrl DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
public static Image downloadImageOfUrl(final URL imageUrl) throws Exception {
final SoftReference<Image> cachedImageRef = IMAGE_CACHE.get(imageUrl);
if (cachedImageRef != null) {
return cachedImageRef.get();
}
if (imageUrl != null) {
InputStream is = null;
try {
is = WebAccessManager.getInstance().doRequest(imageUrl);
final Image img = ImageIO.read(is);
if (img != null) {
IMAGE_CACHE.put(imageUrl, new SoftReference<Image>(img));
}
return img;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ex) {
LOG.warn("Error during closing InputStream.", ex);
}
}
}
}
return null;
}
/**
* DOCUMENT ME!
*
* @param bi DOCUMENT ME!
* @param insetX DOCUMENT ME!
* @param insetY DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Image adjustScale(final Image bi,
final int insetX,
final int insetY) {
final Dimension size;
if (sizeReference != null) {
size = sizeReference.getSize();
size.width = (int)(size.width * 0.75);
} else {
size = this.getSize();
}
final double scalex = size.getWidth() / bi.getWidth(null);
final double scaley = size.getHeight() / bi.getHeight(null);
final double scale = Math.min(scalex, scaley);
if (scale <= 1d) {
return bi.getScaledInstance((int)(bi.getWidth(null) * scale) - insetX,
(int)(bi.getHeight(null) * scale)
- insetY,
Image.SCALE_SMOOTH);
} else {
return bi;
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void componentResized(final ComponentEvent e) {
if (!timer.isRunning()) {
timer.setInitialDelay(300);
timer.start();
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void componentMoved(final ComponentEvent e) {
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void componentShown(final ComponentEvent e) {
timer.setInitialDelay(0);
timer.start();
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void componentHidden(final ComponentEvent e) {
}
/**
* DOCUMENT ME!
*
* @param sizeReference DOCUMENT ME!
*/
public void setSizeReference(final JComponent sizeReference) {
this.sizeReference = sizeReference;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public JComponent getSizeReference() {
return sizeReference;
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
final class LoadSelectedImageWorker extends SwingWorker<Image, Void> {
//~ Instance fields ----------------------------------------------------
private final URL imageUrl;
//~ Constructors -------------------------------------------------------
/**
* Creates a new LoadSelectedImageWorker object.
*
* @param imageUrl toLoad DOCUMENT ME!
*/
public LoadSelectedImageWorker(final URL imageUrl) {
this.imageUrl = imageUrl;
lblPicture.setText("");
lblPicture.setToolTipText(null);
showWait(!IMAGE_CACHE.containsKey(imageUrl));
}
//~ Methods ------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
@Override
protected Image doInBackground() throws Exception {
if (imageUrl != null) {
return downloadImageOfUrl(imageUrl);
}
return null;
}
/**
* DOCUMENT ME!
*/
@Override
protected void done() {
try {
originalImage = get();
if (originalImage == null) {
indicateNotAvailable("");
}
lblPicture.setText("");
lblPicture.setToolTipText(null);
lblPicture.setIcon(new ImageIcon(adjustScale(originalImage, 20, 20)));
} catch (InterruptedException ex) {
originalImage = null;
LOG.warn(ex, ex);
} catch (ExecutionException ex) {
originalImage = null;
LOG.error(ex, ex);
indicateNotAvailable("");
} finally {
showWait(false);
}
}
}
}