JAL-3048 allow a chain of responses for a particular response code (needed when inter...
[jalview.git] / src / jalview / util / dialogrunner / DialogRunner.java
index fc1a73d..b631128 100644 (file)
@@ -39,7 +39,7 @@ import java.util.Map;
 public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
 {
 
-  private Map<Response, RunResponse> callbacks = new java.util.HashMap<>();
+  private Map<Response, List<RunResponse>> callbacks = new java.util.HashMap<>();
 
   public T dialog;
 
@@ -54,9 +54,12 @@ public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
    */
   public void resetResponses()
   {
-    for (RunResponse response : callbacks.values())
+    for (List<RunResponse> lr : callbacks.values())
     {
-      response.reset();
+      for (RunResponse response : lr)
+      {
+        response.reset();
+      }
     }
     responses.clear();
     firstRunWasCalled = false;
@@ -65,11 +68,59 @@ public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
   @Override
   public T response(RunResponse action)
   {
-    callbacks.put(action.ourTrigger, action);
+    return addResponse(false, action);
+  }
+
+  /**
+   * insert a response at the beginning of the chain for the action. Useful to add
+   * pre-action validations local to the Dialog class
+   * 
+   * @param action
+   * @return
+   */
+  public T firstResponse(RunResponse action)
+  {
+    return addResponse(true, action);
+  }
+
+  protected T addResponse(boolean prePend, RunResponse action)
+  {
+    List<RunResponse> laction = callbacks.get(action.ourTrigger);
+    if (laction == null)
+    {
+      laction = new ArrayList<>();
+      callbacks.put(action.ourTrigger, laction);
+    }
+    if (prePend)
+    {
+      laction.add(0,action);
+    } else {
+      laction.add(action);
+    }
     return dialog;
   }
 
   /**
+   * 
+   * @param action
+   * @return true if action is a registered callback
+   */
+  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
@@ -125,24 +176,36 @@ public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
   private void run(Response response)
   {
     responses.add(response);
-    RunResponse action = callbacks.get(response);
-    if (action == null)
+    List<RunResponse> laction = callbacks.get(response);
+
+    if (laction == null)
     {
       System.err.println("Doing nothing for " + response);
       return;
     }
-    if (action.wasRun)
+    boolean wasRun = false;
+    int num = 0;
+    for (RunResponse action : laction)
     {
-      System.err
-              .println("IMPLEMENTATION ERROR: Cycle in DialogRunner ! for "
-                      + action);
+      num++;
+      // find next action to execute
+      if (!action.wasRun)
+      {
+        System.err
+                .println("Executing action (" + num + ") for " + response);
+        wasRun = true;
+        action.wasRun = true;
+        action.run();
+        if (action.returned != null)
+        {
+          run(action.returned);
+        }
+        break;
+      }
     }
-    System.err.println("Executing action for " + response);
-    action.wasRun = true;
-    action.run();
-    if (action.returned != null)
+    if (!wasRun)
     {
-      run(action.returned);
+      System.err.println("Did nothing for " + response);
     }
   }