package jalview.util.dialogrunner;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
* the actual dialog that will be shown - which will also initiate the
* response chain.
*/
-public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
+public class DialogRunner implements DialogRunnerI
{
+ private Map<Object, List<RunResponse>> callbacks = new HashMap<>();
- private Map<Response, List<RunResponse>> callbacks = new java.util.HashMap<>();
+ private boolean firstRunWasCalled = false;
- public T dialog;
-
- public DialogRunner(T ourDialog)
+ /**
+ * Constructor
+ */
+ public DialogRunner()
{
- dialog = ourDialog;
}
/**
- * clear all 'was ran' flags so responses can be called again, and firstRun will
- * trigger response execution
+ * Reset so handleResponse will start response execution
*/
public void resetResponses()
{
- for (List<RunResponse> lr : callbacks.values())
- {
- for (RunResponse response : lr)
- {
- response.reset();
- }
- }
- responses.clear();
- if (defaultResponse != null)
- {
- defaultResponse.reset();
- }
firstRunWasCalled = false;
}
@Override
- public T addResponse(RunResponse action)
+ public DialogRunnerI addResponse(RunResponse action)
{
- return addResponse(false, action);
+ addResponse(false, action);
+ return this;
}
/**
* @param action
* @return
*/
- public T firstResponse(RunResponse action)
+ public DialogRunnerI setFirstResponse(RunResponse action)
{
return addResponse(true, action);
}
- protected T addResponse(boolean prePend, RunResponse action)
+ protected DialogRunnerI addResponse(boolean prePend, RunResponse action)
{
- List<RunResponse> laction = callbacks.get(action.ourTrigger);
- if (laction == null)
+ List<RunResponse> actions = callbacks.get(action.getTrigger());
+ if (actions == null)
{
- laction = new ArrayList<>();
- callbacks.put(action.ourTrigger, laction);
+ actions = new ArrayList<>();
+ callbacks.put(action.getTrigger(), actions);
}
if (prePend)
{
- laction.add(0,action);
+ actions.add(0,action);
} else {
- laction.add(action);
+ actions.add(action);
}
- return dialog;
+ return this;
}
/**
*/
public boolean isRegistered(RunResponse action)
{
- List<RunResponse> resp = callbacks.get(action.ourTrigger);
- if (resp != null)
- {
- for (RunResponse r : resp)
- {
- if (r == action)
- {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * handle a response
- *
- * @param responseCode
- */
- public void run(int responseCode)
- {
- run(new Response(responseCode));
- }
-
- public void run(String responseString)
- {
- run(new Response(responseString));
- }
-
- public void run(Object responseObj)
- {
- run(new Response(responseObj));
+ List<RunResponse> resp = callbacks.get(action.getTrigger());
+ return resp != null && resp.contains(action);
}
/**
- * start of response handling.
+ * Handles a response by running the chain of registered actions (if any).
+ * Answers the list of responses run (in order).
*
- * @param responseCode
+ * @param response
*/
- public void firstRun(int responseCode)
- {
- doFirstRun(new Response(responseCode));
- }
-
- public void firstRun(String responseString)
+ @Override
+ public List<RunResponse> handleResponse(Object response)
{
- doFirstRun(new Response(responseString));
- }
+ List<RunResponse> responsesRun = new ArrayList<RunResponse>();
- public void firstRun(Object responseObj)
- {
- if (responseObj != null && !responseObj.equals(responseObj))
+ /*
+ * this test is for NaN in Chrome
+ */
+ if (response != null && !response.equals(response))
{
- // NaN is an object in Chrome - catch this weirdness
- // this so we don't cause issues later
- return;
+ return responsesRun;
}
- doFirstRun(new Response(responseObj));
- }
-
-
- boolean firstRunWasCalled = false;
-
- private void doFirstRun(Response response)
- {
+
+ /*
+ * failsafe check for illegal duplicate call(?)
+ */
if (firstRunWasCalled)
{
- return;
+// return responsesRun;
}
firstRunWasCalled = true;
- run(response);
+
+ runResponse(response, responsesRun);
+ if (responsesRun.isEmpty())
+ {
+ System.err.println("Did nothing for " + response);
+ }
+
+ return responsesRun;
}
- private void run(Response response)
+ /**
+ * Runs any response handlers registered for the given response. If any
+ * response provides a return value, then the handler for that value is
+ * run next recursively. Handlers are only run once.
+ *
+ * @param response
+ * @param alreadyRun
+ */
+ private void runResponse(Object response, List<RunResponse> alreadyRun)
{
- if (response.objresp != null
- && !response.objresp.equals(response.objresp))
+ /*
+ * this test is for NaN in Chrome
+ */
+ if (response != null && !response.equals(response))
{
- // NaN is an object in Chrome - catch this weirdness
- // this so we don't cause issues later
return;
}
- responses.add(response);
- List<RunResponse> laction = response.isNull() ? null : callbacks.get(response);
+ List<RunResponse> actions = response == null ? null : callbacks.get(response);
- if (laction == null)
+ if (actions == null)
{
- if (defaultResponse != null)
- {
- defaultResponse.ourTrigger = response;
- defaultResponse.wasRun = true;
- defaultResponse.run();
- }
- else
- {
- System.err.println("Doing nothing for " + response);
- }
+ System.err.println("Doing nothing for " + response);
return;
}
- boolean wasRun = false;
- int num = 0;
- for (RunResponse action : laction)
+ for (RunResponse action : actions)
{
- num++;
- // find next action to execute
- if (!action.wasRun)
+ if (!alreadyRun.contains(action))
{
- System.err
- .println("Executing action (" + num + ") for " + response);
- wasRun = true;
- action.wasRun = true;
+ action.setReturnValue(null);
action.run();
- if (action.returned != null)
+ alreadyRun.add(action);
+ Object returnValue = action.getReturnValue();
+ if (returnValue != null)
{
- run(action.returned);
+ /*
+ * RunResponse wants to chain another action
+ */
+ runResponse(returnValue, alreadyRun);
}
break;
}
}
- if (!wasRun)
- {
- System.err.println("Did nothing for " + response);
- }
- }
-
- List<Response> responses = new ArrayList<>();
-
- RunResponse defaultResponse = null;
-
- /**
- * Convenience wrapper for setting default response to a runnable
- *
- * @param runnable
- */
- public void setDefaultResponse(Runnable runnable)
- {
- defaultResponse = new RunResponse(runnable)
- {
- @Override
- public void run()
- {
- runnable.run();
- }
- };
- }
-
- /**
- * Default responses are called once, with ourTrigger set to the unHandled
- * response received
- *
- * @param runnable
- */
- public void setDefaultResponse(RunResponse runnable)
- {
- defaultResponse = runnable;
}
}