FormatConverterController.java
package com.github.celldynamics.quimp.filesystem.converter;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import com.github.celldynamics.quimp.QuimpException;
import com.github.celldynamics.quimp.QuimpException.MessageSinkTypes;
import com.github.celldynamics.quimp.filesystem.FileDialogEx;
import com.github.celldynamics.quimp.filesystem.FileExtensions;
import com.github.celldynamics.quimp.filesystem.QconfLoader;
import com.github.celldynamics.quimp.plugin.AbstractPluginTemplate;
import com.github.celldynamics.quimp.plugin.QuimpPluginException;
import com.github.celldynamics.quimp.plugin.qanalysis.STmap;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import ij.IJ;
import ij.io.OpenDialog;
/**
* Performs conversion actions. UI interface to {@link FormatConverter}
*
* @author p.baniukiewicz
* @see FormatConverterUi
*/
public class FormatConverterController extends AbstractPluginTemplate {
private FormatConverterUi view;
private FormatConverter fc;
private static String thisPluginName = "Format converter";
/**
* Default constructor.
*/
public FormatConverterController() {
super(new FormatConverterModel(), thisPluginName);
fc = new FormatConverter();
FormatConverterModel model = (FormatConverterModel) options;
view = new FormatConverterUi(model);
view.getOkButton().addActionListener(new GenerateActionListener());
view.getLoadButton().addActionListener(new LoadActionListener());
view.getConvertButton().addActionListener(new ConvertActionListener());
view.getCancelButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
view.dispose();
}
});
}
/**
* Constructor allowing passing file to process.
*
* @param fileToLoad to process
* @see FormatConverter#doConversion()
* @see #getModel()
*/
public FormatConverterController(Path fileToLoad) {
this();
FormatConverterModel model = (FormatConverterModel) options;
model.paramFile = fileToLoad.toString();
}
/*
* (non-Javadoc)
*
* @see com.github.celldynamics.quimp.plugin.AbstractPluginTemplate#executer(java.lang.String)
*/
@Override
protected void executer() throws QuimpException {
super.executer();
FormatConverterModel model = (FormatConverterModel) options;
if (model.getStatus().isEmpty()) {
runPluginConversion();
} else {
runPluginExtraction();
}
}
/**
* Run in convert mode.
*
* @throws QuimpException QuimpException
*/
private void runPluginConversion() throws QuimpException {
FormatConverterModel model = (FormatConverterModel) options;
fc.attachFile(new File(model.paramFile));
fc.doConversion();
publishMacroString(thisPluginName);
}
/**
* Run in QCONF extraction mode.
*
* @throws QuimpException on file load error
*/
private void runPluginExtraction() throws QuimpException {
FormatConverterModel model = (FormatConverterModel) options;
fc.attachFile(new File(model.paramFile));
saveDataFiles();
publishMacroString(thisPluginName);
}
/**
* Get model and allow to set own configuration in no-gui mode.
*
* @return the model
*/
public FormatConverterModel getModel() {
FormatConverterModel model = (FormatConverterModel) options;
return model;
}
/**
* Re-initialises logger to log event>=INFO to internal console hiding them from stdout.
*
* <p>If logging level is less than INFO, all messages end in console as well. By default Fiji
* sets level to INFO, any external configuration (e.g. quimp-logback.xml) will produce logs in
* stdout
*/
private void initializeLogger() {
LoggerContext lc = FormatConverter.logger.getLoggerContext();
MyAppender myAppender = new MyAppender();
myAppender.setContext(lc);
myAppender.setName("internalr");
ThresholdFilter th = new ThresholdFilter();
th.setLevel(Level.INFO.toString()); // above info pass, below hide
th.start();
myAppender.addFilter(th);
myAppender.start();
FormatConverter.logger.addAppender(myAppender);
// trick to prevent doubling logs in windows and console (for normal debug state)
if (FormatConverter.logger.getEffectiveLevel().isGreaterOrEqual(Level.INFO)) {
FormatConverter.logger.setAdditive(false);
} // otherwise if debug set below INFO, all will be doubled (but in this window only those
// >=INFO, Console will capture everything)
}
/**
* Handle Load button.
*
* @author p.baniukiewicz
*
*/
private class LoadActionListener implements ActionListener {
FormatConverterModel model = (FormatConverterModel) options;
@Override
public void actionPerformed(ActionEvent e) {
FileDialogEx od = new FileDialogEx(IJ.getInstance());
od.setDirectory(OpenDialog.getLastDirectory());
od.setExtension(FileExtensions.newConfigFileExt);
if (od.showOpenDialog() == null) {
return;
}
try {
FormatConverter.logger
.info("-------------------------------------------------------------------------");
model.paramFile = od.getPath().toString();
fc.attachFile(od.getPath().toFile());
FormatConverter.logger.info(fc.toString());
} catch (QuimpException e1) {
e1.logger.addAppender(FormatConverter.logger.getAppender("internalr"));
e1.logger.setAdditive(false); // show only in appender
e1.setMessageSinkType(MessageSinkTypes.CONSOLE);
e1.handleException(null, "File could not be loaded.");
}
}
}
/**
* Handle Convert button.
*
* @author p.baniukiewicz
*
*/
private class ConvertActionListener implements ActionListener {
FormatConverterModel model = (FormatConverterModel) options;
@Override
public void actionPerformed(ActionEvent e) {
FileDialogEx od = new FileDialogEx(IJ.getInstance());
od.setDirectory(OpenDialog.getLastDirectory());
od.setExtension(FileExtensions.newConfigFileExt, FileExtensions.configFileExt);
if (od.showOpenDialog() == null) {
return;
}
try {
FormatConverter.logger
.info("-------------------------------------------------------------------------");
// this will clear UI and clear status list as well. Empty status list stands for conversion
view.setUiElements(false);
model.paramFile = od.getPath().toString();
runPluginConversion(); // run in convert mode - status clear
} catch (QuimpException e1) {
e1.logger.addAppender(FormatConverter.logger.getAppender("internalr"));
e1.logger.setAdditive(false); // show only in appender
e1.setMessageSinkType(MessageSinkTypes.CONSOLE);
e1.handleException(null, "File could not be converted.");
}
}
}
/**
* Handle Generate button.
*
* @author p.baniukiewicz
*
*/
private class GenerateActionListener implements ActionListener {
/*
* (non-Javadoc)
*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
if (fc.isFileLoaded() == QconfLoader.QCONF_INVALID) {
FormatConverter.logger.error("Load valid QCONF file first");
return;
}
try {
FormatConverter.logger.info("Generating data...");
runPluginExtraction();
} catch (QuimpException e1) {
e1.logger.addAppender(FormatConverter.logger.getAppender("internalr"));
e1.logger.setAdditive(false); // show only in appender
e1.setMessageSinkType(MessageSinkTypes.CONSOLE);
e1.handleException(null, "File could not be converted.");
}
}
}
/**
* Save data selected in {@link FormatConverterModel}.
*
* @throws QuimpException
*
* @see FormatConverterModel#getStatus()
* @see FormatConverterUi
*/
public void saveDataFiles() throws QuimpException {
FormatConverterModel model = (FormatConverterModel) options;
List<String> status = model.getStatus();
FormatConverter.logger.debug(status.toString());
for (String s : status) {
FormatConverter.logger.info("Saving " + s);
switch (s.toLowerCase()) { // if user provide in other case
case FormatConverterUi.MAP_MOTILITY: // this is also String displayed on control
fc.saveMaps(STmap.MOTILITY);
break;
case FormatConverterUi.MAP_CONVEXITY:
fc.saveMaps(STmap.CONVEXITY);
break;
case FormatConverterUi.MAP_COORD:
fc.saveMaps(STmap.COORD);
break;
case FormatConverterUi.MAP_FLUORES:
fc.saveMaps(STmap.ALLFLU);
break;
case FormatConverterUi.MAP_ORIGIN:
fc.saveMaps(STmap.ORIGIN);
break;
case FormatConverterUi.MAP_X_COORDS:
fc.saveMaps(STmap.XMAP);
break;
case FormatConverterUi.MAP_Y_COORDS:
fc.saveMaps(STmap.YMAP);
break;
case FormatConverterUi.BOA_CENTROID:
fc.saveBoaCentroids();
break;
case FormatConverterUi.BOA_SNAKES:
fc.saveBoaSnakes(view.getChckbxMultiFileOutput());
break;
case FormatConverterUi.ECMM_CENTROID:
fc.saveEcmmCentroids();
break;
case FormatConverterUi.ECCM_OUTLINES:
fc.saveEcmmOutlines(view.getChckbxMultiFileOutput());
break;
case FormatConverterUi.STATS_FLUORES:
fc.saveStatFluores();
break;
case FormatConverterUi.STATS_GEOMETRIC:
fc.saveStatGeom();
break;
case FormatConverterUi.STATS_Q11:
fc.saveStats();
break;
default:
FormatConverter.logger.warn("Parameter " + s + " is inproper");
}
}
}
/**
* Redirect log events to application window. Type errors and warns in red.
*
* @author p.baniukiewicz
*
*/
private class MyAppender extends AppenderBase<ILoggingEvent> {
@Override
protected void append(ILoggingEvent arg0) {
StyleContext sc = StyleContext.getDefaultStyleContext();
StyledDocument doc = view.getInfoText().getStyledDocument();
Color textColor = Color.BLACK;
if (arg0.getLevel().isGreaterOrEqual(Level.WARN)) {
textColor = Color.RED;
}
AttributeSet aset =
sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, textColor);
String message = arg0.getMessage() + '\n';
try {
// fake space simulation
doc.insertString(doc.getLength(), message.replace("\t", "... "), aset);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
@Override
public void showUi(boolean val) throws Exception {
initializeLogger(); // redirect log only for UI
view.setVisible(val);
}
/*
* (non-Javadoc)
*
* @see com.github.celldynamics.quimp.plugin.IQuimpPlugin#about()
*/
@Override
public String about() {
return "Format conversion Plugin.\n" + "Author: Piotr Baniukiewicz\n"
+ "mail: p.baniukiewicz@warwick.ac.uk";
}
/*
* (non-Javadoc)
*
* @see com.github.celldynamics.quimp.plugin.AbstractPluginTemplate#runPlugin()
*/
@Override
protected void runPlugin() throws QuimpPluginException {
}
}