package com.kreative.paint.document.layer;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import com.kreative.paint.document.undo.Atom;
import com.kreative.paint.document.undo.History;
public class GroupLayer extends Layer implements List<Layer> {
private List<Layer> layers;
private LayerListener listener;
public GroupLayer(String name) {
super(name);
this.layers = new ArrayList<Layer>();
this.listener = new GroupLayerLayerListener(this);
}
private GroupLayer(GroupLayer o) {
super(o);
this.layers = new ArrayList<Layer>();
for (Layer l : o.layers) this.layers.add(l.clone());
this.listener = new GroupLayerLayerListener(this);
for (Layer l : this.layers) l.addLayerListener(listener);
}
@Override
public void setHistory(History history) {
super.setHistory(history);
for (Layer l : this.layers) l.setHistory(history);
}
@Override
public GroupLayer clone() {
return new GroupLayer(this);
}
@Override
protected void paintImpl(Graphics2D g, int gx, int gy, int gw, int gh) {
for (Layer l : layers) {
if (l.visible) {
l.paint(g, gx, gy, gw, gh, -gx, -gy);
}
}
}
private static class SetLayersAtom implements Atom {
private GroupLayer l;
private List<Layer> oldLayers;
private List<Layer> newLayers;
public SetLayersAtom(
GroupLayer l,
List<Layer> oldLayers,
List<Layer> newLayers
) {
this.l = l;
this.oldLayers = oldLayers;
this.newLayers = newLayers;
}
@Override
public boolean canBuildUpon(Atom prev) {
return (prev instanceof SetLayersAtom)
&& (((SetLayersAtom)prev).l == this.l);
}
@Override
public Atom buildUpon(Atom prev) {
this.oldLayers = ((SetLayersAtom)prev).oldLayers;
return this;
}
@Override
public void redo() {
l.layers.clear();
l.layers.addAll(newLayers);
for (Layer layer : oldLayers) {
layer.setHistory(null);
layer.removeLayerListener(l.listener);
}
for (Layer layer : newLayers) {
layer.setHistory(l.history);
layer.addLayerListener(l.listener);
}
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public void undo() {
l.layers.clear();
l.layers.addAll(oldLayers);
for (Layer layer : newLayers) {
layer.setHistory(null);
layer.removeLayerListener(l.listener);
}
for (Layer layer : oldLayers) {
layer.setHistory(l.history);
layer.addLayerListener(l.listener);
}
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
}
private List<Layer> changing() {
List<Layer> oldLayers = new ArrayList<Layer>();
oldLayers.addAll(layers);
return oldLayers;
}
private void changed(List<Layer> oldLayers) {
List<Layer> newLayers = new ArrayList<Layer>();
newLayers.addAll(layers);
if (history != null) history.add(new SetLayersAtom(this, oldLayers, newLayers));
for (Layer layer : oldLayers) {
layer.setHistory(null);
layer.removeLayerListener(listener);
}
for (Layer layer : newLayers) {
layer.setHistory(history);
layer.addLayerListener(listener);
}
this.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public boolean add(Layer o) {
List<Layer> c = changing();
boolean r = layers.add(o);
changed(c);
return r;
}
@Override
public void add(int index, Layer o) {
List<Layer> c = changing();
layers.add(index, o);
changed(c);
}
@Override
public boolean addAll(Collection<? extends Layer> coll) {
List<Layer> c = changing();
boolean r = layers.addAll(coll);
changed(c);
return r;
}
@Override
public boolean addAll(int index, Collection<? extends Layer> coll) {
List<Layer> c = changing();
boolean r = layers.addAll(index, coll);
changed(c);
return r;
}
@Override
public void clear() {
List<Layer> c = changing();
layers.clear();
changed(c);
}
@Override
public boolean contains(Object o) {
return layers.contains(o);
}
@Override
public boolean containsAll(Collection<?> coll) {
return layers.containsAll(coll);
}
@Override
public Layer get(int index) {
return layers.get(index);
}
@Override
public int indexOf(Object o) {
return layers.indexOf(o);
}
@Override
public boolean isEmpty() {
return layers.isEmpty();
}
@Override
public Iterator<Layer> iterator() {
return Collections.unmodifiableList(layers).iterator();
}
@Override
public int lastIndexOf(Object o) {
return layers.lastIndexOf(o);
}
@Override
public ListIterator<Layer> listIterator() {
return Collections.unmodifiableList(layers).listIterator();
}
@Override
public ListIterator<Layer> listIterator(int index) {
return Collections.unmodifiableList(layers).listIterator(index);
}
@Override
public boolean remove(Object o) {
List<Layer> c = changing();
boolean r = layers.remove(o);
changed(c);
return r;
}
@Override
public Layer remove(int index) {
List<Layer> c = changing();
Layer r = layers.remove(index);
changed(c);
return r;
}
@Override
public boolean removeAll(Collection<?> coll) {
List<Layer> c = changing();
boolean r = layers.removeAll(coll);
changed(c);
return r;
}
@Override
public boolean retainAll(Collection<?> coll) {
List<Layer> c = changing();
boolean r = layers.retainAll(coll);
changed(c);
return r;
}
@Override
public Layer set(int index, Layer o) {
List<Layer> c = changing();
Layer r = layers.set(index, o);
changed(c);
return r;
}
@Override
public int size() {
return layers.size();
}
@Override
public List<Layer> subList(int fromIndex, int toIndex) {
return Collections.unmodifiableList(layers).subList(fromIndex, toIndex);
}
@Override
public Object[] toArray() {
return layers.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return layers.toArray(a);
}
private static class GroupLayerLayerListener implements LayerListener {
private final GroupLayer l;
public GroupLayerLayerListener(GroupLayer l) {
this.l = l;
}
@Override
public void layerNameChanged(LayerEvent e) {
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public void layerVisibleChanged(LayerEvent e) {
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public void layerLockedChanged(LayerEvent e) {
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public void layerSelectedChanged(LayerEvent e) {
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public void layerLocationChanged(LayerEvent e) {
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
@Override
public void layerContentChanged(LayerEvent e) {
l.notifyLayerListeners(LayerEvent.LAYER_CONTENT_CHANGED);
}
}
}