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 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