- Improve FakeApplication, integrate into main application
- Add separate execution thread for user code
- Add error handling for failing AppStates
- Add error handling for failing Controls
- AppStateExplorer now works when opening it after the scene

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10079 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 12 years ago
parent 2c6e8cbb2a
commit 2d1af0f1f8
  1. 25
      sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateExplorerTopComponent.java
  2. 2
      sdk/jme3-core/src/com/jme3/gde/core/appstates/AppStateManagerNode.java
  3. 9
      sdk/jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java
  4. 201
      sdk/jme3-core/src/com/jme3/gde/core/scene/FakeApplication.java
  5. 45
      sdk/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java
  6. 10
      sdk/jme3-core/src/com/jme3/gde/core/scene/SceneRequest.java

@ -74,31 +74,27 @@ preferredID = "AppStateExplorerTopComponent")
public final class AppStateExplorerTopComponent extends TopComponent implements ExplorerManager.Provider { public final class AppStateExplorerTopComponent extends TopComponent implements ExplorerManager.Provider {
private transient ExplorerManager explorerManager = new ExplorerManager(); private transient ExplorerManager explorerManager = new ExplorerManager();
private FakeApplication fakeApp;
private ProjectAssetManager mgr; private ProjectAssetManager mgr;
private SceneRequest currentRequest;
//TODO: move to global place
private SceneListener listener = new SceneListener() { private SceneListener listener = new SceneListener() {
public void sceneOpened(SceneRequest request) { public void sceneOpened(SceneRequest request) {
currentRequest = request;
Spatial rootNode = request.getRootNode(); Spatial rootNode = request.getRootNode();
if (!(rootNode instanceof com.jme3.scene.Node)) { if (!(rootNode instanceof com.jme3.scene.Node)) {
return; return;
} }
mgr = request.getManager(); mgr = request.getManager();
AssetManager assetManager = request.getManager(); final AppStateManagerNode nod = new AppStateManagerNode(request.getFakeApp().getStateManager());
Camera cam = SceneApplication.getApplication().getCamera();
com.jme3.scene.Node guiNode = SceneApplication.getApplication().getGuiNode();
fakeApp = new FakeApplication((com.jme3.scene.Node) rootNode, guiNode, assetManager, cam);
//TODO: ermagherd, hackish
SceneApplication.getApplication().setFakeApp(fakeApp);
final AppStateManagerNode nod = new AppStateManagerNode(fakeApp.getStateManager());
jButton1.setEnabled(true); jButton1.setEnabled(true);
explorerManager.setRootContext(nod); explorerManager.setRootContext(nod);
setActivatedNodes(new Node[]{nod}); setActivatedNodes(new Node[]{nod});
} }
public void sceneClosed(SceneRequest request) { public void sceneClosed(SceneRequest request) {
currentRequest = null;
SceneApplication.getApplication().setFakeApp(null); SceneApplication.getApplication().setFakeApp(null);
mgr = null; mgr = null;
fakeApp = null;
jButton1.setEnabled(false); jButton1.setEnabled(false);
explorerManager.setRootContext(Node.EMPTY); explorerManager.setRootContext(Node.EMPTY);
setActivatedNodes(new Node[]{Node.EMPTY}); setActivatedNodes(new Node[]{Node.EMPTY});
@ -117,6 +113,11 @@ public final class AppStateExplorerTopComponent extends TopComponent implements
// map.put("moveup", new MoveUpAction()); // map.put("moveup", new MoveUpAction());
// map.put("movedown", new MoveDownAction()); // map.put("movedown", new MoveDownAction());
associateLookup(ExplorerUtils.createLookup(explorerManager, map)); associateLookup(ExplorerUtils.createLookup(explorerManager, map));
//TODO: move to scene listener notify in scene?
SceneRequest request = SceneApplication.getApplication().getCurrentSceneRequest();
if (request != null) {
listener.sceneOpened(request);
}
SceneApplication.getApplication().addSceneListener(listener); SceneApplication.getApplication().addSceneListener(listener);
} }
@ -165,9 +166,9 @@ public final class AppStateExplorerTopComponent extends TopComponent implements
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
ProjectAssetManager projectAssetManager = mgr; ProjectAssetManager projectAssetManager = mgr;
FakeApplication fakeApp = this.fakeApp; SceneRequest currentRequest = this.currentRequest;
if (fakeApp != null && mgr != null) { if (currentRequest != null && mgr != null && currentRequest.getFakeApp() != null) {
new NewAppStateWizardAction(projectAssetManager, fakeApp).showWizard(); new NewAppStateWizardAction(projectAssetManager, currentRequest.getFakeApp()).showWizard();
} }
}//GEN-LAST:event_jButton1ActionPerformed }//GEN-LAST:event_jButton1ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables

@ -32,7 +32,7 @@
package com.jme3.gde.core.appstates; package com.jme3.gde.core.appstates;
import com.jme3.app.state.AppState; import com.jme3.app.state.AppState;
import com.jme3.gde.core.appstates.FakeApplication.FakeAppStateManager; import com.jme3.gde.core.scene.FakeApplication.FakeAppStateManager;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.openide.nodes.AbstractNode; import org.openide.nodes.AbstractNode;

@ -48,17 +48,18 @@ public class ApplicationLogHandler extends Handler {
JmeFormatter formatter = new JmeFormatter(); JmeFormatter formatter = new JmeFormatter();
public ApplicationLogHandler() { public ApplicationLogHandler() {
io.setErrSeparated(true);
} }
@Override @Override
public void publish(LogRecord record) { public void publish(LogRecord record) {
if (record.getLevel().equals(Level.SEVERE)) { if (record.getLevel().equals(Level.SEVERE)) {
io.getErr().println(formatter.formatMessage(record)); io.getErr().println(formatter.formatMessage(record));
} } else if (record.getLevel().equals(Level.WARNING)) {
else if (record.getLevel().equals(Level.WARNING)) {
io.getErr().println(formatter.formatMessage(record)); io.getErr().println(formatter.formatMessage(record));
} } else if (record.getLevel().equals(Level.INFO)) {
else { io.getOut().println(formatter.formatMessage(record));
} else {
io.getOut().println(formatter.formatMessage(record)); io.getOut().println(formatter.formatMessage(record));
} }
} }

@ -29,7 +29,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.gde.core.appstates; package com.jme3.gde.core.scene;
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
@ -38,6 +38,7 @@ import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer; import com.jme3.audio.AudioRenderer;
import com.jme3.audio.Listener; import com.jme3.audio.Listener;
import com.jme3.gde.core.appstates.AppStateManagerNode;
import com.jme3.input.FlyByCamera; import com.jme3.input.FlyByCamera;
import com.jme3.input.InputManager; import com.jme3.input.InputManager;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
@ -45,6 +46,7 @@ import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer; import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.control.Control;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext; import com.jme3.system.JmeContext;
import com.jme3.system.JmeContext.Type; import com.jme3.system.JmeContext.Type;
@ -54,9 +56,14 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.openide.DialogDisplayer; import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
@ -332,9 +339,60 @@ public class FakeApplication extends SimpleApplication {
//TODO: also nice messages //TODO: also nice messages
} }
public static class FakeAppStateManager extends AppStateManager {
private AppStateManagerNode node;
ArrayList<AppState> states = new ArrayList<AppState>();
public FakeAppStateManager(Application app) {
super(app);
}
public List<AppState> getAddedStates() {
return states;
}
@Override
public boolean attach(AppState state) {
boolean ret = super.attach(state);
if (ret) {
states.add(state);
}
if (node != null) {
node.refresh();
}
return ret;
}
@Override
public boolean detach(AppState state) {
boolean ret = super.detach(state);
if (ret) {
states.remove(state);
}
if (node != null) {
node.refresh();
}
return ret;
}
public void setNode(AppStateManagerNode node) {
this.node = node;
}
}
/* /*
* Internal * Internal
*/ */
private ScheduledThreadPoolExecutor fakeAppThread;
public void startFakeApp() {
fakeAppThread = new ScheduledThreadPoolExecutor(1);
}
public void stopFakeApp() {
fakeAppThread.shutdown();
}
private void defaultFakeError() { private void defaultFakeError() {
defaultFakeError(false); defaultFakeError(false);
} }
@ -366,60 +424,129 @@ public class FakeApplication extends SimpleApplication {
NotifyDescriptor.WARNING_MESSAGE)); NotifyDescriptor.WARNING_MESSAGE));
} }
public void updateFake(float tpf) { private void removeAllStates() {
// System.out.println("UPDATE"); for (Iterator<AppState> it = new ArrayList(appStateManager.getAddedStates()).iterator(); it.hasNext();) {
appStateManager.update(tpf); AppState appState = it.next();
appStateManager.detach(appState);
}
} }
public void renderFake() { public boolean updateFake(final float tpf) {
appStateManager.render(renderManager); Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
appStateManager.update(tpf);
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in AppState, all AppStates removed."));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Update loop was blocked for too long, all AppStates removed."));
return false;
}
return true;
} }
public static class FakeAppStateManager extends AppStateManager { public boolean renderFake() {
Future fut = fakeAppThread.submit(new Callable<Void>() {
private AppStateManagerNode node; public Void call() throws Exception {
ArrayList<AppState> states = new ArrayList<AppState>(); appStateManager.render(renderManager);
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in AppState, all AppStates removed."));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
removeAllStates();
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Render loop was blocked for too long, all AppStates removed."));
return false;
}
return true;
}
public FakeAppStateManager(Application app) { public boolean updateExternalLogicalState(final Node externalNode, final float tpf) {
super(app); Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
externalNode.updateLogicalState(tpf);
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in Control, scene content removed.\n" + ex.getMessage()));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Render loop was blocked for too long, scene content removed."));
return false;
} }
return true;
}
public List<AppState> getAddedStates() { public boolean updateExternalGeometricState(final Node externalNode) {
return states; Future fut = fakeAppThread.submit(new Callable<Void>() {
public Void call() throws Exception {
externalNode.updateGeometricState();
return null;
}
});
try {
fut.get(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (ExecutionException ex) {
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Exception in Control, scene content removed.\n" + ex.getMessage()));
return false;
} catch (TimeoutException ex) {
fut.cancel(true);
clearNode(externalNode);
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Render loop was blocked for too long, scene content removed."));
return false;
} }
return true;
}
@Override private void clearNode(final Node externalNode) {
public boolean attach(AppState state) { while (!externalNode.getChildren().isEmpty()) {
boolean ret = super.attach(state);
try { try {
states.add(state); externalNode.detachAllChildren();
} catch (Exception e) { } catch (Exception e) {
Exceptions.printStackTrace(e); Exceptions.printStackTrace(e);
} catch (Error e) {
Exceptions.printStackTrace(e);
} }
// DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(
// "attach state",
// NotifyDescriptor.WARNING_MESSAGE));
if (node != null) {
// DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(
// "refresh node",
// NotifyDescriptor.WARNING_MESSAGE));
node.refresh();
}
return ret;
} }
Control control = externalNode.getControl(Control.class);
@Override while (control != null) {
public boolean detach(AppState state) {
try { try {
states.remove(state); externalNode.removeControl(control);
} catch (Exception e) { } catch (Exception e) {
Exceptions.printStackTrace(e); Exceptions.printStackTrace(e);
} catch (Error e) {
Exceptions.printStackTrace(e);
} }
return super.detach(state); control = externalNode.getControl(Control.class);
}
public void setNode(AppStateManagerNode node) {
this.node = node;
} }
} }
} }

