/*
* 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;
}
}