package org.egonet.gui.wholenet;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.io.*;
import java.util.*;
import net.miginfocom.swing.MigLayout;
import org.egonet.io.InterviewFileFilter;
import org.egonet.io.InterviewReader;
import org.egonet.model.Interview;
import org.egonet.model.Study;
import org.egonet.util.CatchingAction;
import org.egonet.util.SwingWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InterviewFileSelectionFrame extends JFrame {
final private static Logger logger = LoggerFactory.getLogger(InterviewFileSelectionFrame.class);
private final Study study;
private final File studyFile;
private JList<File> interviewList;
final InterviewFileFilter filter;
public InterviewFileSelectionFrame(final File studyFile, final Study study) throws HeadlessException {
this(studyFile, study, "Select interviews to include in whole network analysis");
}
public InterviewFileSelectionFrame(final File studyFile, final Study study, String title) throws HeadlessException {
super(title);
this.studyFile = studyFile;
this.study = study;
this.filter = new InterviewFileFilter(study, "Interview Files", "int");
logger.info("Building interview file selection frame");
build();
}
private void build() {
BorderLayout layout = new BorderLayout();
setLayout(layout);
interviewList = new JList<File>();
DefaultListCellRenderer cellRenderer = new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if(value instanceof File) {
File fValue = (File)value;
value = fValue.toString().replace(studyFile.getParent().toString(), "");
}
return super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
}
};
interviewList.setCellRenderer(cellRenderer);
JScrollPane interviewScroller = new JScrollPane(interviewList);
add(interviewScroller, BorderLayout.CENTER);
JPanel fileButtonPanel = new JPanel();
MigLayout vertical = new MigLayout("flowy,fill");
fileButtonPanel.setLayout(vertical);
Action addFileAction = new CatchingAction("Add interview file") {
@Override
public void safeActionPerformed(ActionEvent e) throws Exception {
addFileAction();
}
};
fileButtonPanel.add(new JButton(addFileAction), "growx, sg 1");
Action addDirectoryAction = new CatchingAction("Add directory") {
@Override
public void safeActionPerformed(ActionEvent e) throws Exception {
addDirectoryAction();
}
};
fileButtonPanel.add(new JButton(addDirectoryAction), "growx, sg 1");
Action removeFileAction = new CatchingAction("Remove selected") {
@Override
public void safeActionPerformed(ActionEvent e) throws Exception {
removeFileAction();
}
};
fileButtonPanel.add(new JButton(removeFileAction), "growx, sg 1");
add(fileButtonPanel, BorderLayout.WEST);
List<File> files = getInitialFiles(studyFile.getParentFile());
interviewList.setModel(new InterviewFileListModel(files));
JPanel cancelNextButtonPanel = new JPanel();
MigLayout horiz = new MigLayout("flowx,fill","center");
cancelNextButtonPanel.setLayout(horiz);
Action cancelAction = new CatchingAction("Cancel") {
@Override
public void safeActionPerformed(ActionEvent e) throws Exception {
dispose();
}
};
cancelNextButtonPanel.add(new JButton(cancelAction), "growx, sg 2");
Action nextAction = new CatchingAction("Continue") {
@Override
public void safeActionPerformed(ActionEvent e) throws Exception {
final InterviewFileListModel model = (InterviewFileListModel)interviewList.getModel();
SwingWorker sw = new SwingWorker() {
NameMapperFrame frame;
@Override
public Object construct() {
List<File> mappableFiles = new ArrayList<File>();
for(Object f : model.toArray())
mappableFiles.add((File)f);
frame = new NameMapperFrame(study, studyFile, mappableFiles);
return frame;
}
@Override
public void finished() {
frame.setVisible(true);
}
};
sw.start();
dispose();
}
};
cancelNextButtonPanel.add(new JButton(nextAction), "growx, sg 2");
add(cancelNextButtonPanel, BorderLayout.SOUTH);
pack();
}
protected void removeFileAction() {
int[] selected = interviewList.getSelectedIndices();
if(selected.length > 0) {
InterviewFileListModel newModel = new InterviewFileListModel();
ListModel<File> model = interviewList.getModel();
for(int i = 0; i < model.getSize(); i++) {
File item = model.getElementAt(i);
boolean remove = false;
for(int j = 0; j < selected.length; j++) {
if(selected[j] == i)
remove = true;
}
if(!remove)
newModel.addElement(item);
}
interviewList.setModel(newModel);
}
}
protected void addDirectoryAction() {
JFileChooser jfc = new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
jfc.setMultiSelectionEnabled(false);
int c = jfc.showOpenDialog(this);
if(c == JFileChooser.CANCEL_OPTION)
return;
InterviewFileListModel model = (InterviewFileListModel)interviewList.getModel();
File selected = jfc.getSelectedFile();
if(selected != null && selected.isDirectory()) {
List<File> results = getInitialFiles(selected);
for(File result : results) {
logger.info("Possible new file " + result.getName());
if(!model.contains(result))
model.addElement(result);
}
}
}
protected void addFileAction() {
JFileChooser jfc = new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
jfc.setFileFilter(filter);
jfc.setMultiSelectionEnabled(true);
int c = jfc.showOpenDialog(this);
if(c == JFileChooser.CANCEL_OPTION)
return;
InterviewFileListModel model = (InterviewFileListModel)interviewList.getModel();
File [] selected = jfc.getSelectedFiles();
for(File result : selected) {
if(!model.contains(result))
model.addElement(result);
}
}
private boolean validFile(File candidate) {
boolean shouldRead = candidate.isFile() && candidate.canRead() && filter.accept(candidate);
if(!shouldRead) {
// it didn't match for some reason
//logger.info("Couldn't read or wasn't accepted by filter: " + candidate.getName());
return false;
}
try {
InterviewReader reader = new InterviewReader(study, candidate);
Interview interview = reader.getInterview();
if(!interview.isComplete()) {
//logger.info("Interview wasn't completed: " + candidate.getName());
return false;
}
} catch (Exception ex) {
//logger.info("Exception reading: " + candidate.getName());
return false;
}
return true;
}
private List<File> getInitialFiles(File directory) {
List<File> output = new ArrayList<File>();
if(!directory.isDirectory()) {
logger.info("Asked to scan a directory for whole network files, but the argument wasn't a directory: " + directory);
return output;
}
List<File> files = new ArrayList<File>();
files.add(directory);
while(files.size() > 0) {
File candidate = files.remove(0);
if(candidate.isDirectory()) {
for(File subfile : candidate.listFiles()) {
files.add(subfile);
}
continue;
}
if(validFile(candidate)) {
output.add(candidate);
logger.info("I'd try to use candidate file " + candidate.getName());
}
else {
logger.info("I'd skip file " + candidate.getName());
}
}
if(output.size() <= 0)
logger.info("No files found for whole network analysis; you may have to add your own");
return output;
}
public Study getStudy() {
return study;
}
public File getStudyFile() {
return studyFile;
}
public class InterviewFileListModel extends DefaultListModel<File> {
public InterviewFileListModel() {
super();
}
public InterviewFileListModel(List<File> files) {
super();
for(File f : files)
addElement(f);
}
}
}