/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
/*
* @(#)SVGGroupFigure.java 1.0.1 2007-07-28
*
* Copyright (c) 1996-2007 by the original authors of JHotDraw
* and all its contributors.
* All rights reserved.
*
* The copyright of this software is owned by the authors and
* contributors of the JHotDraw project ("the copyright holders").
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* the copyright holders. For details see accompanying license terms.
*/
package org.jhotdraw.samples.svg.figures;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import org.jhotdraw.draw.*;
import org.jhotdraw.samples.svg.*;
import org.jhotdraw.xml.*;
import static org.jhotdraw.samples.svg.SVGAttributeKeys.*;
/**
* SVGGroupFigure.
*
* @author Werner Randelshofer
* @version 1.0.1 2007-07-28 Bounds were not computed correctly.
* <br>1.0 July 8, 2006 Created.
*/
public class SVGGroupFigure extends GroupFigure implements SVGFigure {
private HashMap<AttributeKey, Object> attributes = new HashMap<AttributeKey, Object>();
/** Creates a new instance. */
public SVGGroupFigure() {
SVGAttributeKeys.setDefaults(this);
}
@Override
public <T> void setAttribute(AttributeKey<T> key, T value) {
if (key == OPACITY) {
attributes.put(key, value);
} else if (key == LINK || key == LINK_TARGET) {
attributes.put(key, value);
} else {
super.setAttribute(key, value);
}
invalidate();
}
@Override
public <T> T getAttribute(AttributeKey<T> key) {
return key.get(attributes);
}
@Override
public Map<AttributeKey, Object> getAttributes() {
return new HashMap<AttributeKey, Object>(attributes);
}
@SuppressWarnings("unchecked")
public void setAttributes(Map<AttributeKey, Object> map) {
for (Map.Entry<AttributeKey, Object> entry : map.entrySet()) {
setAttribute(entry.getKey(), entry.getValue());
}
}
@Override
public void draw(Graphics2D g) {
double opacity = OPACITY.get(this);
opacity = Math.min(Math.max(0d, opacity), 1d);
if (opacity != 0d) {
if (opacity != 1d) {
Rectangle2D.Double drawingArea = getDrawingArea();
Rectangle2D clipBounds = g.getClipBounds();
if (clipBounds != null) {
Rectangle2D.intersect(drawingArea, clipBounds, drawingArea);
}
if (!drawingArea.isEmpty()) {
BufferedImage buf = new BufferedImage(
Math.max(1, (int) ((2 + drawingArea.width) * g.getTransform().getScaleX())),
Math.max(1, (int) ((2 + drawingArea.height) * g.getTransform().getScaleY())),
BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = buf.createGraphics();
gr.scale(g.getTransform().getScaleX(), g.getTransform().getScaleY());
gr.translate((int) -drawingArea.x, (int) -drawingArea.y);
gr.setRenderingHints(g.getRenderingHints());
super.draw(gr);
gr.dispose();
Composite savedComposite = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) opacity));
g.drawImage(buf, (int) drawingArea.x, (int) drawingArea.y,
2 + (int) drawingArea.width, 2 + (int) drawingArea.height, null);
g.setComposite(savedComposite);
}
} else {
super.draw(g);
}
}
}
public Rectangle2D.Double getBounds() {
if (cachedBounds == null) {
if (getChildCount() == 0) {
cachedBounds = new Rectangle2D.Double();
} else {
for (Figure f : children) {
Rectangle2D.Double bounds = f.getBounds();
if (TRANSFORM.get(f) != null) {
bounds.setRect(TRANSFORM.get(f).createTransformedShape(bounds).getBounds2D());
}
if (cachedBounds == null || cachedBounds.isEmpty()) {
cachedBounds = bounds;
} else {
cachedBounds.add(bounds);
}
}
}
}
return (Rectangle2D.Double) cachedBounds.clone();
}
@Override
public LinkedList<Handle> createHandles(int detailLevel) {
LinkedList<Handle> handles = new LinkedList<Handle>();
switch (detailLevel) {
case -1: // Mouse hover handles
TransformHandleKit.addGroupHoverHandles(this, handles);
break;
case 0:
TransformHandleKit.addGroupTransformHandles(this, handles);
handles.add(new LinkHandle(this));
break;
}
return handles;
}
@Override
final public void write(DOMOutput out) throws IOException {
throw new UnsupportedOperationException("Use SVGStorableOutput to write this Figure.");
}
@Override
final public void read(DOMInput in) throws IOException {
throw new UnsupportedOperationException("Use SVGStorableInput to read this Figure.");
}
public boolean isEmpty() {
return getChildCount() == 0;
}
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1));
buf.append('@');
buf.append(hashCode());
if (getChildCount() > 0) {
buf.append('(');
for (Iterator<Figure> i = getChildren().iterator(); i.hasNext();) {
Figure child = i.next();
buf.append(child);
if (i.hasNext()) {
buf.append(',');
}
}
buf.append(')');
}
return buf.toString();
}
public SVGGroupFigure clone() {
SVGGroupFigure that = (SVGGroupFigure) super.clone();
that.attributes = new HashMap<AttributeKey, Object>(this.attributes);
return that;
}
}