package ovh.gasser.newshapes.shapes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ovh.gasser.newshapes.App; import ovh.gasser.newshapes.ShapeVisitor; import ovh.gasser.newshapes.attributes.Attributes; import ovh.gasser.newshapes.attributes.ColorAttributes; import ovh.gasser.newshapes.attributes.SelectionAttributes; import ovh.gasser.newshapes.util.Streamable; import javax.swing.text.html.Option; import java.awt.*; import java.util.*; import java.util.List; public class SCollection extends AbstractShape implements Streamable { private final static Logger logger = LoggerFactory.getLogger(SCollection.class); private final List children; private SCollection(Shape... shapes) { this.children = new ArrayList<>(List.of(shapes)); } @Override public void accept(ShapeVisitor visitor) { visitor.visitCollection(this); } @Override public Rectangle getBounds() { try { if (children.isEmpty()) { // If the SCollection is empty, set the bounds to fill the window return new Rectangle(App.WIN_SIZE); } Rectangle bounds = children.get(0).getBounds(); for (Shape s : children) bounds = bounds.union(s.getBounds()); return bounds; } catch (IndexOutOfBoundsException e){ logger.error("getBounds(): {}", e); throw new RuntimeException(e); } } @Override public Shape clone() { var clonedChildren = children.stream().map(Shape::clone).toArray(Shape[]::new); var collection = new SCollection(clonedChildren); collection.addAttributes(new SelectionAttributes()); return collection; } @Override public void translate(int dx, int dy) { children.forEach(s -> s.translate(dx, dy)); } @Override public Iterator iterator() { return children.iterator(); } @Override public Spliterator spliterator() { return children.spliterator(); } public void add(Shape s) { children.add(s); } public void remove(Shape s) { if (!children.remove(s)) { logger.error("Unable to delete shape: {}", s); } } @Override public Attributes getAttributes(String key) { if (key.equals(ColorAttributes.ID)) { // If the shape is a collection, it does not support color attributes directly // For now, use the attributes from the first child shape Optional first = children.stream().findFirst(); return first.map(shape -> shape.getAttributes(key)).orElse(null); } return super.getAttributes(key); } @Override public void addAttributes(Attributes attrs) { // Propagate color attributes to children if (attrs.getID().equals(ColorAttributes.ID)) { children.forEach(shape -> shape.addAttributes(attrs)); } super.addAttributes(attrs); } @Override public String toString() { StringBuilder sb = new StringBuilder("SCollection{"); children.forEach(obj -> sb.append(obj).append(", ")); return sb.append("}").toString(); } public static SCollection of(Shape ...shapes) { SCollection collection = new SCollection(shapes); collection.addAttributes(new SelectionAttributes()); return collection; } }