/* * File : MediaBagElement.java * Created : 19-dec-2000 15:36 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * 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 (see the LICENSE file). */ package edu.xtec.jclic.bags; import edu.xtec.jclic.edit.Editable; import edu.xtec.jclic.edit.Editor; import edu.xtec.jclic.fileSystem.FileSystem; import edu.xtec.jclic.misc.Utils; import edu.xtec.util.Domable; import edu.xtec.util.JDomUtility; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import javax.swing.ImageIcon; import net.sf.image4j.codec.bmp.BMPDecoder; import net.sf.image4j.codec.ico.ICODecoder; /** * <CODE>MediaBagElements</CODE> are the members of {@link edu.xtec.jclic.bags.MediaBag} * objects. Media elements have a name, a reference to a file (the <CODE>fileName</CODE>) * and, when initialized, a <CODE>data</CODE> field containing the raw content of * the media. They have also a flag indicating if the data must be saved into the * {@link edu.xtec.jclic.project.JClicProject} file or must be mantained as a single * reference to a external file. * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.08.28 */ public class MediaBagElement extends Object implements Editable, Domable, Comparable { private String name; private String fileName; private int usageCount; private Object data; public boolean projectFlag; public boolean saveFlag; public boolean animated; private boolean hasThumb; private boolean isGif; // 10-Aug-2015 // Added to allow renaming of media files private String metadata; /** Creates new MediaBagElement */ public MediaBagElement(String fileName) { this(fileName, null); } public MediaBagElement(String fileName, Object data) { this(fileName, data, fileName); } public MediaBagElement(String fileName, Object data, String name) { setName(name); setFileName(fileName); setData(data); usageCount = 0; animated = false; saveFlag = true; } public static final String ELEMENT_NAME = "media"; public static final String FILE = "file", NAME = "name", SAVE = "save", USAGE = "usage", ANIMATED = "animated"; public org.jdom.Element getJDomElement() { org.jdom.Element e = new org.jdom.Element(ELEMENT_NAME); e.setAttribute(NAME, name); e.setAttribute(FILE, fileName); if (!saveFlag) e.setAttribute(SAVE, JDomUtility.BOOL_STR[JDomUtility.FALSE]); if (usageCount > 0) e.setAttribute(USAGE, Integer.toString(usageCount)); if (isGif) e.setAttribute(ANIMATED, JDomUtility.BOOL_STR[animated ? JDomUtility.TRUE : JDomUtility.FALSE]); return e; } protected static MediaBagElement getMediaBagElement(org.jdom.Element e) throws Exception { MediaBagElement mb = new MediaBagElement("NONAME", null); mb.setProperties(e, null); return mb; } public void setProperties(org.jdom.Element e, Object aux) throws Exception { JDomUtility.checkName(e, ELEMENT_NAME); setName(JDomUtility.getStringAttr(e, NAME, name, false)); setFileName(JDomUtility.getStringAttr(e, FILE, fileName, false)); saveFlag = JDomUtility.getBoolAttr(e, SAVE, true); usageCount = JDomUtility.getIntAttr(e, USAGE, usageCount); animated = JDomUtility.getBoolAttr(e, ANIMATED, false); } public Editor getEditor(Editor parent) { return Editor.createEditor(getClass().getName() + "Editor", this, parent); } public boolean isEmpty() { return data == null; } public void setFileName(String sName) { fileName = FileSystem.stdFn(sName); data = null; animated = false; isGif = fileName.toLowerCase().endsWith(".gif"); } public String getFileName() { return fileName; } public void setMetaData(String meta) { metadata = meta; } public String getMetaData() { return metadata; } public boolean isImage() { return Utils.getFileType(fileName) == Utils.TYPE_IMAGE; } public void setData(Object sData) { data = sData; // CHANGED: 28/Apr/2016 - Don't clear animated flag! // animated=false; if (data != null && data instanceof Image) Toolkit.getDefaultToolkit().prepareImage((Image) data, -1, -1, null); } public void clearData() { if (data != null && !(data instanceof java.awt.Font)) { if (data instanceof Image) ((Image) data).flush(); setData(null); } } public Object getData() { return data; } public boolean isInternal() { return (data != null); } public void incUsageCount() { usageCount++; } public void decUsageCount() { usageCount--; } public boolean isUsed() { return usageCount <= 0; } @Override protected void finalize() throws Throwable { Image img = getImage(); if (img != null) img.flush(); data = null; super.finalize(); } public boolean prepareImage(FileSystem fs) throws Exception { boolean result = false; if (isImage()) { if (data == null || !(data instanceof Image)) { String fn = fileName.toLowerCase(); if (fn.endsWith(".bmp")) { // Old edu.xtec.jclic.misc.Bmp replaced by image4j //Bmp bmp=new Bmp(fs.getInputStream(fileName)); //setData(bmp.getImage()); BufferedImage img = BMPDecoder.read(fs.getInputStream(fileName)); setData(Toolkit.getDefaultToolkit().createImage(img.getSource())); } else if (fn.endsWith(".ico")) { java.util.List list = ICODecoder.read(fs.getInputStream(fileName)); int maxs = 0; BufferedImage img = null; int listSize = list.size(); for (int i = 0; i < listSize; i++) { BufferedImage imgtmp = (BufferedImage) list.get(i); int s = imgtmp.getWidth() * imgtmp.getHeight(); if (s >= maxs) { img = imgtmp; maxs = s; } } if (img != null) setData(Toolkit.getDefaultToolkit().createImage(img.getSource())); } else setData(fs.getImageFile(fileName)); } result = true; } return result; } private static int imgReadyFlag = (ImageObserver.WIDTH | ImageObserver.HEIGHT); public Image getImage() throws Exception { int imgStatus = 0; if (data == null || !(data instanceof Image)) return null; if (!animated) while (true) { imgStatus = Toolkit.getDefaultToolkit().checkImage((Image) data, -1, -1, null); if ((imgStatus & (ImageObserver.ERROR | ImageObserver.ABORT)) != 0) { System.err.println( "Error loading " + getName() + " - Toolkit.checkImage returned status: " + imgStatus); data = null; break; } else if ((imgStatus & imgReadyFlag) == imgReadyFlag) break; Thread.sleep(50); } if (data != null && (imgStatus & ImageObserver.FRAMEBITS) != 0) animated = true; return (Image) data; } public Image prepareAndGetImage(FileSystem fs) throws Exception { Image img = getImage(); if (img == null && data == null) { if (prepareImage(fs)) img = getImage(); } return img; } public ImageIcon getThumbNail(int maxWidth, int maxHeight, FileSystem fs) { ImageIcon result = null; try { Image img = prepareAndGetImage(fs); if (img == null) { img = Utils.getFileIcon(fileName).getImage(); } if (img != null && maxWidth > 0 && maxHeight > 0) { int w = img.getWidth(null); int h = img.getHeight(null); if (w > 0 && h > 0 && (w > maxWidth || h > maxHeight)) { double f = Math.min((double) maxWidth / w, (double) maxHeight / h); img = img.getScaledInstance((int) (f * w), (int) (f * h), Image.SCALE_SMOOTH); } result = new ImageIcon(img); hasThumb = true; } } catch (Exception ex) { System.err.println("Error reading image:\n" + ex); } return result; } public boolean isWaitingForImage() { if (hasThumb == true || animated == true || data == null || !(data instanceof Image)) return false; int state = Toolkit.getDefaultToolkit().checkImage((Image) data, -1, -1, null); if ((state & ImageObserver.FRAMEBITS) != 0) { animated = true; } boolean result = (state & (ImageObserver.ALLBITS | ImageObserver.FRAMEBITS)) == 0; return result; } /** Getter for property name. * @return Value of property name. * */ public java.lang.String getName() { return name; } /** Setter for property name. * @param name New value of property name. * */ public void setName(String name) { this.name = FileSystem.stdFn(name); } @Override public String toString() { return name; } public int compareTo(Object obj) { int result = -1; if (getName() != null && obj instanceof MediaBagElement) { result = getName().compareTo(((MediaBagElement) obj).getName()); } return result; } }