/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package es.eucm.ead.editor.model.nodes;
import es.eucm.ead.editor.R;
import es.eucm.ead.editor.model.EditorModel;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import es.eucm.ead.editor.model.ModelIndex;
/**
* A pattern-node allows editing a set of "engine-model" EditorNodes as a unit.
* There can be several pattern-nodes for a single editor-node (corresponding
* to alternate view-points).
* @author mfreire
*/
public class EditorNode extends DependencyNode<HashSet<DependencyNode<?>>> {
private static Logger logger = LoggerFactory.getLogger(EditorNode.class);
public static final int THUMBNAIL_SIZE = 128;
private static final BufferedImage defaultThumbnail = new BufferedImage(
THUMBNAIL_SIZE, 128, BufferedImage.TYPE_INT_ARGB);
protected BufferedImage thumbnail;
/**
* A list of indexed fields.
*/
protected String[] indexedFields;
/**
* Builds a new editor-node.
* @param id
* @param indexedFields
*/
public EditorNode(int id, String... indexedFields) {
super(id, new HashSet<DependencyNode<?>>());
this.indexedFields = indexedFields;
ModelIndex.addProperty(this, ModelIndex.editorIdFieldName, "" + id,
false);
}
/**
* Returns all fields that should be visited to fully re-index this node.
* @return
*/
public String[] getIndexedFields() {
return indexedFields;
}
public HashSet<DependencyNode<?>> getContents() {
return content;
}
@Override
public String getLinkIcon() {
return R.Drawable.assets__editor_png;
}
/**
* Subclasses should update their thumbnail when this is called.
* It may be called more than necessary, so subclasses should check if the
* update is really required...
*/
protected void updateThumbnail() {
// by default, do nothing
}
/**
* Sets an image as a thumbnail. The image is rescaled and centered as
* necessary.
* @param image
*/
public void setThumbnail(BufferedImage image) {
int fw = image.getWidth();
int fh = image.getHeight();
double s = Math.min(THUMBNAIL_SIZE * 1.0 / fw, THUMBNAIL_SIZE * 1.0
/ fh);
thumbnail = new BufferedImage(THUMBNAIL_SIZE, THUMBNAIL_SIZE,
BufferedImage.TYPE_INT_ARGB);
Graphics g = thumbnail.getGraphics();
int tw = (int) (s * fw);
int th = (int) (s * fh);
g.drawImage(image, (THUMBNAIL_SIZE - tw) / 2,
(THUMBNAIL_SIZE - th) / 2, tw, th, null);
}
public Image getThumbnail() {
if (thumbnail == null) {
updateThumbnail();
}
return thumbnail != null ? thumbnail : defaultThumbnail;
}
/**
* Many editor-nodes will only have a single child.
* @return
*/
public DependencyNode getFirst() {
return content.iterator().next();
}
public boolean addChild(DependencyNode<?> node) {
return content.add(node);
}
/**
* Generates an XML snippet with the contents of this EditorNode.
* Format is similar to
* <node class="ead.editor.model.MyClass" id="editor-id"
* contents="comma-separted-list-of-children">
* (element details here)
* </node>
*/
public void write(StringBuilder sb) {
sb.append("<node class='").append(getClass().getName())
.append("' id='").append(getId()).append("' contents='");
if (getContents().isEmpty()) {
sb.append("\'");
} else {
for (DependencyNode<?> n : getContents()) {
sb.append(n.getId()).append(",");
}
sb.setCharAt(sb.length() - 1, '\'');
}
sb.append(">\n\t");
writeInner(sb);
sb.append("\n</node>\n");
}
/**
* Writes inner contents to an XML snippet.
* @param sb
*/
public void writeInner(StringBuilder sb) {
// by default, nothing to write
}
@SuppressWarnings("unchecked")
public static EditorNode restore(Element element, EditorModel em) {
String className = element.getAttribute("class");
int id = Integer.parseInt(element.getAttribute("id"));
String contentIdStrings[] = element.getAttribute("contents").split(",");
EditorNode instance = null;
ClassLoader cl = EditorNode.class.getClassLoader();
try {
Class<EditorNode> c = (Class<EditorNode>) cl.loadClass(className);
instance = c.getConstructor(Integer.TYPE).newInstance(id);
for (String cid : contentIdStrings) {
instance.getContents().add(em.getNode(Integer.parseInt(cid)));
}
instance.restoreInner(element, em);
} catch (Exception e) {
logger.error("Could not restore editorNode for class {}",
className, e);
}
return instance;
}
public void restoreInner(Element element, EditorModel em) {
// by default, nothing to restore
}
/**
* Generates a one-line description with as much information as possible.
* @return a human-readable description of this node
*/
@Override
public String getTextualDescription(EditorModel m) {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName()).append(" (").append(getId())
.append(")");
for (DependencyNode n : getContents()) {
sb.append("\n").append(n.getTextualDescription(m));
}
return sb.toString();
}
}