@ -24,7 +24,6 @@
*/ */
package com.jme3.gde.core.scene; package com.jme3.gde.core.scene;
import com.jme3.gde.core.appstates.FakeApplication;
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.app.StatsView; import com.jme3.app.StatsView;
import com.jme3.bullet.BulletAppState; import com.jme3.bullet.BulletAppState;
@ -77,7 +76,7 @@ import org.openide.util.NbPreferences;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
/** /**
* *
* @author normenhansen * @author normenhansen
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -171,7 +170,6 @@ public class SceneApplication extends Application implements LookupProvider {
private void attachPanel() { private void attachPanel() {
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
panel.attachTo(true, viewPort, overlayView, guiViewPort); panel.attachTo(true, viewPort, overlayView, guiViewPort);
return null; return null;
@ -267,7 +265,7 @@ public class SceneApplication extends Application implements LookupProvider {
} }
try { try {
super.update(); super.update();
FakeApplication fakap=fakeApp; FakeApplication fakap = fakeApp;
float tpf = timer.getTimePerFrame(); float tpf = timer.getTimePerFrame();
camLight.setPosition(cam.getLocation()); camLight.setPosition(cam.getLocation());
secondCounter += tpf; secondCounter += tpf;
@ -277,16 +275,21 @@ public class SceneApplication extends Application implements LookupProvider {
secondCounter = 0.0f; secondCounter = 0.0f;
} }
getStateManager().update(tpf); getStateManager().update(tpf);
if(fakap!=null){ toolsNode.updateLogicalState(tpf);
if (fakap != null) {
fakap.updateFake(tpf); fakap.updateFake(tpf);
fakap.updateExternalLogicalState(rootNode, tpf);
fakap.updateExternalLogicalState(guiNode, tpf);
fakap.updateExternalGeometricState(rootNode);
fakap.updateExternalGeometricState(guiNode);
} else {
rootNode.updateLogicalState(tpf);
guiNode.updateLogicalState(tpf);
rootNode.updateGeometricState();
guiNode.updateGeometricState();
} }
rootNode.updateLogicalState(tpf);
guiNode.updateLogicalState(tpf);
toolsNode.updateLogicalState(tpf);
rootNode.updateGeometricState();
guiNode.updateGeometricState();
toolsNode.updateGeometricState(); toolsNode.updateGeometricState();
if(fakap!=null){ if (fakap != null) {
fakap.renderFake(); fakap.renderFake();
} }
getStateManager().render(renderManager); getStateManager().render(renderManager);
@ -331,7 +334,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void notifyPreview(final PreviewRequest request) { public void notifyPreview(final PreviewRequest request) {
java.awt.EventQueue.invokeLater(new Runnable() { java.awt.EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
for (Iterator<SceneListener> it = listeners.iterator(); it.hasNext();) { for (Iterator<SceneListener> it = listeners.iterator(); it.hasNext();) {
SceneListener sceneViewerListener = it.next(); SceneListener sceneViewerListener = it.next();
@ -347,12 +349,12 @@ public class SceneApplication extends Application implements LookupProvider {
/** /**
* method to display the node tree of a plugin (threadsafe) * method to display the node tree of a plugin (threadsafe)
*
* @param request * @param request
*/ */
public void openScene(final SceneRequest request) { public void openScene(final SceneRequest request) {
closeScene(currentSceneRequest, request); closeScene(currentSceneRequest, request);
java.awt.EventQueue.invokeLater(new Runnable() { java.awt.EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
if (request == null) { if (request == null) {
return; return;
@ -370,8 +372,10 @@ public class SceneApplication extends Application implements LookupProvider {
} else { } else {
camController.disable(); camController.disable();
} }
fakeApp = new FakeApplication(rootNode, guiNode, request.getManager(), cam);
fakeApp.startFakeApp();
request.setFakeApp(fakeApp);
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
if (request.getManager() != null) { if (request.getManager() != null) {
assetManager = request.getManager(); assetManager = request.getManager();
@ -396,6 +400,7 @@ public class SceneApplication extends Application implements LookupProvider {
/** /**
* method to close a scene displayed by a scene request (threadsafe) * method to close a scene displayed by a scene request (threadsafe)
*
* @param request * @param request
*/ */
public void closeScene(final SceneRequest request) { public void closeScene(final SceneRequest request) {
@ -404,7 +409,6 @@ public class SceneApplication extends Application implements LookupProvider {
private void closeScene(final SceneRequest oldRequest, final SceneRequest newRequest) { private void closeScene(final SceneRequest oldRequest, final SceneRequest newRequest) {
java.awt.EventQueue.invokeLater(new Runnable() { java.awt.EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
if (oldRequest == null) { if (oldRequest == null) {
return; return;
@ -425,8 +429,11 @@ public class SceneApplication extends Application implements LookupProvider {
if (oldRequest.getRequester() instanceof SceneApplication) { if (oldRequest.getRequester() instanceof SceneApplication) {
camController.disable(); camController.disable();
} }
if (fakeApp != null) {
fakeApp.stopFakeApp();
}
fakeApp = null;
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
if (physicsState != null) { if (physicsState != null) {
physicsState.getPhysicsSpace().removeAll(rootNode); physicsState.getPhysicsSpace().removeAll(rootNode);
@ -465,7 +472,7 @@ public class SceneApplication extends Application implements LookupProvider {
req.setModified(false); req.setModified(false);
} }
} }
if ((request != null) && (request.getDataObject()instanceof AssetDataObject)){ if ((request != null) && (request.getDataObject() instanceof AssetDataObject)) {
AssetDataObject obj = (AssetDataObject) request.getDataObject(); AssetDataObject obj = (AssetDataObject) request.getDataObject();
obj.closeAsset(); obj.closeAsset();
} }
@ -501,7 +508,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void enableCamLight(final boolean enabled) { public void enableCamLight(final boolean enabled) {
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
if (enabled) { if (enabled) {
rootNode.removeLight(camLight); rootNode.removeLight(camLight);
@ -516,7 +522,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void enableStats(final boolean enabled) { public void enableStats(final boolean enabled) {
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
if (enabled) { if (enabled) {
guiNode.attachChild(statsGuiNode); guiNode.attachChild(statsGuiNode);
@ -530,7 +535,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void enableWireFrame(final boolean selected) { public void enableWireFrame(final boolean selected) {
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
if (selected) { if (selected) {
viewPort.addProcessor(wireProcessor); viewPort.addProcessor(wireProcessor);
@ -544,7 +548,6 @@ public class SceneApplication extends Application implements LookupProvider {
public void setPhysicsEnabled(final boolean enabled) { public void setPhysicsEnabled(final boolean enabled) {
enqueue(new Callable() { enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
if (enabled) { if (enabled) {
if (physicsState == null) { if (physicsState == null) {

@ -54,6 +54,7 @@ public class SceneRequest {
private boolean displayed = false; private boolean displayed = false;
private DataObject dataObject; private DataObject dataObject;
private HelpCtx helpCtx; private HelpCtx helpCtx;
private FakeApplication fakeApp;
public SceneRequest(Object requester, JmeNode rootNode, ProjectAssetManager manager) { public SceneRequest(Object requester, JmeNode rootNode, ProjectAssetManager manager) {
this.requester = requester; this.requester = requester;
@ -175,4 +176,13 @@ public class SceneRequest {
public void setHelpCtx(HelpCtx helpCtx) { public void setHelpCtx(HelpCtx helpCtx) {
this.helpCtx = helpCtx; this.helpCtx = helpCtx;
} }
public void setFakeApp(FakeApplication fakeApp) {
this.fakeApp = fakeApp;
}
public FakeApplication getFakeApp() {
return fakeApp;
}
} }

Loading…
Cancel
Save