/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.util.dialogrunner; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * daft gymnastics to allow Dialogs to extend from a Swing class and use this * class to implement chained Response run() definition and execution. * * There is probably a better way of doing this. * * @author jprocter * * @param * the actual dialog that will be shown - which will also initiate the * response chain. */ public class DialogRunner implements DialogRunnerI { private Map> callbacks = new java.util.HashMap<>(); public T dialog; public DialogRunner(T ourDialog) { dialog = ourDialog; } /** * clear all 'was ran' flags so responses can be called again, and firstRun will * trigger response execution */ public void resetResponses() { for (List lr : callbacks.values()) { for (RunResponse response : lr) { response.reset(); } } responses.clear(); if (defaultResponse != null) { defaultResponse.reset(); } firstRunWasCalled = false; } @Override public T response(RunResponse 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 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 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)); } /** * start of response handling. * * @param responseCode */ public void firstRun(int responseCode) { doFirstRun(new Response(responseCode)); } public void firstRun(String responseString) { doFirstRun(new Response(responseString)); } public void firstRun(Object responseObj) { if (responseObj != null && !responseObj.equals(responseObj)) { // NaN is an object in Chrome - catch this weirdness // this so we don't cause issues later return; } doFirstRun(new Response(responseObj)); } boolean firstRunWasCalled = false; private void doFirstRun(Response response) { if (firstRunWasCalled) { return; } firstRunWasCalled = true; run(response); } private void run(Response response) { if (response.objresp != null && !response.objresp.equals(response.objresp)) { // NaN is an object in Chrome - catch this weirdness // this so we don't cause issues later return; } responses.add(response); List laction = response.isNull() ? null : callbacks.get(response); if (laction == null) { if (defaultResponse != null) { defaultResponse.ourTrigger = response; defaultResponse.wasRun = true; defaultResponse.run(); } else { System.err.println("Doing nothing for " + response); } return; } boolean wasRun = false; int num = 0; for (RunResponse action : laction) { 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; } } if (!wasRun) { System.err.println("Did nothing for " + response); } } List 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; } }