package greenfoot.platforms.ide;
import bluej.runtime.ExecServer;
import greenfoot.Actor;
import greenfoot.World;
import greenfoot.core.ImageCache;
import greenfoot.core.Simulation;
import greenfoot.core.WorldHandler;
import greenfoot.vmcomm.VMCommsSimulation;
import greenfoot.vmcomm.VMCommsSimulation.PaintWhen;
import greenfoot.platforms.WorldHandlerDelegate;
import greenfoot.record.GreenfootRecorder;
import greenfoot.util.GreenfootUtil;
import threadchecker.OnThread;
import threadchecker.Tag;
import java.awt.Color;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
| Implementation for running in the Greenfoot IDE.
|
| @author Poul Henriksen
|
public class WorldHandlerDelegateIDE
implements WorldHandlerDelegate{
protected final Color envOpColour = new Color(152,32,32);
private final VMCommsSimulation vmCommsSimulation;
private boolean worldInitialising;
private final List<Actor> actorsToName = new ArrayList<>();
private String mostRecentlyInstantiatedWorldClassName;
public WorldHandlerDelegateIDE(VMCommsSimulation vmCommsSimulation)
{
this.vmCommsSimulation = vmCommsSimulation;
}
| Clear the world from the cache.
| @param world World to discard
|
@Override
public void discardWorld(World world)
{
ImageCache.getInstance().clearImageCache();
vmCommsSimulation.setWorld(null);
}
@Override
public void setWorld(final World oldWorld, final World newWorld)
{
nameActors(actorsToName.toArray(new Actor[0]));
if (oldWorld != null) {
discardWorld(oldWorld);
}
vmCommsSimulation.setWorld(newWorld);
}
@Override
public void initialisingWorld(String className)
{
worldInitialising = true;
mostRecentlyInstantiatedWorldClassName = className;
actorsToName.clear();
}
@Override
public void finishedInitialisingWorld()
{
worldInitialising = false;
}
@Override
@OnThread(Tag.Simulation)
public void paint(World drawWorld, boolean forcePaint)
{
vmCommsSimulation.paintRemote(forcePaint ? PaintWhen.FORCE : PaintWhen.IF_DUE);
}
@Override
public void notifyStoppedWithError()
{
vmCommsSimulation.notifyStoppedWithError();
}
@Override
public void instantiateNewWorld(String className, Runnable runIfError)
{
if (className != null)
{
mostRecentlyInstantiatedWorldClassName = className;
}
worldInitialising = true;
Class<? extends World> cls = getLastWorldClass();
if (cls == null)
{
runIfError.run();
return;
}
final Class<? extends World> icls = cls;
Simulation.getInstance().runLater(() -> {
try {
Constructor<?> cons = icls.getConstructor(new Class<?>[0]);
WorldHandler.getInstance().clearWorldSet();
World newWorld = (World) Simulation.newInstance(cons);
if (! WorldHandler.getInstance().checkWorldSet()) {
ImageCache.getInstance().clearImageCache();
WorldHandler.getInstance().setWorld(newWorld, false);
}
}
catch (LinkageError | NoSuchMethodException | IllegalAccessException | InstantiationException e) {
runIfError.run();
}
catch (InvocationTargetException ite) {
ite.getCause().printStackTrace();
runIfError.run();
}
catch (Exception e) {
System.err.println("Exception during World initialisation:");
e.printStackTrace();
runIfError.run();
}
worldInitialising = false;
});
}
| Get the last world class that was instantiated, if it can (still) be instantiated.
| May return null.
|
private Class extends World> getLastWorldClass()
{
if (mostRecentlyInstantiatedWorldClassName != null)
{
try
{
ClassLoader classLdr = ExecServer.getCurrentClassLoader();
Class<?> cls = Class.forName(mostRecentlyInstantiatedWorldClassName, false, classLdr);
if (GreenfootUtil.canBeInstantiated(cls))
{
return cls.asSubclass(World.class);
}
}
catch (java.lang.ClassNotFoundException cnfe)
{
}
catch (ClassCastException cce)
{
}
catch (LinkageError e)
{
e.printStackTrace();
}
}
return null;
}
@Override
public void objectAddedToWorld(Actor object)
{
if (worldInitialising) {
StackTraceElement[] methods = Thread.currentThread().getStackTrace();
boolean gonePastUs = false;
String lastWorldClassName = mostRecentlyInstantiatedWorldClassName;
if (lastWorldClassName == null) {
return;
}
for (StackTraceElement item : methods) {
if (GreenfootRecorder.METHOD_NAME.equals(item.getMethodName()) &&
item.getClassName().equals(lastWorldClassName)) {
actorsToName.add(object);
return;
}
if (gonePastUs && item.getClassName().startsWith("java.")) {
return;
}
gonePastUs = gonePastUs || "objectAddedToWorld".equals(item.getMethodName());
}
}
}
| This is a special method that will have a breakpoint set on it
| by GreenfootDebugHandler to watch out for actors which should
| be named. Do not remove or rename without also editing that code.
|
private void nameActors(Actor[] actor)
{
}
| Is the world currently initialising?
|
public boolean initialising()
{
return worldInitialising;
}
@Override
public String ask(final String prompt)
{
if (!Simulation.getInstance().equals(Thread.currentThread()))
throw new RuntimeException("Greenfoot.ask can only be called from the main simulation thread");
int askId = vmCommsSimulation.getAskId();
return vmCommsSimulation.doAsk(askId, prompt);
}
}
top,
use,
map,
class WorldHandlerDelegateIDE
. WorldHandlerDelegateIDE
. discardWorld
. setWorld
. initialisingWorld
. finishedInitialisingWorld
. paint
. notifyStoppedWithError
. instantiateNewWorld
. getLastWorldClass
. objectAddedToWorld
. nameActors
. initialising
. ask
309 neLoCode
+ 10 LoComm