package org.samcrow.util;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.LinkedList;
import java.util.List;
import org.lekan.graphics.GraphicsProgram;
import org.lekan.graphics.SGFrame;
import org.lekan.graphics.SGObject;
/**
* Manages SGObjects to draw.
* Background objects are drawn in the background every time.
* Persistent objects are drawn after the background every time.
* Transient objects are drawn after the persistent objects only once. Calling <code>redraw</code> subsequently will erase them.
* @author Sam Crow
*
*/
public class DrawQueue {
private List<SGObject> transientObjects;
private List<SGObject> draggingObjects;//SGObjects that normally persist but can be cleared on demand. Drawn just before transient objects.
private List<SGObject> persistentObjects;//SGObjects that are redrawn every time, after the background
private List<SGObject> backgroundObjects;//SGObjects in the background that are redrawn every time
private GraphicsProgram program;
/**
* Constructor
* @param inProgram the GraphicsProgram that contains the SGFrame to draw to
*/
public DrawQueue(GraphicsProgram inProgram){
draggingObjects = Collections.synchronizedList(new LinkedList<SGObject>());
transientObjects = Collections.synchronizedList(new LinkedList<SGObject>());
backgroundObjects = Collections.synchronizedList(new LinkedList<SGObject>());
persistentObjects = Collections.synchronizedList(new LinkedList<SGObject>());
program = inProgram;
}
/**
* Constructor, specifying a collection of SGObjects to draw in the background every time
* @param inProgram the GraphicsProgram that contains the SGFrame to draw to
* @param inBackgroundObjects a Collection of background SGObjects
*/
public DrawQueue(GraphicsProgram inProgram, List<SGObject> inBackgroundObjects){
transientObjects = new LinkedList<SGObject>();
backgroundObjects = new LinkedList<SGObject>(inBackgroundObjects);
persistentObjects = new LinkedList<SGObject>();
program = inProgram;
}
/**
* Add an object to the background list
* @param object the SGObject to add
*/
public void addBackground(SGObject object){
backgroundObjects.add(object);
}
/**
* Add a Collection of objects to the background list
* @param objects the Collection of SGObjects to add
*/
public void addBackground(List<SGObject> objects){
backgroundObjects.addAll(objects);
}
/**
* Add an object to the persistent list
* @param object the SGObject to add
*/
public void addPersistent(SGObject object){
persistentObjects.add(object);
}
/**
* Add a Collection of objects to the persistent list
* @param objects the Collection of SGObjects to add
*/
public void addPersistent(List<SGObject> objects){
persistentObjects.addAll(objects);
}
/**
* Remove a collection of SGObjects from the queue
* @param objects the SGObjects to remove
*/
public void removePersistent(List<SGObject> objects){
persistentObjects.removeAll(objects);
}
/**
* Add a feature that will be drawn when <code>redraw</code> is called, but that will be erased
* when <code>redraw</code> is called subsequent times.
* @param object The SGObject that will be drawn
*/
public void addTransient(SGObject object){
transientObjects.add(object);
}
/**
* Add a Collection of objects to the transient list
* @param objects the Collection of SGObjects to add
*/
public void addTransient(List<SGObject> objects){
transientObjects.addAll(objects);
}
/**
* Remove all SGObejcts from the array of persistent objects to draw
*/
public void clearPersistent(){
persistentObjects.clear();
}
/**
* Add a dragging object
* @param object the object to add
*/
public void addDragging(SGObject object){
draggingObjects.add(object);
}
/**
* Add a List of dragging objects
* @param objects the objects to add
*/
public void addDragging(List<SGObject> objects){
draggingObjects.addAll(objects);
}
/**
* Clear all dragging objects
*/
public void clearDragging(){
draggingObjects.clear();
}
/**
* Clear the frame and draw all features added since the last call to <code>redraw</code>
*/
public void redrawAndClear(){
redraw();
transientObjects.clear();
}
/**
* Redraw the scene, specifying if transient objects should be cleared.
* @see org.samcrow.util.DrawQueue#redrawAndClear()
* @param clearTransient if transient objects should be cleared
*/
public void redraw(boolean clearTransient){
redraw();
if(clearTransient){
transientObjects.clear();
}
}
private void redraw(){
SGFrame frame = program.getFrame();
frame.clearGraphics();
try{
synchronized(backgroundObjects){
for(SGObject object : backgroundObjects){
frame.addObject(object);//no origin specified, so add it
}
}
}catch(ConcurrentModificationException e){
System.err.println("Encountered a ConcurrentModificationException while drawing background objects.");
//JOptionPane.showMessageDialog(null, "ConcurrentModificationException!");
redraw();
return;
}catch(IndexOutOfBoundsException e){
System.err.println("Encountered an IndexOutOfBoundsException while drawing background objects.");
redraw();
return;
}
try{
synchronized(persistentObjects){
for(SGObject object : persistentObjects){
frame.addObject(object);//no origin specified, so add it
}
}
}catch(ConcurrentModificationException e){
System.err.println("Encountered a ConcurrentModificationException while drawing persistent objects.");
//JOptionPane.showMessageDialog(null, "ConcurrentModificationException!");
redraw();
return;
}catch(IndexOutOfBoundsException e){
System.err.println("Encountered an IndexOutOfBoundsException while drawing persistent objects.");
redraw();
return;
}
try{
synchronized(transientObjects){
for(SGObject object : transientObjects){
frame.addObject(object);//no origin specified, so add it
}
}
}catch(ConcurrentModificationException e){
System.err.println("Encountered a ConcurrentModificationException while drawing transient objects.");
//JOptionPane.showMessageDialog(null, "ConcurrentModificationException!");
redraw();
return;
}catch(IndexOutOfBoundsException e){
System.err.println("Encountered an IndexOutOfBoundsException while drawing transient objects.");
redraw();
return;
}
try{
synchronized(draggingObjects){
for(SGObject object : draggingObjects){
frame.addObject(object);//no origin specified, so add it
}
}
}catch(ConcurrentModificationException e){
System.err.println("Encountered a ConcurrentModificationException while drawing dragging objects.");
//JOptionPane.showMessageDialog(null, "ConcurrentModificationException!");
redraw();
return;
}catch(IndexOutOfBoundsException e){
System.err.println("Encountered an IndexOutOfBoundsException while drawing dragging objects.");
redraw();
return;
}
}
}