/*
* Scriptographer
*
* This file is part of Scriptographer, a Scripting Plugin for Adobe Illustrator
* http://scriptographer.org/
*
* Copyright (c) 2002-2010, Juerg Lehni
* http://scratchdisk.com/
*
* All rights reserved. See LICENSE file for details.
*
* File created on 03.12.2004.
*/
package com.scriptographer.ai;
import com.scratchdisk.list.List;
import com.scratchdisk.list.Lists;
/**
* A Group is a collection of items. When you transform a Group, it's
* children are treated as a single unit without changing their relative
* positions. The Group's style or transparency blending attributes affect the
* rendering of it's children without changing their style/attributes.
*
* @author lehni
*/
public class Group extends Item {
protected Group(int handle, int docHandle, boolean created) {
super(handle, docHandle, created);
}
/**
* Creates a group item
*/
public Group() {
super(TYPE_GROUP);
}
/**
* Creates a group item.
*
* Sample code:
* <code>
* // Create an empty group:
* var group = new Group();
* // Append a path to the group:
* var line = new Path.Line(new Point(10, 10), new Point(50, 50));
* group.appendTop(line);
*
* // Create a group containing a path:
* var circle = new Path.Circle(new Point(10, 10), 100);
* var circleGroup = new Group([circle]);
* </code>
*
* @param children the children to be added to the newly created group
*/
public Group(List<? extends Item> children) {
this();
for (Item child : children)
this.appendBottom(child);
}
public Group(Item[] children) {
this(Lists.asList(children));
}
/**
* Specifies whether the group item is to be clipped.
* When setting to true, the first child in the group is automatically
* defined as the clipping mask.
*
* Sample code:
* <code>
* var group = new Group();
* group.appendChild(path);
* group.clipped = true;
* </code>
* @return {@true if the group item is to be clipped}
*/
public native boolean isClipped();
private native void nativeSetClipped(boolean clipped);
public void setClipped(boolean clipped) {
nativeSetClipped(clipped);
Item child = getFirstChild();
if (child != null)
child.setClipMask(clipped);
}
/*
* Setting selected attribute on Groups and CompoundPaths only works when
* also explicitly applying the same attributes to all the children, even
* when using setFully selected. So override both here.
*/
public void setSelected(boolean selected) {
Item child = getFirstChild();
while (child != null) {
child.setSelected(selected);
child = child.getNextSibling();
}
super.setSelected(selected);
}
public void setFullySelected(boolean selected) {
Item child = getFirstChild();
while (child != null) {
child.setFullySelected(selected);
child = child.getNextSibling();
}
super.setFullySelected(selected);
}
public Rectangle getBounds() {
// Delegate to the clipped item...
Item item = isClipped() ? getFirstChild() : null;
if (item != null)
return item.getBounds();
item = getFirstChild();
if (item != null) {
Rectangle bounds = item.getBounds();
item = item.getNextSibling();
while (item != null) {
bounds = bounds.unite(item.getBounds());
item = item.getNextSibling();
}
return bounds;
}
return super.getBounds();
}
public Rectangle getStrokeBounds() {
Item item = isClipped() ? getFirstChild() : null;
if (item != null)
return item.getStrokeBounds();
item = getFirstChild();
if (item != null) {
Rectangle bounds = item.getStrokeBounds();
item = item.getNextSibling();
while (item != null) {
bounds = bounds.unite(item.getStrokeBounds());
item = item.getNextSibling();
}
return bounds;
}
return super.getStrokeBounds();
}
public Rectangle getControlBounds() {
Item item = isClipped() ? getFirstChild() : null;
if (item != null)
return item.getControlBounds();
item = getFirstChild();
if (item != null) {
Rectangle bounds = item.getControlBounds();
item = item.getNextSibling();
while (item != null) {
bounds = bounds.unite(item.getControlBounds());
item = item.getNextSibling();
}
return bounds;
}
return super.getControlBounds();
}
}