From b565b212dc5244aeab2fed977d25392e50411b59 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 27 Sep 2024 14:01:50 -0400 Subject: [PATCH 1/9] Initial Attempt At Loading Factory and Event Listeners --- .../java/org/vcell/N5/LoadingFactory.java | 107 ++++++++++++++++++ .../java/org/vcell/N5/N5ImageHandler.java | 1 + .../java/org/vcell/N5/SimResultsLoader.java | 81 +------------ .../java/org/vcell/N5/UI/ImageIntoMemory.java | 2 +- .../java/org/vcell/N5/UI/N5ExportTable.java | 23 ++-- .../org/vcell/N5/UI/RemoteFileSelection.java | 3 +- .../vcell/N5/UI/SimLoadingEventCreator.java | 14 +++ .../org/vcell/N5/UI/SimLoadingListener.java | 11 ++ 8 files changed, 154 insertions(+), 88 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java new file mode 100644 index 0000000..23a9247 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java @@ -0,0 +1,107 @@ +package org.vcell.N5; + +import ij.ImagePlus; +import org.vcell.N5.UI.ImageIntoMemory; +import org.vcell.N5.UI.N5ExportTable; +import org.vcell.N5.UI.SimLoadingEventCreator; +import org.vcell.N5.UI.SimLoadingListener; + +import javax.swing.*; +import javax.swing.event.EventListenerList; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +public class LoadingFactory implements SimLoadingEventCreator{ + private static final EventListenerList eventListenerList = new EventListenerList(); + + public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ + N5ExportTable.enableCriticalButtons(false); + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + Thread openN5FileDataset = new Thread(() -> { + try{ + for(SimResultsLoader simResultsLoader: filesToOpen){ + simResultsLoader.createS3ClientAndReader(); + ImageIntoMemory imageIntoMemory; + if (openInMemory){ + ArrayList dimensions = simResultsLoader.getN5Dimensions(); + imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader); + imageIntoMemory.displayRangeMenu(); + } else{ + ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + imagePlus.show(); + } + + } + } catch (Exception ex) { + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + N5ExportTable.enableCriticalButtons(true); + throw new RuntimeException(ex); + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (!openInMemory) { + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + N5ExportTable.enableCriticalButtons(true); + } + } + }); + } + }); + openN5FileDataset.setName("Open N5 File"); + openN5FileDataset.start(); + } + + public void openLocalN5FS(ArrayList filesToOpen){ + N5ExportTable.enableCriticalButtons(true); + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setAcceptAllFileFilterUsed(false); + int result = fileChooser.showOpenDialog(null); + if (result == JFileChooser.APPROVE_OPTION){ + File file = fileChooser.getSelectedFile(); + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + Thread openN5FileDataset = new Thread(() -> { + try{ + for(SimResultsLoader simResultsLoader: filesToOpen){ + simResultsLoader.setSelectedLocalFile(file); + ImagePlus imagePlus = simResultsLoader.getImgPlusFromLocalN5File(); + imagePlus.show(); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + N5ExportTable.enableCriticalButtons(true); + } + }); + } + }); + openN5FileDataset.start(); + } + } + + @Override + public void addSimLoadingListener(SimLoadingListener simLoadingListener) { + eventListenerList.add(SimLoadingListener.class, simLoadingListener); + } + + @Override + public void notifySimIsLoading(SimResultsLoader simResultsLoader) { + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + simLoadingListener.simIsLoading(simResultsLoader.rowNumber); + } + } + + @Override + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber); + } + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index 3a9a14e..e69e1cf 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -35,6 +35,7 @@ public class N5ImageHandler implements Command { public static N5ExportTable exportTable; public static String exportedMetaDataPath = System.getProperty("user.home") + "/.vcell/exportMetaData.json"; private static ExportDataRepresentation.FormatExportDataRepresentation exampleJSONData; + public final static LoadingFactory loadingFactory = new LoadingFactory(); @Override public void run() { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java index bcebbaf..890ef62 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java @@ -10,7 +10,6 @@ import com.google.gson.GsonBuilder; import ij.ImagePlus; import ij.plugin.ContrastEnhancer; -import ij.plugin.frame.ContrastAdjuster; import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; import net.imglib2.type.numeric.real.DoubleType; @@ -24,14 +23,10 @@ import org.janelia.saalfeldlab.n5.imglib2.N5Utils; import org.janelia.saalfeldlab.n5.s3.N5AmazonS3Reader; import org.scijava.log.Logger; -import org.vcell.N5.UI.N5ExportTable; -import org.vcell.N5.UI.ImageIntoMemory; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; -import javax.swing.*; -import java.awt.*; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -57,9 +52,14 @@ public class SimResultsLoader { private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public static AmazonS3ClientBuilder s3ClientBuilder; + public int rowNumber; public SimResultsLoader(){ + } + public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber){ + this(stringURI, userSetFileName); + this.rowNumber = rowNumber; } public SimResultsLoader(String stringURI, String userSetFileName){ uri = URI.create(stringURI); @@ -164,77 +164,6 @@ public ArrayList getN5Dimensions(){ return n5AmazonS3Reader.getAttribute(dataSetChosen, "dimensions", ArrayList.class); } - - public static void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ - N5ExportTable.enableCriticalButtons(false); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - Thread openN5FileDataset = new Thread(() -> { - try{ - for(SimResultsLoader simResultsLoader: filesToOpen){ - simResultsLoader.createS3ClientAndReader(); - ImageIntoMemory imageIntoMemory; - if (openInMemory){ - ArrayList dimensions = simResultsLoader.getN5Dimensions(); - imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader); - imageIntoMemory.displayRangeMenu(); - } else{ - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - imagePlus.show(); - } - - } - } catch (Exception ex) { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); - throw new RuntimeException(ex); - } finally { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (!openInMemory) { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); - } - } - }); - } - }); - openN5FileDataset.setName("Open N5 File"); - openN5FileDataset.start(); - } - - public static void openLocalN5FS(ArrayList filesToOpen){ - N5ExportTable.enableCriticalButtons(true); - JFileChooser fileChooser = new JFileChooser(); - fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - fileChooser.setAcceptAllFileFilterUsed(false); - int result = fileChooser.showOpenDialog(null); - if (result == JFileChooser.APPROVE_OPTION){ - File file = fileChooser.getSelectedFile(); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - Thread openN5FileDataset = new Thread(() -> { - try{ - for(SimResultsLoader simResultsLoader: filesToOpen){ - simResultsLoader.setSelectedLocalFile(file); - ImagePlus imagePlus = simResultsLoader.getImgPlusFromLocalN5File(); - imagePlus.show(); - } - } catch (IOException ex) { - throw new RuntimeException(ex); - } finally { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); - } - }); - } - }); - openN5FileDataset.start(); - } - } - void setDataSetChosen(String dataSetChosen) { this.dataSetChosen = dataSetChosen; } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java index 3735deb..f89a327 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java @@ -15,7 +15,7 @@ import java.awt.event.FocusEvent; import java.io.IOException; -public class ImageIntoMemory extends EventListenerList implements ActionListener { +public class ImageIntoMemory implements ActionListener { public int startC; public int endC; public int startT; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 08d8dbf..8348bf5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -1,14 +1,8 @@ package org.vcell.N5.UI; -import ij.ImagePlus; -import net.imglib2.cache.img.CachedCellImg; -import net.imglib2.img.display.imagej.ImageJFunctions; -import net.imglib2.type.numeric.real.DoubleType; -import org.janelia.saalfeldlab.n5.N5FSReader; import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.SimCacheLoader; import org.vcell.N5.SimResultsLoader; import javax.swing.*; @@ -24,7 +18,6 @@ import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; import java.io.FileNotFoundException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -32,7 +25,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; -public class N5ExportTable implements ActionListener, ListSelectionListener { +public class N5ExportTable implements ActionListener, ListSelectionListener, SimLoadingListener { public static JDialog exportTableDialog; private N5ExportTableModel n5ExportTableModel; private ParameterTableModel parameterTableModel; @@ -363,7 +356,7 @@ public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName); filesToOpen.add(simResultsLoader); } - SimResultsLoader.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); + N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); } else if (e.getSource().equals(copyLink)) { ExportDataRepresentation.SimulationExportDataRepresentation selectedRow = n5ExportTableModel.getRowData(exportListTable.getSelectedRow()); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); @@ -381,7 +374,7 @@ public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName); filesToOpen.add(simResultsLoader); } - SimResultsLoader.openLocalN5FS(filesToOpen); + N5ImageHandler.loadingFactory.openLocalN5FS(filesToOpen); } else if (e.getSource().equals(includeExampleExports)){ if(includeExampleExports.isSelected()){ @@ -429,6 +422,16 @@ public void valueChanged(ListSelectionEvent e) { parameterTable.updateUI(); } + @Override + public void simIsLoading(int itemRow) { + + } + + @Override + public void simFinishedLoading(int itemRow) { + + } + static class ParameterTableModel extends AbstractTableModel{ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index be90e61..84823c5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -1,5 +1,6 @@ package org.vcell.N5.UI; +import org.vcell.N5.N5ImageHandler; import org.vcell.N5.SimResultsLoader; import javax.swing.*; @@ -95,7 +96,7 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), ""); - SimResultsLoader.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, N5ExportTable.openInMemory.isSelected()); + N5ImageHandler.loadingFactory.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, N5ExportTable.openInMemory.isSelected()); this.setVisible(false); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java new file mode 100644 index 0000000..fcb6538 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java @@ -0,0 +1,14 @@ +package org.vcell.N5.UI; + +import org.vcell.N5.SimResultsLoader; + +import javax.swing.event.EventListenerList; + +public interface SimLoadingEventCreator { + public void addSimLoadingListener(SimLoadingListener simLoadingListener); + + public void notifySimIsLoading(SimResultsLoader simResultsLoader); + + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader); + +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java new file mode 100644 index 0000000..c5a0ea7 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java @@ -0,0 +1,11 @@ +package org.vcell.N5.UI; + +import java.util.EventListener; + +public interface SimLoadingListener extends EventListener { + + public void simIsLoading(int itemRow); + + public void simFinishedLoading(int itemRow); + +} From b017a0a46ad9c61b72286c26e580c82e5949ff67 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 27 Sep 2024 14:01:50 -0400 Subject: [PATCH 2/9] Initial Attempt At Loading Factory and Event Listeners --- .../java/org/vcell/N5/LoadingFactory.java | 107 ++++++++++++++++++ .../java/org/vcell/N5/N5ImageHandler.java | 1 + .../java/org/vcell/N5/SimResultsLoader.java | 81 +------------ .../java/org/vcell/N5/UI/ImageIntoMemory.java | 2 +- .../java/org/vcell/N5/UI/N5ExportTable.java | 23 ++-- .../org/vcell/N5/UI/RemoteFileSelection.java | 3 +- .../vcell/N5/UI/SimLoadingEventCreator.java | 14 +++ .../org/vcell/N5/UI/SimLoadingListener.java | 11 ++ 8 files changed, 154 insertions(+), 88 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java new file mode 100644 index 0000000..23a9247 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java @@ -0,0 +1,107 @@ +package org.vcell.N5; + +import ij.ImagePlus; +import org.vcell.N5.UI.ImageIntoMemory; +import org.vcell.N5.UI.N5ExportTable; +import org.vcell.N5.UI.SimLoadingEventCreator; +import org.vcell.N5.UI.SimLoadingListener; + +import javax.swing.*; +import javax.swing.event.EventListenerList; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +public class LoadingFactory implements SimLoadingEventCreator{ + private static final EventListenerList eventListenerList = new EventListenerList(); + + public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ + N5ExportTable.enableCriticalButtons(false); + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + Thread openN5FileDataset = new Thread(() -> { + try{ + for(SimResultsLoader simResultsLoader: filesToOpen){ + simResultsLoader.createS3ClientAndReader(); + ImageIntoMemory imageIntoMemory; + if (openInMemory){ + ArrayList dimensions = simResultsLoader.getN5Dimensions(); + imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader); + imageIntoMemory.displayRangeMenu(); + } else{ + ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + imagePlus.show(); + } + + } + } catch (Exception ex) { + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + N5ExportTable.enableCriticalButtons(true); + throw new RuntimeException(ex); + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (!openInMemory) { + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + N5ExportTable.enableCriticalButtons(true); + } + } + }); + } + }); + openN5FileDataset.setName("Open N5 File"); + openN5FileDataset.start(); + } + + public void openLocalN5FS(ArrayList filesToOpen){ + N5ExportTable.enableCriticalButtons(true); + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setAcceptAllFileFilterUsed(false); + int result = fileChooser.showOpenDialog(null); + if (result == JFileChooser.APPROVE_OPTION){ + File file = fileChooser.getSelectedFile(); + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + Thread openN5FileDataset = new Thread(() -> { + try{ + for(SimResultsLoader simResultsLoader: filesToOpen){ + simResultsLoader.setSelectedLocalFile(file); + ImagePlus imagePlus = simResultsLoader.getImgPlusFromLocalN5File(); + imagePlus.show(); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + N5ExportTable.enableCriticalButtons(true); + } + }); + } + }); + openN5FileDataset.start(); + } + } + + @Override + public void addSimLoadingListener(SimLoadingListener simLoadingListener) { + eventListenerList.add(SimLoadingListener.class, simLoadingListener); + } + + @Override + public void notifySimIsLoading(SimResultsLoader simResultsLoader) { + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + simLoadingListener.simIsLoading(simResultsLoader.rowNumber); + } + } + + @Override + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber); + } + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index 022da38..4e36b7c 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -35,6 +35,7 @@ public class N5ImageHandler implements Command { public static N5ExportTable exportTable; public static String exportedMetaDataPath = System.getProperty("user.home") + "/.vcell/exportMetaData.json"; private static ExportDataRepresentation.FormatExportDataRepresentation exampleJSONData; + public final static LoadingFactory loadingFactory = new LoadingFactory(); @Override public void run() { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java index 36ff0cb..f0e3356 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java @@ -10,7 +10,6 @@ import com.google.gson.GsonBuilder; import ij.ImagePlus; import ij.plugin.ContrastEnhancer; -import ij.plugin.frame.ContrastAdjuster; import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; import net.imglib2.type.numeric.real.DoubleType; @@ -24,14 +23,10 @@ import org.janelia.saalfeldlab.n5.imglib2.N5Utils; import org.janelia.saalfeldlab.n5.s3.N5AmazonS3Reader; import org.scijava.log.Logger; -import org.vcell.N5.UI.N5ExportTable; -import org.vcell.N5.UI.ImageIntoMemory; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; -import javax.swing.*; -import java.awt.*; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -57,9 +52,14 @@ public class SimResultsLoader { private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public static AmazonS3ClientBuilder s3ClientBuilder; + public int rowNumber; public SimResultsLoader(){ + } + public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber){ + this(stringURI, userSetFileName); + this.rowNumber = rowNumber; } public SimResultsLoader(String stringURI, String userSetFileName){ uri = URI.create(stringURI); @@ -165,77 +165,6 @@ public ArrayList getN5Dimensions(){ return n5AmazonS3Reader.getAttribute(dataSetChosen, "dimensions", ArrayList.class); } - - public static void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ - N5ExportTable.enableCriticalButtons(false); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - Thread openN5FileDataset = new Thread(() -> { - try{ - for(SimResultsLoader simResultsLoader: filesToOpen){ - simResultsLoader.createS3ClientAndReader(); - ImageIntoMemory imageIntoMemory; - if (openInMemory){ - ArrayList dimensions = simResultsLoader.getN5Dimensions(); - imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader); - imageIntoMemory.displayRangeMenu(); - } else{ - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - imagePlus.show(); - } - - } - } catch (Exception ex) { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); - throw new RuntimeException(ex); - } finally { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (!openInMemory) { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); - } - } - }); - } - }); - openN5FileDataset.setName("Open N5 File"); - openN5FileDataset.start(); - } - - public static void openLocalN5FS(ArrayList filesToOpen){ - N5ExportTable.enableCriticalButtons(true); - JFileChooser fileChooser = new JFileChooser(); - fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - fileChooser.setAcceptAllFileFilterUsed(false); - int result = fileChooser.showOpenDialog(null); - if (result == JFileChooser.APPROVE_OPTION){ - File file = fileChooser.getSelectedFile(); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - Thread openN5FileDataset = new Thread(() -> { - try{ - for(SimResultsLoader simResultsLoader: filesToOpen){ - simResultsLoader.setSelectedLocalFile(file); - ImagePlus imagePlus = simResultsLoader.getImgPlusFromLocalN5File(); - imagePlus.show(); - } - } catch (IOException ex) { - throw new RuntimeException(ex); - } finally { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); - } - }); - } - }); - openN5FileDataset.start(); - } - } - void setDataSetChosen(String dataSetChosen) { this.dataSetChosen = dataSetChosen; } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java index 3735deb..f89a327 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java @@ -15,7 +15,7 @@ import java.awt.event.FocusEvent; import java.io.IOException; -public class ImageIntoMemory extends EventListenerList implements ActionListener { +public class ImageIntoMemory implements ActionListener { public int startC; public int endC; public int startT; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 08d8dbf..8348bf5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -1,14 +1,8 @@ package org.vcell.N5.UI; -import ij.ImagePlus; -import net.imglib2.cache.img.CachedCellImg; -import net.imglib2.img.display.imagej.ImageJFunctions; -import net.imglib2.type.numeric.real.DoubleType; -import org.janelia.saalfeldlab.n5.N5FSReader; import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.SimCacheLoader; import org.vcell.N5.SimResultsLoader; import javax.swing.*; @@ -24,7 +18,6 @@ import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; import java.io.FileNotFoundException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -32,7 +25,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; -public class N5ExportTable implements ActionListener, ListSelectionListener { +public class N5ExportTable implements ActionListener, ListSelectionListener, SimLoadingListener { public static JDialog exportTableDialog; private N5ExportTableModel n5ExportTableModel; private ParameterTableModel parameterTableModel; @@ -363,7 +356,7 @@ public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName); filesToOpen.add(simResultsLoader); } - SimResultsLoader.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); + N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); } else if (e.getSource().equals(copyLink)) { ExportDataRepresentation.SimulationExportDataRepresentation selectedRow = n5ExportTableModel.getRowData(exportListTable.getSelectedRow()); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); @@ -381,7 +374,7 @@ public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName); filesToOpen.add(simResultsLoader); } - SimResultsLoader.openLocalN5FS(filesToOpen); + N5ImageHandler.loadingFactory.openLocalN5FS(filesToOpen); } else if (e.getSource().equals(includeExampleExports)){ if(includeExampleExports.isSelected()){ @@ -429,6 +422,16 @@ public void valueChanged(ListSelectionEvent e) { parameterTable.updateUI(); } + @Override + public void simIsLoading(int itemRow) { + + } + + @Override + public void simFinishedLoading(int itemRow) { + + } + static class ParameterTableModel extends AbstractTableModel{ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index be90e61..84823c5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -1,5 +1,6 @@ package org.vcell.N5.UI; +import org.vcell.N5.N5ImageHandler; import org.vcell.N5.SimResultsLoader; import javax.swing.*; @@ -95,7 +96,7 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), ""); - SimResultsLoader.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, N5ExportTable.openInMemory.isSelected()); + N5ImageHandler.loadingFactory.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, N5ExportTable.openInMemory.isSelected()); this.setVisible(false); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java new file mode 100644 index 0000000..fcb6538 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java @@ -0,0 +1,14 @@ +package org.vcell.N5.UI; + +import org.vcell.N5.SimResultsLoader; + +import javax.swing.event.EventListenerList; + +public interface SimLoadingEventCreator { + public void addSimLoadingListener(SimLoadingListener simLoadingListener); + + public void notifySimIsLoading(SimResultsLoader simResultsLoader); + + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader); + +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java new file mode 100644 index 0000000..c5a0ea7 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java @@ -0,0 +1,11 @@ +package org.vcell.N5.UI; + +import java.util.EventListener; + +public interface SimLoadingListener extends EventListener { + + public void simIsLoading(int itemRow); + + public void simFinishedLoading(int itemRow); + +} From 09ae8410c678d99fcebf1d8d114053fa435d6d8d Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 30 Sep 2024 08:36:35 -0400 Subject: [PATCH 3/9] Change Text Color When Sim is Loading --- .../java/org/vcell/N5/LoadingFactory.java | 6 +++- .../java/org/vcell/N5/UI/N5ExportTable.java | 28 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java index 23a9247..09d1b52 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java @@ -21,8 +21,12 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); Thread openN5FileDataset = new Thread(() -> { try{ + // Create clients and show loading status for(SimResultsLoader simResultsLoader: filesToOpen){ simResultsLoader.createS3ClientAndReader(); + notifySimIsLoading(simResultsLoader); + } + for (SimResultsLoader simResultsLoader: filesToOpen){ ImageIntoMemory imageIntoMemory; if (openInMemory){ ArrayList dimensions = simResultsLoader.getN5Dimensions(); @@ -31,8 +35,8 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } else{ ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); imagePlus.show(); + notifySimIsDoneLoading(simResultsLoader); } - } } catch (Exception ex) { N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 8348bf5..e4d3c75 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -12,6 +12,7 @@ import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import java.awt.*; import java.awt.datatransfer.Clipboard; @@ -52,10 +53,12 @@ public class N5ExportTable implements ActionListener, ListSelectionListener, Sim private final Border exampleBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Example Exports"); private static RemoteFileSelection remoteFileSelection; private final int paneWidth = 800; + private final Set loadingRows = new HashSet<>(); private final Logger logger = N5ImageHandler.getLogger(N5ExportTable.class); public N5ExportTable(){ + N5ImageHandler.loadingFactory.addSimLoadingListener(this); remoteFileSelection = new RemoteFileSelection(); } @@ -208,6 +211,23 @@ private JScrollPane tablePanel(){ exportListTable = new JTable(n5ExportTableModel); tableScrollPane = new JScrollPane(exportListTable); + DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer(){ + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (loadingRows.contains(row)) { + cell.setForeground(Color.decode("#228B22")); + } else { + cell.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); + } + return cell; + } + }; + + int columns = n5ExportTableModel.getColumnCount(); + for (int i = 0; i < columns; i++){ + exportListTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer); + } tableScrollPane.setPreferredSize(new Dimension(500, 400)); tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Export Table")); @@ -353,7 +373,7 @@ public void actionPerformed(ActionEvent e) { ArrayList filesToOpen = new ArrayList<>(); for(int row: exportListTable.getSelectedRows()){ String uri = n5ExportTableModel.getRowData(row).uri; - SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName); + SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName, row); filesToOpen.add(simResultsLoader); } N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); @@ -424,12 +444,14 @@ public void valueChanged(ListSelectionEvent e) { @Override public void simIsLoading(int itemRow) { - + loadingRows.add(itemRow); + exportListTable.repaint(); } @Override public void simFinishedLoading(int itemRow) { - + loadingRows.remove(itemRow); + exportListTable.repaint(); } From 869a4effd9e9b73f10613bce11d3c8e518a64b7f Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 1 Oct 2024 08:38:27 -0400 Subject: [PATCH 4/9] Open In Memory Causes Loading to be Displayed --- .../java/org/vcell/N5/LoadingFactory.java | 11 +++++- .../java/org/vcell/N5/UI/ImageIntoMemory.java | 38 ++++++++++++++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java index 09d1b52..8bfa620 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java @@ -1,6 +1,7 @@ package org.vcell.N5; import ij.ImagePlus; +import ij.plugin.Duplicator; import org.vcell.N5.UI.ImageIntoMemory; import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.UI.SimLoadingEventCreator; @@ -9,11 +10,16 @@ import javax.swing.*; import javax.swing.event.EventListenerList; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; -public class LoadingFactory implements SimLoadingEventCreator{ +public class LoadingFactory implements SimLoadingEventCreator { private static final EventListenerList eventListenerList = new EventListenerList(); public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ @@ -31,6 +37,9 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o if (openInMemory){ ArrayList dimensions = simResultsLoader.getN5Dimensions(); imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader); + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + imageIntoMemory.addSimLoadingListener(simLoadingListener); + } imageIntoMemory.displayRangeMenu(); } else{ ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java index f89a327..fec732d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java @@ -15,7 +15,7 @@ import java.awt.event.FocusEvent; import java.io.IOException; -public class ImageIntoMemory implements ActionListener { +public class ImageIntoMemory implements ActionListener, SimLoadingEventCreator { public int startC; public int endC; public int startT; @@ -30,12 +30,15 @@ public class ImageIntoMemory implements ActionListener { private final JTextField zStartTextField; private final JTextField zEndTextField; - private final JButton okayButton; - private final JButton cancelButton; + public static final String okayButtonText = "Okay"; + public static final String cancelButtonText = "Cancel"; + public final JButton okayButton; + public final JButton cancelButton; private final JFrame frame; private final SimResultsLoader simResultsLoader; private static final Logger logger = N5ImageHandler.getLogger(ImageIntoMemory.class); + private static final EventListenerList eventListenerList = new EventListenerList(); public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader simResultsLoader){ this.simResultsLoader = simResultsLoader; @@ -75,8 +78,8 @@ public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader s // Create the "Okay" and "Cancel" buttons panel.add(new JLabel()); - okayButton = new JButton("Okay"); - cancelButton = new JButton("Cancel"); + okayButton = new JButton(okayButtonText); + cancelButton = new JButton(cancelButtonText); // Add action listeners to the buttons okayButton.addActionListener(this); @@ -91,6 +94,10 @@ public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader s frame.add(panel); } + public void dispose(){ + frame.dispose(); + } + public void displayRangeMenu(){ // Make the window visible frame.setVisible(true); @@ -133,6 +140,7 @@ public void actionPerformed(ActionEvent e) { } catch (IOException ex) { throw new RuntimeException(ex); } finally { + notifySimIsDoneLoading(simResultsLoader); N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); N5ExportTable.enableCriticalButtons(true); } @@ -142,12 +150,32 @@ public void actionPerformed(ActionEvent e) { } else if (e.getSource().equals(cancelButton)) { + notifySimIsDoneLoading(simResultsLoader); N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); N5ExportTable.enableCriticalButtons(true); frame.dispose(); } } + @Override + public void addSimLoadingListener(SimLoadingListener simLoadingListener) { + eventListenerList.add(SimLoadingListener.class, simLoadingListener); + } + + @Override + public void notifySimIsLoading(SimResultsLoader simResultsLoader) { + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + simLoadingListener.simIsLoading(simResultsLoader.rowNumber); + } + } + + @Override + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { + for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ + simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber); + } + } + static class HintTextField extends JTextField { Font gainFont = new Font("Tahoma", Font.PLAIN, 11); From b9ca9fca3e011e9789e29340f2cd5db855462cb9 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 1 Oct 2024 09:26:56 -0400 Subject: [PATCH 5/9] Create Package for Library Extensions and Retrieval Instead of everything being in the top directory, more fine grained categorization is used for clarity. --- .../src/main/java/org/vcell/N5/N5ImageHandler.java | 6 ++---- .../src/main/java/org/vcell/N5/UI/ImageIntoMemory.java | 4 +++- .../src/main/java/org/vcell/N5/UI/N5ExportTable.java | 4 ++-- .../main/java/org/vcell/N5/UI/RemoteFileSelection.java | 2 +- .../N5/{ => library/extensions}/S3KeyValueAccess.java | 5 +---- .../N5/{ => library/extensions}/SimCacheLoader.java | 2 +- .../org/vcell/N5/{ => retrieving}/LoadingFactory.java | 10 +--------- .../N5/{UI => retrieving}/SimLoadingEventCreator.java | 6 +----- .../N5/{UI => retrieving}/SimLoadingListener.java | 2 +- .../vcell/N5/{ => retrieving}/SimResultsLoader.java | 5 ++++- .../vcell/N5/{ => retrieving}/N5ImageHandlerTest.java | 4 +++- 11 files changed, 20 insertions(+), 30 deletions(-) rename view-simulation-results/src/main/java/org/vcell/N5/{ => library/extensions}/S3KeyValueAccess.java (94%) rename view-simulation-results/src/main/java/org/vcell/N5/{ => library/extensions}/SimCacheLoader.java (98%) rename view-simulation-results/src/main/java/org/vcell/N5/{ => retrieving}/LoadingFactory.java (94%) rename view-simulation-results/src/main/java/org/vcell/N5/{UI => retrieving}/SimLoadingEventCreator.java (71%) rename view-simulation-results/src/main/java/org/vcell/N5/{UI => retrieving}/SimLoadingListener.java (85%) rename view-simulation-results/src/main/java/org/vcell/N5/{ => retrieving}/SimResultsLoader.java (98%) rename view-simulation-results/src/test/java/org/vcell/N5/{ => retrieving}/N5ImageHandlerTest.java (99%) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index 4e36b7c..0c92c15 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -11,13 +11,11 @@ import org.scijava.plugin.Parameter; import org.scijava.plugin.Plugin; import org.vcell.N5.UI.N5ExportTable; +import org.vcell.N5.retrieving.LoadingFactory; +import org.vcell.N5.retrieving.SimResultsLoader; import java.io.*; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; -import java.util.Stack; /* diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java index fec732d..5516647 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java @@ -4,7 +4,9 @@ import ij.plugin.Duplicator; import org.scijava.log.Logger; import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.SimResultsLoader; +import org.vcell.N5.retrieving.SimLoadingEventCreator; +import org.vcell.N5.retrieving.SimLoadingListener; +import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; import javax.swing.event.EventListenerList; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index e4d3c75..1bccbde 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -3,7 +3,8 @@ import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.SimResultsLoader; +import org.vcell.N5.retrieving.SimLoadingListener; +import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; import javax.swing.border.Border; @@ -12,7 +13,6 @@ import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import java.awt.*; import java.awt.datatransfer.Clipboard; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index 84823c5..a143c3f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -1,7 +1,7 @@ package org.vcell.N5.UI; import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.SimResultsLoader; +import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; import java.awt.*; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/S3KeyValueAccess.java b/view-simulation-results/src/main/java/org/vcell/N5/library/extensions/S3KeyValueAccess.java similarity index 94% rename from view-simulation-results/src/main/java/org/vcell/N5/S3KeyValueAccess.java rename to view-simulation-results/src/main/java/org/vcell/N5/library/extensions/S3KeyValueAccess.java index df019bd..a615d01 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/S3KeyValueAccess.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/library/extensions/S3KeyValueAccess.java @@ -1,12 +1,9 @@ -package org.vcell.N5; +package org.vcell.N5.library.extensions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.ListObjectsV2Request; import org.janelia.saalfeldlab.n5.N5Exception; import org.janelia.saalfeldlab.n5.s3.AmazonS3KeyValueAccess; -import org.janelia.saalfeldlab.n5.s3.AmazonS3Utils; - -import java.net.URI; public class S3KeyValueAccess extends AmazonS3KeyValueAccess { private final String bucketName; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/library/extensions/SimCacheLoader.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java rename to view-simulation-results/src/main/java/org/vcell/N5/library/extensions/SimCacheLoader.java index b8c24a6..60bf8dc 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/library/extensions/SimCacheLoader.java @@ -1,4 +1,4 @@ -package org.vcell.N5; +package org.vcell.N5.library.extensions; import ij.ImagePlus; import ij.gui.ImageWindow; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java similarity index 94% rename from view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java rename to view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java index 8bfa620..b65b190 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java @@ -1,23 +1,15 @@ -package org.vcell.N5; +package org.vcell.N5.retrieving; import ij.ImagePlus; -import ij.plugin.Duplicator; import org.vcell.N5.UI.ImageIntoMemory; import org.vcell.N5.UI.N5ExportTable; -import org.vcell.N5.UI.SimLoadingEventCreator; -import org.vcell.N5.UI.SimLoadingListener; import javax.swing.*; import javax.swing.event.EventListenerList; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; public class LoadingFactory implements SimLoadingEventCreator { private static final EventListenerList eventListenerList = new EventListenerList(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java similarity index 71% rename from view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java rename to view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java index fcb6538..2a0a357 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingEventCreator.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java @@ -1,8 +1,4 @@ -package org.vcell.N5.UI; - -import org.vcell.N5.SimResultsLoader; - -import javax.swing.event.EventListenerList; +package org.vcell.N5.retrieving; public interface SimLoadingEventCreator { public void addSimLoadingListener(SimLoadingListener simLoadingListener); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java similarity index 85% rename from view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java rename to view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java index c5a0ea7..1740df5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/SimLoadingListener.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java @@ -1,4 +1,4 @@ -package org.vcell.N5.UI; +package org.vcell.N5.retrieving; import java.util.EventListener; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java rename to view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index f0e3356..32abbfb 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -1,4 +1,4 @@ -package org.vcell.N5; +package org.vcell.N5.retrieving; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSStaticCredentialsProvider; @@ -23,6 +23,9 @@ import org.janelia.saalfeldlab.n5.imglib2.N5Utils; import org.janelia.saalfeldlab.n5.s3.N5AmazonS3Reader; import org.scijava.log.Logger; +import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.library.extensions.S3KeyValueAccess; +import org.vcell.N5.library.extensions.SimCacheLoader; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5ImageHandlerTest.java b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java similarity index 99% rename from view-simulation-results/src/test/java/org/vcell/N5/N5ImageHandlerTest.java rename to view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java index 1f19578..1403cb3 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5ImageHandlerTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java @@ -1,4 +1,4 @@ -package org.vcell.N5; +package org.vcell.N5.retrieving; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.google.gson.internal.LinkedTreeMap; @@ -11,6 +11,8 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.vcell.N5.N5DataSetFile; +import org.vcell.N5.N5ImageHandler; import java.io.File; import java.io.IOException; From 67350c717be6f073d69b74c209cd206b11f0ba9f Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 1 Oct 2024 10:07:54 -0400 Subject: [PATCH 6/9] Loading Status Resilient to Table Changes --- .../java/org/vcell/N5/UI/ImageIntoMemory.java | 4 ++-- .../java/org/vcell/N5/UI/N5ExportTable.java | 21 +++++++++++++------ .../vcell/N5/retrieving/LoadingFactory.java | 4 ++-- .../N5/retrieving/SimLoadingListener.java | 4 ++-- .../vcell/N5/retrieving/SimResultsLoader.java | 4 +++- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java index 5516647..cd0263f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java @@ -167,14 +167,14 @@ public void addSimLoadingListener(SimLoadingListener simLoadingListener) { @Override public void notifySimIsLoading(SimResultsLoader simResultsLoader) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simIsLoading(simResultsLoader.rowNumber); + simLoadingListener.simIsLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); } } @Override public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber); + simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 1bccbde..229d91e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -53,7 +53,7 @@ public class N5ExportTable implements ActionListener, ListSelectionListener, Sim private final Border exampleBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Example Exports"); private static RemoteFileSelection remoteFileSelection; private final int paneWidth = 800; - private final Set loadingRows = new HashSet<>(); + private final Map loadingRows = new HashMap<>(); private final Logger logger = N5ImageHandler.getLogger(N5ExportTable.class); @@ -215,7 +215,15 @@ private JScrollPane tablePanel(){ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if (loadingRows.contains(row)) { + if (loadingRows.containsKey(row)) { + int actualRow = row; + // The table may have changed by refreshing it, so if past idea of affected row no longer align correct it + while (! n5ExportTableModel.getRowData(row).jobID.equals(loadingRows.get(row))){ + actualRow += 1; // assuming only more items are being added to the list + loadingRows.put(actualRow, loadingRows.get(row)); + loadingRows.remove(row); + } + cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, actualRow, column); cell.setForeground(Color.decode("#228B22")); } else { cell.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); @@ -373,7 +381,8 @@ public void actionPerformed(ActionEvent e) { ArrayList filesToOpen = new ArrayList<>(); for(int row: exportListTable.getSelectedRows()){ String uri = n5ExportTableModel.getRowData(row).uri; - SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName, row); + ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); + SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); filesToOpen.add(simResultsLoader); } N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); @@ -443,13 +452,13 @@ public void valueChanged(ListSelectionEvent e) { } @Override - public void simIsLoading(int itemRow) { - loadingRows.add(itemRow); + public void simIsLoading(int itemRow, String exportID) { + loadingRows.put(itemRow, exportID); exportListTable.repaint(); } @Override - public void simFinishedLoading(int itemRow) { + public void simFinishedLoading(int itemRow, String exportID) { loadingRows.remove(itemRow); exportListTable.repaint(); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java index b65b190..3535293 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java @@ -99,14 +99,14 @@ public void addSimLoadingListener(SimLoadingListener simLoadingListener) { @Override public void notifySimIsLoading(SimResultsLoader simResultsLoader) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simIsLoading(simResultsLoader.rowNumber); + simLoadingListener.simIsLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); } } @Override public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber); + simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java index 1740df5..d2ddf09 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java @@ -4,8 +4,8 @@ public interface SimLoadingListener extends EventListener { - public void simIsLoading(int itemRow); + public void simIsLoading(int itemRow, String exportID); - public void simFinishedLoading(int itemRow); + public void simFinishedLoading(int itemRow, String exportID); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index 32abbfb..a3e9495 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -56,13 +56,15 @@ public class SimResultsLoader { private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public static AmazonS3ClientBuilder s3ClientBuilder; public int rowNumber; + public String exportID; public SimResultsLoader(){ } - public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber){ + public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber, String exportID){ this(stringURI, userSetFileName); this.rowNumber = rowNumber; + this.exportID = exportID; } public SimResultsLoader(String stringURI, String userSetFileName){ uri = URI.create(stringURI); From c8a4541736df9244122de1af98b21cf71c3369ac Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 3 Oct 2024 08:14:21 -0400 Subject: [PATCH 7/9] Overhaul of GUI Architecture A complete overhaul of the plugins GUI architecture. Breaking down classes into their core GUI components, and simplifying the interaction logic. --- .../java/org/vcell/N5/N5ImageHandler.java | 6 +- .../org/vcell/N5/UI/ControlButtonsPanel.java | 190 +++++++ .../org/vcell/N5/UI/ExportDetailsPanel.java | 117 ++++ .../java/org/vcell/N5/UI/ImageIntoMemory.java | 10 +- .../main/java/org/vcell/N5/UI/MainPanel.java | 66 +++ .../java/org/vcell/N5/UI/N5ExportTable.java | 505 ++++-------------- .../org/vcell/N5/UI/RemoteFileSelection.java | 2 +- .../vcell/N5/retrieving/LoadingFactory.java | 25 +- 8 files changed, 506 insertions(+), 415 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/ExportDetailsPanel.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index 0c92c15..fd980f2 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -10,6 +10,7 @@ import org.scijava.log.slf4j.SLF4JLogService; import org.scijava.plugin.Parameter; import org.scijava.plugin.Plugin; +import org.vcell.N5.UI.MainPanel; import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.retrieving.LoadingFactory; import org.vcell.N5.retrieving.SimResultsLoader; @@ -30,18 +31,17 @@ public class N5ImageHandler implements Command { public static final String formatName = "N5"; @Parameter public static LogService logService; - public static N5ExportTable exportTable; + public static MainPanel exportTable; public static String exportedMetaDataPath = System.getProperty("user.home") + "/.vcell/exportMetaData.json"; private static ExportDataRepresentation.FormatExportDataRepresentation exampleJSONData; public final static LoadingFactory loadingFactory = new LoadingFactory(); @Override public void run() { - exportTable = new N5ExportTable(); + exportTable = new MainPanel(); initializeLogService(); setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); - exportTable.displayExportTable(); Thread thread = new Thread(() -> { // For some reason getting a standard client takes three seconds. // So create one upon initialization, while the user is focused on the GUI diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java new file mode 100644 index 0000000..a0cfde3 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -0,0 +1,190 @@ +package org.vcell.N5.UI; + +import org.vcell.N5.N5ImageHandler; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.time.LocalDateTime; +import java.util.Enumeration; + +public class ControlButtonsPanel extends JPanel implements ActionListener { + + private static JButton open; +// private final JButton openLocal = new JButton("Open N5 Local"); + private final JButton copyLink; + private final JButton refreshButton; + private final JButton useN5Link; + private final JButton questionMark; + private final JButton openInMemory; + private final JCheckBox includeExampleExports; + private final JCheckBox todayInterval; + private final JCheckBox monthInterval; + private final JCheckBox yearlyInterval; + private final JCheckBox anyInterval; + private final JPanel timeFilter; + + private N5ExportTable n5ExportTable; + private RemoteFileSelection remoteFileSelection; + + public ControlButtonsPanel(){ + refreshButton = new JButton("Refresh"); + open = new JButton("Open"); + copyLink = new JButton("Copy Link"); + useN5Link = new JButton("Use N5 Link"); + questionMark = new JButton("?"); + questionMark.setPreferredSize(new Dimension(20, 20)); + openInMemory = new JButton("Open In Memory"); + openInMemory.setSelected(false); + includeExampleExports = new JCheckBox("Show Example Exports"); + includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); + + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + + JPanel topRow = new JPanel(new GridBagLayout()); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + topRow.add(open, gridBagConstraints); + gridBagConstraints.gridwidth = 1; + + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + topRow.add(openInMemory, gridBagConstraints); + gridBagConstraints.gridx = 2; + + JPanel bottomRow = new JPanel(new GridBagLayout()); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + bottomRow.add(copyLink, gridBagConstraints); + gridBagConstraints.gridx = 1; + bottomRow.add(useN5Link, gridBagConstraints); + bottomRow.add(questionMark); + + + JPanel userButtonsPanel = new JPanel(new GridBagLayout()); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + userButtonsPanel.add(topRow, gridBagConstraints); + gridBagConstraints.gridy = 1; + userButtonsPanel.add(bottomRow, gridBagConstraints); + +// buttonsPanel.add(questionMark); + + + todayInterval = new JCheckBox("Past 24 Hours"); + monthInterval = new JCheckBox("Past Month"); + yearlyInterval = new JCheckBox("Past Year"); + anyInterval = new JCheckBox("Any Time"); + anyInterval.setSelected(true); + + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(todayInterval); + buttonGroup.add(monthInterval); + buttonGroup.add(yearlyInterval); + buttonGroup.add(anyInterval); + + JPanel filters = new JPanel(); + filters.setLayout(new BorderLayout()); + timeFilter = new JPanel(new GridBagLayout()); + timeFilter.add(anyInterval); + timeFilter.add(todayInterval); + timeFilter.add(monthInterval); + timeFilter.add(yearlyInterval); +// timeFilter.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Time ")); + filters.add(timeFilter, BorderLayout.NORTH); + filters.add(includeExampleExports, BorderLayout.SOUTH); + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + filters.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); + + + int paneWidth = 800; + this.setPreferredSize(new Dimension(paneWidth, 100)); + this.setLayout(new BorderLayout()); +// topBar.add(openLocal); + this.add(userButtonsPanel, BorderLayout.EAST); + this.add(filters, BorderLayout.WEST); + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " User Options ")); + + + refreshButton.addActionListener(this); + open.addActionListener(this); + copyLink.addActionListener(this); + questionMark.addActionListener(this); + useN5Link.addActionListener(this); + includeExampleExports.addActionListener(this); +// openLocal.addActionListener(this); + openInMemory.addActionListener(this); + + Enumeration b = buttonGroup.getElements(); + while (b.hasMoreElements()){ + b.nextElement().addActionListener(this); + } + + open.setEnabled(false); + copyLink.setEnabled(false); + openInMemory.setEnabled(false); + } + + public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFileSelection){ + this.n5ExportTable = n5ExportTable; + this.remoteFileSelection = remoteFileSelection; + } + + @Override + public void actionPerformed(ActionEvent e) { + if(e.getSource().equals(open) || e.getSource().equals(openInMemory)){ + n5ExportTable.openSelectedRows(e.getSource().equals(openInMemory)); + } else if (e.getSource().equals(copyLink)) { + n5ExportTable.copySelectedRowLink(); + } else if (e.getSource().equals(questionMark)) { + new HelpExplanation().displayHelpMenu(); + } else if (e.getSource().equals(useN5Link)) { + remoteFileSelection.setVisible(true); + } else if (e.getSource().equals(includeExampleExports)){ + if(includeExampleExports.isSelected()){ + n5ExportTable.updateExampleExportsToTable(); + return; + } + n5ExportTable.updateTableData(); + } else if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) + || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { + if(includeExampleExports.isSelected()){ + n5ExportTable.updateExampleExportsToTable(); + return; + } + n5ExportTable.updateTableData(); + } + } + + public LocalDateTime oldestTimeAllowed(){ + LocalDateTime pastTime = LocalDateTime.now(); + if (todayInterval.isSelected()){ + pastTime = pastTime.minusDays(1); + } else if (monthInterval.isSelected()) { + pastTime = pastTime.minusMonths(1); + } else if (yearlyInterval.isSelected()) { + pastTime = pastTime.minusYears(1); + } else { + pastTime = pastTime.minusYears(10); //Max date back is 10 years + } + return pastTime; + } + + public void enableRowContextDependentButtons(boolean enable){ + open.setEnabled(enable); + copyLink.setEnabled(enable); + openInMemory.setEnabled(enable); + } + + public void enableCriticalButtons(boolean enable){ + useN5Link.setEnabled(enable); + open.setEnabled(enable); + refreshButton.setEnabled(enable); + copyLink.setEnabled(enable); + remoteFileSelection.submitS3Info.setEnabled(enable); + openInMemory.setEnabled(enable); + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ExportDetailsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ExportDetailsPanel.java new file mode 100644 index 0000000..9e9da45 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ExportDetailsPanel.java @@ -0,0 +1,117 @@ +package org.vcell.N5.UI; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.table.AbstractTableModel; +import java.awt.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class ExportDetailsPanel extends JSplitPane { + private final JTextPane variableTextPanel; + private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + private final ParameterTableModel parameterTableModel; + private final JTable parameterTable; + + + public ExportDetailsPanel(){ + super(JSplitPane.HORIZONTAL_SPLIT); + variableTextPanel = new JTextPane(); + parameterTableModel = new ParameterTableModel(); + parameterTable = new JTable(parameterTableModel); + JScrollPane parameterTableScrollPane = new JScrollPane(parameterTable); + int paneWidth = 800; + parameterTableScrollPane.setPreferredSize(new Dimension(paneWidth / 2, 80)); + parameterTableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Parameter Values ")); +// jTextPane.setSize(800, 200); + variableTextPanel.setEditable(false); + JScrollPane jtextScrollPane = new JScrollPane(variableTextPanel); + jtextScrollPane.setPreferredSize(new Dimension(paneWidth / 2, 80)); + jtextScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Variables ")); + + this.add(jtextScrollPane); + this.add(parameterTableScrollPane); +// exportDetails = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jtextScrollPane, parameterTableScrollPane); + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Export Details ")); + this.setResizeWeight(0.5); + this.setContinuousLayout(true); + + MainPanel.setEnableParentAndChild(this, false); +// return exportDetails; + } + + public void resetExportDetails(){ + parameterTableModel.resetTableData(); + variableTextPanel.setText(""); + MainPanel.setEnableParentAndChild(this, false); + } + + public void addExportDetailEntries(String variableText, ArrayList parameters){ + variableTextPanel.setText(variableText); + for(String parameterValues : parameters){ + String[] tokens = parameterValues.split(":"); + parameterTableModel.addRowData(tokens[0], tokens[1], tokens[2]); + } + variableTextPanel.updateUI(); + parameterTable.updateUI(); + } + + + static class ParameterTableModel extends AbstractTableModel { + + private final static String parameterHeader = "Parameter"; + private final static String defaultValueHeader = "Default Value"; + private final static String newValueHeader = "New Value"; + + + private List> tableData = new ArrayList<>(); + private final ArrayList headers = new ArrayList(){{ + add(parameterHeader); + add(defaultValueHeader); + add(newValueHeader); + }}; + @Override + public String getColumnName(int column) { + return headers.get(column); + } + + @Override + public int getRowCount() { + return tableData.size(); + } + + @Override + public int getColumnCount() { + return headers.size(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + HashMap rowData = tableData.get(rowIndex); + if(columnIndex == headers.indexOf(parameterHeader)){ + return rowData.get(parameterHeader); + } else if (columnIndex == headers.indexOf(defaultValueHeader)) { + return rowData.get(defaultValueHeader); + } else if (columnIndex == headers.indexOf(newValueHeader)) { + return rowData.get(newValueHeader); + } + return null; + } + + public void addRowData(String parameterName, String defaultValue, String newValue){ + HashMap data = new HashMap(){{ + put(parameterHeader, parameterName); + put(defaultValueHeader, defaultValue); + put(newValueHeader, newValue); + }}; + tableData.add(data); + } + + public void resetTableData(){ + tableData = new ArrayList<>(); + } + + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java index cd0263f..12c53cd 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java @@ -42,6 +42,8 @@ public class ImageIntoMemory implements ActionListener, SimLoadingEventCreator { private static final Logger logger = N5ImageHandler.getLogger(ImageIntoMemory.class); private static final EventListenerList eventListenerList = new EventListenerList(); + private final ControlButtonsPanel controlButtonsPanel = MainPanel.controlButtonsPanel; + public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader simResultsLoader){ this.simResultsLoader = simResultsLoader; channelStartTextField = new HintTextField("1"); @@ -143,8 +145,8 @@ public void actionPerformed(ActionEvent e) { throw new RuntimeException(ex); } finally { notifySimIsDoneLoading(simResultsLoader); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); } }); openInMemory.setName("Open N5 Image in Memory"); @@ -153,8 +155,8 @@ public void actionPerformed(ActionEvent e) { else if (e.getSource().equals(cancelButton)) { notifySimIsDoneLoading(simResultsLoader); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); frame.dispose(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java new file mode 100644 index 0000000..a49f5b7 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -0,0 +1,66 @@ +package org.vcell.N5.UI; + +import javax.swing.*; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableColumn; +import java.awt.*; +import java.util.Enumeration; + +public class MainPanel { + private static JDialog exportTableDialog; + private final int paneWidth = 800; + + public final static ControlButtonsPanel controlButtonsPanel = new ControlButtonsPanel(); + public final N5ExportTable n5ExportTable = new N5ExportTable(); + public final ExportDetailsPanel exportDetailsPanel = new ExportDetailsPanel(); + public final RemoteFileSelection remoteFileSelection = new RemoteFileSelection(); + + + public MainPanel(){ + JPanel parentPanel = new JPanel(); + + + n5ExportTable.initialize(controlButtonsPanel, exportDetailsPanel); + controlButtonsPanel.initialize(n5ExportTable, remoteFileSelection); + + parentPanel.setLayout(new BorderLayout()); + parentPanel.add(controlButtonsPanel, BorderLayout.NORTH); + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, n5ExportTable, exportDetailsPanel); + jSplitPane.setContinuousLayout(true); + parentPanel.add(jSplitPane, BorderLayout.CENTER); + + parentPanel.setPreferredSize(new Dimension(paneWidth, 650)); + JOptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); + exportTableDialog = pane.createDialog("VCell Exports"); + exportTableDialog.setModal(false); + exportTableDialog.setResizable(true); + exportTableDialog.setVisible(true); + } + + public static void changeCursor(Cursor cursor){ + exportTableDialog.setCursor(cursor); + } + + public static void setEnableParentAndChild(Container container, boolean enable){ + container.setEnabled(enable); + for (Component component : container.getComponents()){ + if (component instanceof Container){ + setEnableParentAndChild((Container) component, enable); + } + component.setEnabled(enable); + if(component instanceof JTable){ + Enumeration columns = ((JTable) component).getColumnModel().getColumns(); + while (columns.hasMoreElements()){ + columns.nextElement().setHeaderRenderer(new DefaultTableCellRenderer(){ + @Override + public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) { + Component c = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column); + c.setForeground(enable ? Color.BLACK : Color.GRAY); + return c; + } + }); + } + } + } + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 229d91e..334b226 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -13,104 +13,143 @@ import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableColumn; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.io.FileNotFoundException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.List; import java.util.*; import java.util.concurrent.TimeUnit; -public class N5ExportTable implements ActionListener, ListSelectionListener, SimLoadingListener { - public static JDialog exportTableDialog; +public class N5ExportTable extends JScrollPane implements ListSelectionListener, SimLoadingListener { private N5ExportTableModel n5ExportTableModel; - private ParameterTableModel parameterTableModel; - private JTable parameterTable; private JTable exportListTable; - private JScrollPane tableScrollPane; - private JSplitPane exportDetails; - - private static JButton open; - private static final JButton openLocal = new JButton("Open N5 Local"); - private static JButton copyLink; - private static JButton refreshButton; - private static JButton useN5Link; - private static JButton questionMark; - public static JButton openInMemory; - public static JCheckBox includeExampleExports; - private JCheckBox todayInterval; - private JCheckBox monthInterval; - private JCheckBox yearlyInterval; - private JCheckBox anyInterval; - private JPanel timeFilter; - private JTextPane variableTextPanel; + private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); private final Border exampleBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Example Exports"); - private static RemoteFileSelection remoteFileSelection; - private final int paneWidth = 800; - private final Map loadingRows = new HashMap<>(); + private final Map loadingRowsJobID = new HashMap<>(); + + private ControlButtonsPanel controlPanel; + private ExportDetailsPanel exportDetailsPanel; + private final Logger logger = N5ImageHandler.getLogger(N5ExportTable.class); - public N5ExportTable(){ + public N5ExportTable(){} + + public void initialize(ControlButtonsPanel controlButtonsPanel, ExportDetailsPanel exportDetailsPanel){ + this.controlPanel = controlButtonsPanel; + this.exportDetailsPanel = exportDetailsPanel; N5ImageHandler.loadingFactory.addSimLoadingListener(this); - remoteFileSelection = new RemoteFileSelection(); + n5ExportTableModel = new N5ExportTableModel(); + exportListTable = new JTable(n5ExportTableModel); + this.setViewportView(exportListTable); + + + DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer(){ + // The table may have changed by refreshing it, so if past idea of affected row no longer align correct it + public int findActualRow(int row){ + if (row == n5ExportTableModel.getRowCount()){ + return -1; + } + else if (n5ExportTableModel.getRowData(row).jobID.equals(loadingRowsJobID.get(row)) && + row < n5ExportTableModel.getRowCount()){ + return row; + } else { + return findActualRow(row + 1); + } + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + int actualRow = loadingRowsJobID.containsKey(row) ? findActualRow(row) : -1; + if (actualRow != -1){ + if (actualRow != row){ + loadingRowsJobID.put(actualRow, loadingRowsJobID.get(row)); + loadingRowsJobID.remove(row); + } + cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, actualRow, column); + cell.setForeground(Color.decode("#228B22")); + } else { + cell.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); + } + return cell; + } + }; + + int columns = n5ExportTableModel.getColumnCount(); + for (int i = 0; i < columns; i++){ + exportListTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer); + } + + this.setPreferredSize(new Dimension(500, 400)); + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Export Table")); + exportListTable.getSelectionModel().addListSelectionListener(this); + + if(!N5ImageHandler.exportedDataExists()){ + updateExampleExportsToTable(); + } + else{ + updateTableData(); + } + automaticRefresh(); } - private LocalDateTime oldestTimeAllowed(){ - LocalDateTime pastTime = LocalDateTime.now(); - if (todayInterval.isSelected()){ - pastTime = pastTime.minusDays(1); - } else if (monthInterval.isSelected()) { - pastTime = pastTime.minusMonths(1); - } else if (yearlyInterval.isSelected()) { - pastTime = pastTime.minusYears(1); + void updateTableData(){ + // when initializing it is null + if (controlPanel == null){ + updateTableData(LocalDateTime.now().minusYears(10)); } else { - pastTime = pastTime.minusYears(10); //Max date back is 10 years + updateTableData(controlPanel.oldestTimeAllowed()); } - return pastTime; } - public void initalizeTableData(){ + void updateTableData(LocalDateTime oldestTimeAllowed){ n5ExportTableModel.resetData(); - tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Personal Exports")); + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Personal Exports")); try { ExportDataRepresentation.FormatExportDataRepresentation formatExportData = N5ImageHandler.getJsonData(); if (formatExportData != null){ Stack jobStack = formatExportData.formatJobIDs; while (!jobStack.isEmpty()){ String jobID = jobStack.pop(); - if (!n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(jobID), oldestTimeAllowed())){ + if (!n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(jobID), oldestTimeAllowed)){ break; } } } n5ExportTableModel.fireTableDataChanged(); - tableScrollPane.updateUI(); + this.updateUI(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } - private void updateExampleExportsToTable(){ + void updateExampleExportsToTable(){ + // when initializing it is null + if (controlPanel == null){ + updateExampleExportsToTable(LocalDateTime.now().minusYears(10)); + } else { + updateExampleExportsToTable(controlPanel.oldestTimeAllowed()); + } + } + + void updateExampleExportsToTable(LocalDateTime oldestTimeAllowed){ n5ExportTableModel.resetData(); - tableScrollPane.setBorder(exampleBorder); + this.setBorder(exampleBorder); try{ ExportDataRepresentation.FormatExportDataRepresentation exampleFormatExportData = N5ImageHandler.getExampleJSONData(); Stack exampleJobStack = (Stack) exampleFormatExportData.formatJobIDs.clone(); while (!exampleJobStack.isEmpty()){ String jobID = exampleJobStack.pop(); - if (!n5ExportTableModel.appendRowData(exampleFormatExportData.simulationDataMap.get(jobID), oldestTimeAllowed())){ + if (!n5ExportTableModel.appendRowData(exampleFormatExportData.simulationDataMap.get(jobID), oldestTimeAllowed)){ break; } } n5ExportTableModel.fireTableDataChanged(); - tableScrollPane.updateUI(); + this.updateUI(); } catch (FileNotFoundException e){ throw new RuntimeException("Can't open example N5 export table.", e); @@ -122,7 +161,7 @@ private void automaticRefresh(){ try { while(true){ ExportDataRepresentation.FormatExportDataRepresentation formatExportData = N5ImageHandler.getJsonData(); - if (formatExportData != null && !tableScrollPane.getBorder().equals(exampleBorder)){ + if (formatExportData != null && !this.getBorder().equals(exampleBorder)){ ExportDataRepresentation.SimulationExportDataRepresentation mostRecentTableEntry = !n5ExportTableModel.tableData.isEmpty() ? n5ExportTableModel.tableData.getFirst() : null; Stack jobStack = formatExportData.formatJobIDs; boolean isUpdated = false; @@ -132,11 +171,11 @@ private void automaticRefresh(){ || !formatExportData.simulationDataMap.containsKey(mostRecentTableEntry.jobID))){ break; } - isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), oldestTimeAllowed()); + isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), controlPanel.oldestTimeAllowed()); } if(isUpdated){ n5ExportTableModel.fireTableDataChanged(); - tableScrollPane.updateUI(); + this.updateUI(); } } Thread.sleep(TimeUnit.SECONDS.toMillis(2)); @@ -150,376 +189,50 @@ private void automaticRefresh(){ refreshTableThread.start(); } - - private void initialize(){ - JPanel parentPanel = new JPanel(); - - parentPanel.setLayout(new BorderLayout()); - parentPanel.add(topPanel(), BorderLayout.NORTH); - JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,tablePanel(), exportDetailsPanel()); - jSplitPane.setContinuousLayout(true); - parentPanel.add(jSplitPane, BorderLayout.CENTER); - - parentPanel.setPreferredSize(new Dimension(paneWidth, 650)); - JOptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); - exportTableDialog = pane.createDialog("VCell Exports"); - exportTableDialog.setModal(false); - exportTableDialog.setResizable(true); - exportTableDialog.setVisible(true); - if(!N5ImageHandler.exportedDataExists()){ - updateExampleExportsToTable(); - } - else{ - initalizeTableData(); - } - automaticRefresh(); - } - - - public void displayExportTable() { - if (exportTableDialog == null) { - initialize(); - } else { - exportTableDialog.setVisible(true); - } - } - - private JSplitPane exportDetailsPanel(){ - variableTextPanel = new JTextPane(); - parameterTableModel = new ParameterTableModel(); - parameterTable = new JTable(parameterTableModel); - JScrollPane parameterTableScrollPane = new JScrollPane(parameterTable); - parameterTableScrollPane.setPreferredSize(new Dimension(paneWidth / 2, 80)); - parameterTableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Parameter Values ")); -// jTextPane.setSize(800, 200); - variableTextPanel.setEditable(false); - JScrollPane jtextScrollPane = new JScrollPane(variableTextPanel); - jtextScrollPane.setPreferredSize(new Dimension(paneWidth / 2, 80)); - jtextScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Variables ")); - - exportDetails = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jtextScrollPane, parameterTableScrollPane); - exportDetails.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Export Details ")); - exportDetails.setResizeWeight(0.5); - exportDetails.setContinuousLayout(true); - - setEnableParentAndChild(exportDetails, false); - return exportDetails; - } - - private JScrollPane tablePanel(){ - n5ExportTableModel = new N5ExportTableModel(); - exportListTable = new JTable(n5ExportTableModel); - tableScrollPane = new JScrollPane(exportListTable); - - DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer(){ - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if (loadingRows.containsKey(row)) { - int actualRow = row; - // The table may have changed by refreshing it, so if past idea of affected row no longer align correct it - while (! n5ExportTableModel.getRowData(row).jobID.equals(loadingRows.get(row))){ - actualRow += 1; // assuming only more items are being added to the list - loadingRows.put(actualRow, loadingRows.get(row)); - loadingRows.remove(row); - } - cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, actualRow, column); - cell.setForeground(Color.decode("#228B22")); - } else { - cell.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); - } - return cell; - } - }; - - int columns = n5ExportTableModel.getColumnCount(); - for (int i = 0; i < columns; i++){ - exportListTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer); - } - - tableScrollPane.setPreferredSize(new Dimension(500, 400)); - tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Export Table")); - exportListTable.getSelectionModel().addListSelectionListener(this); - - return tableScrollPane; - } - - private JPanel topPanel(){ - refreshButton = new JButton("Refresh"); - open = new JButton("Open"); - copyLink = new JButton("Copy Link"); - useN5Link = new JButton("Use N5 Link"); - questionMark = new JButton("?"); - questionMark.setPreferredSize(new Dimension(20, 20)); - openInMemory = new JButton("Open In Memory"); - openInMemory.setSelected(false); - includeExampleExports = new JCheckBox("Show Example Exports"); - includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); - - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - - JPanel topRow = new JPanel(new GridBagLayout()); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - topRow.add(open, gridBagConstraints); - gridBagConstraints.gridwidth = 1; - - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - topRow.add(openInMemory, gridBagConstraints); - gridBagConstraints.gridx = 2; - - JPanel bottomRow = new JPanel(new GridBagLayout()); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - bottomRow.add(copyLink, gridBagConstraints); - gridBagConstraints.gridx = 1; - bottomRow.add(useN5Link, gridBagConstraints); - bottomRow.add(questionMark); - - - JPanel userButtonsPanel = new JPanel(new GridBagLayout()); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - userButtonsPanel.add(topRow, gridBagConstraints); - gridBagConstraints.gridy = 1; - userButtonsPanel.add(bottomRow, gridBagConstraints); - -// buttonsPanel.add(questionMark); - - - todayInterval = new JCheckBox("Past 24 Hours"); - monthInterval = new JCheckBox("Past Month"); - yearlyInterval = new JCheckBox("Past Year"); - anyInterval = new JCheckBox("Any Time"); - anyInterval.setSelected(true); - - ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(todayInterval); - buttonGroup.add(monthInterval); - buttonGroup.add(yearlyInterval); - buttonGroup.add(anyInterval); - - JPanel filters = new JPanel(); - filters.setLayout(new BorderLayout()); - timeFilter = new JPanel(new GridBagLayout()); - timeFilter.add(anyInterval); - timeFilter.add(todayInterval); - timeFilter.add(monthInterval); - timeFilter.add(yearlyInterval); -// timeFilter.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Time ")); - filters.add(timeFilter, BorderLayout.NORTH); - filters.add(includeExampleExports, BorderLayout.SOUTH); - filters.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); - - - JPanel topBar = new JPanel(); - topBar.setPreferredSize(new Dimension(paneWidth, 100)); - topBar.setLayout(new BorderLayout()); -// topBar.add(openLocal); - topBar.add(userButtonsPanel, BorderLayout.EAST); - topBar.add(filters, BorderLayout.WEST); - topBar.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " User Options ")); - - - refreshButton.addActionListener(this); - open.addActionListener(this); - copyLink.addActionListener(this); - questionMark.addActionListener(this); - useN5Link.addActionListener(this); - includeExampleExports.addActionListener(this); - openLocal.addActionListener(this); - openInMemory.addActionListener(this); - - Enumeration b = buttonGroup.getElements(); - while (b.hasMoreElements()){ - b.nextElement().addActionListener(this); + public void openSelectedRows(boolean inMemory){ + ArrayList filesToOpen = new ArrayList<>(); + for(int row: exportListTable.getSelectedRows()){ + String uri = n5ExportTableModel.getRowData(row).uri; + ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); + SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); + filesToOpen.add(simResultsLoader); } - - open.setEnabled(false); - copyLink.setEnabled(false); - openInMemory.setEnabled(false); - - return topBar; - } - - public static void enableCriticalButtons(boolean enable){ - useN5Link.setEnabled(enable); - open.setEnabled(enable); - refreshButton.setEnabled(enable); - copyLink.setEnabled(enable); - remoteFileSelection.submitS3Info.setEnabled(enable); - openInMemory.setEnabled(enable); + N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, inMemory); } - public static void setEnableParentAndChild(Container container, boolean enable){ - container.setEnabled(enable); - for (Component component : container.getComponents()){ - if (component instanceof Container){ - setEnableParentAndChild((Container) component, enable); - } - component.setEnabled(enable); - if(component instanceof JTable){ - Enumeration columns = ((JTable) component).getColumnModel().getColumns(); - while (columns.hasMoreElements()){ - columns.nextElement().setHeaderRenderer(new DefaultTableCellRenderer(){ - @Override - public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) { - Component c = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column); - c.setForeground(enable ? Color.BLACK : Color.GRAY); - return c; - } - }); - } - } - } - } - - @Override - public void actionPerformed(ActionEvent e) { - if(e.getSource().equals(open) || e.getSource().equals(openInMemory)){ - ArrayList filesToOpen = new ArrayList<>(); - for(int row: exportListTable.getSelectedRows()){ - String uri = n5ExportTableModel.getRowData(row).uri; - ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); - SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); - filesToOpen.add(simResultsLoader); - } - N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, e.getSource().equals(openInMemory)); - } else if (e.getSource().equals(copyLink)) { - ExportDataRepresentation.SimulationExportDataRepresentation selectedRow = n5ExportTableModel.getRowData(exportListTable.getSelectedRow()); - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - clipboard.setContents(new StringSelection(selectedRow.uri), null); - } else if (e.getSource().equals(refreshButton)) { - initalizeTableData(); - } else if (e.getSource().equals(questionMark)) { - new HelpExplanation().displayHelpMenu(); - } else if (e.getSource().equals(useN5Link)) { - remoteFileSelection.setVisible(true); - } else if (e.getSource().equals(openLocal)){ // This button is not displayed to the end user - ArrayList filesToOpen = new ArrayList<>(); - for(int row: exportListTable.getSelectedRows()){ - String uri = n5ExportTableModel.getRowData(row).uri; - SimResultsLoader simResultsLoader = new SimResultsLoader(uri, n5ExportTableModel.getRowData(row).savedFileName); - filesToOpen.add(simResultsLoader); - } - N5ImageHandler.loadingFactory.openLocalN5FS(filesToOpen); - } - else if (e.getSource().equals(includeExampleExports)){ - if(includeExampleExports.isSelected()){ - updateExampleExportsToTable(); - return; - } - initalizeTableData(); - } else if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) - || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { - if(includeExampleExports.isSelected()){ - updateExampleExportsToTable(); - return; - } - initalizeTableData(); - } + public void copySelectedRowLink(){ + ExportDataRepresentation.SimulationExportDataRepresentation selectedRow = n5ExportTableModel.getRowData(exportListTable.getSelectedRow()); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(new StringSelection(selectedRow.uri), null); } @Override public void valueChanged(ListSelectionEvent e) { int row = exportListTable.getSelectedRow(); + exportDetailsPanel.resetExportDetails(); if (row > exportListTable.getRowCount() || row < 0){ - parameterTableModel.resetTableData(); - variableTextPanel.setText(""); - open.setEnabled(false); - copyLink.setEnabled(false); - openInMemory.setEnabled(false); - setEnableParentAndChild(exportDetails, false); + controlPanel.enableRowContextDependentButtons(false); return; } - open.setEnabled(true); - copyLink.setEnabled(true); - openInMemory.setEnabled(true); - setEnableParentAndChild(exportDetails, true); + controlPanel.enableRowContextDependentButtons(true); + MainPanel.setEnableParentAndChild(exportDetailsPanel, true); // AttributeSet attributeSet = styleContext.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.) ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); - variableTextPanel.setText("Variables: " + rowData.variables); - - parameterTableModel.resetTableData(); - for(String parameterValues : rowData.differentParameterValues){ - String[] tokens = parameterValues.split(":"); - parameterTableModel.addRowData(tokens[0], tokens[1], tokens[2]); - } - - variableTextPanel.updateUI(); - parameterTable.updateUI(); + exportDetailsPanel.addExportDetailEntries("Variables: " + rowData.variables, rowData.differentParameterValues); } @Override public void simIsLoading(int itemRow, String exportID) { - loadingRows.put(itemRow, exportID); + loadingRowsJobID.put(itemRow, exportID); exportListTable.repaint(); } @Override public void simFinishedLoading(int itemRow, String exportID) { - loadingRows.remove(itemRow); + loadingRowsJobID.remove(itemRow); exportListTable.repaint(); } - - static class ParameterTableModel extends AbstractTableModel{ - - private final static String parameterHeader = "Parameter"; - private final static String defaultValueHeader = "Default Value"; - private final static String newValueHeader = "New Value"; - - - private List> tableData = new ArrayList<>(); - private final ArrayList headers = new ArrayList(){{ - add(parameterHeader); - add(defaultValueHeader); - add(newValueHeader); - }}; - @Override - public String getColumnName(int column) { - return headers.get(column); - } - - @Override - public int getRowCount() { - return tableData.size(); - } - - @Override - public int getColumnCount() { - return headers.size(); - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - HashMap rowData = tableData.get(rowIndex); - if(columnIndex == headers.indexOf(parameterHeader)){ - return rowData.get(parameterHeader); - } else if (columnIndex == headers.indexOf(defaultValueHeader)) { - return rowData.get(defaultValueHeader); - } else if (columnIndex == headers.indexOf(newValueHeader)) { - return rowData.get(newValueHeader); - } - return null; - } - - public void addRowData(String parameterName, String defaultValue, String newValue){ - HashMap data = new HashMap(){{ - put(parameterHeader, parameterName); - put(defaultValueHeader, defaultValue); - put(newValueHeader, newValue); - }}; - tableData.add(data); - } - - public void resetTableData(){ - tableData = new ArrayList<>(); - } - - } - static class N5ExportTableModel extends AbstractTableModel { public final ArrayList headers = new ArrayList(){{ add("BioModel"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index a143c3f..7dbe31d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -96,7 +96,7 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), ""); - N5ImageHandler.loadingFactory.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, N5ExportTable.openInMemory.isSelected()); + N5ImageHandler.loadingFactory.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, false); this.setVisible(false); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java index 3535293..bc585c1 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java @@ -1,8 +1,9 @@ package org.vcell.N5.retrieving; import ij.ImagePlus; +import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.ImageIntoMemory; -import org.vcell.N5.UI.N5ExportTable; +import org.vcell.N5.UI.MainPanel; import javax.swing.*; import javax.swing.event.EventListenerList; @@ -14,9 +15,11 @@ public class LoadingFactory implements SimLoadingEventCreator { private static final EventListenerList eventListenerList = new EventListenerList(); + private final ControlButtonsPanel controlButtonsPanel = MainPanel.controlButtonsPanel; + public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ - N5ExportTable.enableCriticalButtons(false); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(false); + MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); Thread openN5FileDataset = new Thread(() -> { try{ // Create clients and show loading status @@ -40,16 +43,16 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } } } catch (Exception ex) { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); throw new RuntimeException(ex); } finally { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (!openInMemory) { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); } } }); @@ -60,14 +63,14 @@ public void run() { } public void openLocalN5FS(ArrayList filesToOpen){ - N5ExportTable.enableCriticalButtons(true); + controlButtonsPanel.enableCriticalButtons(true); JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fileChooser.setAcceptAllFileFilterUsed(false); int result = fileChooser.showOpenDialog(null); if (result == JFileChooser.APPROVE_OPTION){ File file = fileChooser.getSelectedFile(); - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); Thread openN5FileDataset = new Thread(() -> { try{ for(SimResultsLoader simResultsLoader: filesToOpen){ @@ -81,8 +84,8 @@ public void openLocalN5FS(ArrayList filesToOpen){ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - N5ExportTable.enableCriticalButtons(true); + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); } }); } From 7bc1c0f8f59e7092ab9c9d73bb28aa3a83a218d7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 4 Oct 2024 09:21:38 -0400 Subject: [PATCH 8/9] Implement Cancel Button Have each simulation being opened be managed it's own thread, and allow interruptions to that thread which will stop the I/O occurring to read remote files. --- .../java/org/vcell/N5/N5ImageHandler.java | 5 +- .../org/vcell/N5/UI/ControlButtonsPanel.java | 39 +++++--- .../java/org/vcell/N5/UI/N5ExportTable.java | 40 +++++--- ...mageIntoMemory.java => RangeSelector.java} | 94 ++++-------------- .../org/vcell/N5/UI/RemoteFileSelection.java | 2 +- .../vcell/N5/retrieving/LoadingFactory.java | 96 +++++++++++++------ 6 files changed, 143 insertions(+), 133 deletions(-) rename view-simulation-results/src/main/java/org/vcell/N5/UI/{ImageIntoMemory.java => RangeSelector.java} (59%) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index fd980f2..b2695e0 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -34,12 +34,13 @@ public class N5ImageHandler implements Command { public static MainPanel exportTable; public static String exportedMetaDataPath = System.getProperty("user.home") + "/.vcell/exportMetaData.json"; private static ExportDataRepresentation.FormatExportDataRepresentation exampleJSONData; - public final static LoadingFactory loadingFactory = new LoadingFactory(); + public static LoadingFactory loadingFactory; @Override public void run() { - exportTable = new MainPanel(); initializeLogService(); + loadingFactory = new LoadingFactory(); + exportTable = new MainPanel(); setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); Thread thread = new Thread(() -> { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index a0cfde3..9eb0579 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -13,10 +13,9 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { - private static JButton open; + private static JButton openOrCancel; // private final JButton openLocal = new JButton("Open N5 Local"); private final JButton copyLink; - private final JButton refreshButton; private final JButton useN5Link; private final JButton questionMark; private final JButton openInMemory; @@ -31,8 +30,7 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private RemoteFileSelection remoteFileSelection; public ControlButtonsPanel(){ - refreshButton = new JButton("Refresh"); - open = new JButton("Open"); + openOrCancel = new JButton("Open"); copyLink = new JButton("Copy Link"); useN5Link = new JButton("Use N5 Link"); questionMark = new JButton("?"); @@ -47,7 +45,7 @@ public ControlButtonsPanel(){ JPanel topRow = new JPanel(new GridBagLayout()); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; - topRow.add(open, gridBagConstraints); + topRow.add(openOrCancel, gridBagConstraints); gridBagConstraints.gridwidth = 1; gridBagConstraints.gridx = 1; @@ -109,8 +107,7 @@ public ControlButtonsPanel(){ this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " User Options ")); - refreshButton.addActionListener(this); - open.addActionListener(this); + openOrCancel.addActionListener(this); copyLink.addActionListener(this); questionMark.addActionListener(this); useN5Link.addActionListener(this); @@ -123,7 +120,7 @@ public ControlButtonsPanel(){ b.nextElement().addActionListener(this); } - open.setEnabled(false); + openOrCancel.setEnabled(false); copyLink.setEnabled(false); openInMemory.setEnabled(false); } @@ -135,8 +132,12 @@ public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFi @Override public void actionPerformed(ActionEvent e) { - if(e.getSource().equals(open) || e.getSource().equals(openInMemory)){ - n5ExportTable.openSelectedRows(e.getSource().equals(openInMemory)); + if(e.getSource().equals(openOrCancel) || e.getSource().equals(openInMemory)){ + if (openOrCancel.getText().equals("Cancel")){ + n5ExportTable.removeFromLoadingRows(); + } else { + n5ExportTable.openSelectedRows(e.getSource().equals(openInMemory)); + } } else if (e.getSource().equals(copyLink)) { n5ExportTable.copySelectedRowLink(); } else if (e.getSource().equals(questionMark)) { @@ -173,16 +174,28 @@ public LocalDateTime oldestTimeAllowed(){ return pastTime; } + public void allowCancel(boolean allow){ + openOrCancel.setEnabled(true); + copyLink.setEnabled(true); + openInMemory.setEnabled(!allow); + useN5Link.setEnabled(true); + remoteFileSelection.submitS3Info.setEnabled(true); + if (allow){ + openOrCancel.setText("Cancel"); + } else { + openOrCancel.setText("Open"); + } + } + public void enableRowContextDependentButtons(boolean enable){ - open.setEnabled(enable); + openOrCancel.setEnabled(enable); copyLink.setEnabled(enable); openInMemory.setEnabled(enable); } public void enableCriticalButtons(boolean enable){ useN5Link.setEnabled(enable); - open.setEnabled(enable); - refreshButton.setEnabled(enable); + openOrCancel.setEnabled(enable); copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); openInMemory.setEnabled(enable); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 334b226..19c4f5e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -48,23 +48,10 @@ public void initialize(ControlButtonsPanel controlButtonsPanel, ExportDetailsPan DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer(){ - // The table may have changed by refreshing it, so if past idea of affected row no longer align correct it - public int findActualRow(int row){ - if (row == n5ExportTableModel.getRowCount()){ - return -1; - } - else if (n5ExportTableModel.getRowData(row).jobID.equals(loadingRowsJobID.get(row)) && - row < n5ExportTableModel.getRowCount()){ - return row; - } else { - return findActualRow(row + 1); - } - } - @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - int actualRow = loadingRowsJobID.containsKey(row) ? findActualRow(row) : -1; + int actualRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row) : -1; if (actualRow != -1){ if (actualRow != row){ loadingRowsJobID.put(actualRow, loadingRowsJobID.get(row)); @@ -206,6 +193,19 @@ public void copySelectedRowLink(){ clipboard.setContents(new StringSelection(selectedRow.uri), null); } + // The table may have changed by refreshing it, so if past idea of affected row no longer align correct it + private int findLoadingRow(int row){ + if (row < 0 || row == n5ExportTableModel.getRowCount()){ + return -1; + } + else if (n5ExportTableModel.getRowData(row).jobID.equals(loadingRowsJobID.get(row)) && + row < n5ExportTableModel.getRowCount()){ + return row; + } else { + return findLoadingRow(row + 1); + } + } + @Override public void valueChanged(ListSelectionEvent e) { int row = exportListTable.getSelectedRow(); @@ -216,9 +216,18 @@ public void valueChanged(ListSelectionEvent e) { } controlPanel.enableRowContextDependentButtons(true); MainPanel.setEnableParentAndChild(exportDetailsPanel, true); -// AttributeSet attributeSet = styleContext.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.) ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); exportDetailsPanel.addExportDetailEntries("Variables: " + rowData.variables, rowData.differentParameterValues); + + int loadingRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row) : -1; + controlPanel.allowCancel(loadingRow != -1); + } + + public void removeFromLoadingRows(){ + int row = exportListTable.getSelectedRow(); + N5ImageHandler.loadingFactory.stopOpeningSimulation(n5ExportTableModel.tableData.get(row).jobID); + loadingRowsJobID.remove(row); + exportListTable.repaint(); } @Override @@ -231,6 +240,7 @@ public void simIsLoading(int itemRow, String exportID) { public void simFinishedLoading(int itemRow, String exportID) { loadingRowsJobID.remove(itemRow); exportListTable.repaint(); + controlPanel.allowCancel(false); } static class N5ExportTableModel extends AbstractTableModel { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java similarity index 59% rename from view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java rename to view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java index 12c53cd..feb47c8 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java @@ -1,12 +1,7 @@ package org.vcell.N5.UI; -import ij.ImagePlus; -import ij.plugin.Duplicator; import org.scijava.log.Logger; import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.retrieving.SimLoadingEventCreator; -import org.vcell.N5.retrieving.SimLoadingListener; -import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; import javax.swing.event.EventListenerList; @@ -15,9 +10,8 @@ import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; -import java.io.IOException; -public class ImageIntoMemory implements ActionListener, SimLoadingEventCreator { +public class RangeSelector extends JDialog implements ActionListener { public int startC; public int endC; public int startT; @@ -32,20 +26,20 @@ public class ImageIntoMemory implements ActionListener, SimLoadingEventCreator { private final JTextField zStartTextField; private final JTextField zEndTextField; - public static final String okayButtonText = "Okay"; - public static final String cancelButtonText = "Cancel"; + public boolean cancel; + + private static final String okayButtonText = "Okay"; + private static final String cancelButtonText = "Cancel"; public final JButton okayButton; public final JButton cancelButton; private final JFrame frame; - private final SimResultsLoader simResultsLoader; - private static final Logger logger = N5ImageHandler.getLogger(ImageIntoMemory.class); + private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); private static final EventListenerList eventListenerList = new EventListenerList(); private final ControlButtonsPanel controlButtonsPanel = MainPanel.controlButtonsPanel; - public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader simResultsLoader){ - this.simResultsLoader = simResultsLoader; + public RangeSelector(double cDim, double zDim, double tDim, String userSetFileName){ channelStartTextField = new HintTextField("1"); channelEndTextField = new HintTextField("" + (int) cDim); @@ -56,9 +50,10 @@ public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader s timeEndTextField = new HintTextField("" + (int) tDim); // Create the frame - frame = new JFrame("Select " + simResultsLoader.userSetFileName + " Dimensions"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setSize(400, 200); + frame = new JFrame("Select " + userSetFileName + " Dimensions"); + this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + this.setSize(400, 200); + this.setTitle("Select " + userSetFileName + " Dimensions"); // Create a panel to hold the input boxes and buttons JPanel panel = new JPanel(); @@ -96,34 +91,22 @@ public ImageIntoMemory(double cDim, double zDim, double tDim, SimResultsLoader s // Add the panel to the frame frame.add(panel); - } - - public void dispose(){ - frame.dispose(); + this.setContentPane(panel); + this.setModal(true); } public void displayRangeMenu(){ // Make the window visible - frame.setVisible(true); - } - - public static void usePopUp(){ - - } - - public static void useExistingParameters(int startC, int endC, int startT, int endT, int startZ, int endZ){ - + this.setVisible(true); } public static void main(String[] args) { - ImageIntoMemory inMemoryPopUp = new ImageIntoMemory(1, 2, 3, null); + RangeSelector inMemoryPopUp = new RangeSelector(1, 2, 3, null); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(okayButton)){ - frame.dispose(); - startC = Integer.parseInt(channelStartTextField.getText()); endC = Integer.parseInt(channelEndTextField.getText()); startT = Integer.parseInt(timeStartTextField.getText()) - 1; @@ -131,52 +114,17 @@ public void actionPerformed(ActionEvent e) { startZ = Integer.parseInt(zStartTextField.getText()) - 1; endZ = Integer.parseInt(zEndTextField.getText()) - 1; - Thread openInMemory = new Thread(() -> { - try { - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - long start = System.currentTimeMillis(); - logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory"); - imagePlus = new Duplicator().run(imagePlus, startC, endC, startZ, - endZ, startT, endT); - long end = System.currentTimeMillis(); - logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s"); - imagePlus.show(); - } catch (IOException ex) { - throw new RuntimeException(ex); - } finally { - notifySimIsDoneLoading(simResultsLoader); - MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); - } - }); - openInMemory.setName("Open N5 Image in Memory"); - openInMemory.start(); + cancel = false; + + this.setVisible(false); + this.setModal(false); } else if (e.getSource().equals(cancelButton)) { - notifySimIsDoneLoading(simResultsLoader); MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); controlButtonsPanel.enableCriticalButtons(true); - frame.dispose(); - } - } - - @Override - public void addSimLoadingListener(SimLoadingListener simLoadingListener) { - eventListenerList.add(SimLoadingListener.class, simLoadingListener); - } - - @Override - public void notifySimIsLoading(SimResultsLoader simResultsLoader) { - for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simIsLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); - } - } - - @Override - public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { - for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); + cancel = true; + this.setVisible(false); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index 7dbe31d..6f0f827 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -95,7 +95,7 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { - SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), ""); + SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, ""); N5ImageHandler.loadingFactory.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, false); this.setVisible(false); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java index bc585c1..a673257 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java @@ -1,8 +1,13 @@ package org.vcell.N5.retrieving; +import com.amazonaws.AbortedException; +import com.amazonaws.http.timers.client.SdkInterruptedException; import ij.ImagePlus; +import ij.plugin.Duplicator; +import org.scijava.log.Logger; +import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.ControlButtonsPanel; -import org.vcell.N5.UI.ImageIntoMemory; +import org.vcell.N5.UI.RangeSelector; import org.vcell.N5.UI.MainPanel; import javax.swing.*; @@ -11,55 +16,88 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; public class LoadingFactory implements SimLoadingEventCreator { private static final EventListenerList eventListenerList = new EventListenerList(); private final ControlButtonsPanel controlButtonsPanel = MainPanel.controlButtonsPanel; + private final HashMap openingSimulations = new HashMap<>(); + private final Object openSimulationsLock = new Object(); + + private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); + public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ - controlButtonsPanel.enableCriticalButtons(false); + controlButtonsPanel.allowCancel(true); MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); - Thread openN5FileDataset = new Thread(() -> { - try{ - // Create clients and show loading status - for(SimResultsLoader simResultsLoader: filesToOpen){ + + for (int i = 0; i < filesToOpen.size(); i++){ + SimResultsLoader simResultsLoader = filesToOpen.get(i); + Thread openThread = new Thread(() -> { + try{ simResultsLoader.createS3ClientAndReader(); notifySimIsLoading(simResultsLoader); - } - for (SimResultsLoader simResultsLoader: filesToOpen){ - ImageIntoMemory imageIntoMemory; + RangeSelector rangeSelector; if (openInMemory){ ArrayList dimensions = simResultsLoader.getN5Dimensions(); - imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader); - for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - imageIntoMemory.addSimLoadingListener(simLoadingListener); + rangeSelector = new RangeSelector(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader.userSetFileName); + rangeSelector.displayRangeMenu(); + if (!rangeSelector.cancel){ + openInMemory(simResultsLoader, rangeSelector); } - imageIntoMemory.displayRangeMenu(); + rangeSelector.dispose(); } else{ ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); imagePlus.show(); - notifySimIsDoneLoading(simResultsLoader); } } - } catch (Exception ex) { - MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); - throw new RuntimeException(ex); - } finally { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (!openInMemory) { - MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); - } + catch (RuntimeException e) { + if (e.getCause().getCause().getCause() instanceof SdkInterruptedException || + e.getCause().getCause() instanceof AbortedException){ + logger.debug("Simulation stopped loading"); + } else { + throw new RuntimeException(e); } - }); + } + catch (Exception e){ + throw new RuntimeException(e); + } finally { + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); + notifySimIsDoneLoading(simResultsLoader); + synchronized (openSimulationsLock){ + openingSimulations.remove(simResultsLoader.exportID); + } + } + }); + openThread.setName("Opening sim number: " + i + ". With id: " + simResultsLoader.exportID); + synchronized (openSimulationsLock){ + openingSimulations.put(simResultsLoader.exportID, openThread); + } + openThread.start(); + } + } + + private void openInMemory(SimResultsLoader simResultsLoader, RangeSelector rangeSelector) throws IOException { + ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + long start = System.currentTimeMillis(); + logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory"); + imagePlus = new Duplicator().run(imagePlus, rangeSelector.startC, rangeSelector.endC, rangeSelector.startZ, + rangeSelector.endZ, rangeSelector.startT, rangeSelector.endT); + long end = System.currentTimeMillis(); + logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s"); + imagePlus.show(); + } + + public void stopOpeningSimulation(String exportID){ + Thread stopOtherThread = new Thread(() -> { + synchronized (openSimulationsLock){ + openingSimulations.get(exportID).interrupt(); + openingSimulations.remove(exportID); } }); - openN5FileDataset.setName("Open N5 File"); - openN5FileDataset.start(); + stopOtherThread.start(); } public void openLocalN5FS(ArrayList filesToOpen){ From fac12aeac4a5a70c784b0cd5a235456164f3c425 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 4 Oct 2024 10:20:58 -0400 Subject: [PATCH 9/9] Fix Find Loading Rows Function The recursive function attempted to get a jobID that didn't exist within the loading rows hashtable. --- .../java/org/vcell/N5/UI/N5ExportTable.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 19c4f5e..f9de4e0 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -51,12 +51,8 @@ public void initialize(ControlButtonsPanel controlButtonsPanel, ExportDetailsPan @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - int actualRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row) : -1; + int actualRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row, row) : -1; if (actualRow != -1){ - if (actualRow != row){ - loadingRowsJobID.put(actualRow, loadingRowsJobID.get(row)); - loadingRowsJobID.remove(row); - } cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, actualRow, column); cell.setForeground(Color.decode("#228B22")); } else { @@ -163,6 +159,7 @@ private void automaticRefresh(){ if(isUpdated){ n5ExportTableModel.fireTableDataChanged(); this.updateUI(); + exportListTable.repaint(); } } Thread.sleep(TimeUnit.SECONDS.toMillis(2)); @@ -194,15 +191,20 @@ public void copySelectedRowLink(){ } // The table may have changed by refreshing it, so if past idea of affected row no longer align correct it - private int findLoadingRow(int row){ - if (row < 0 || row == n5ExportTableModel.getRowCount()){ + private int findLoadingRow(int currentRow, int initialRow){ + String expectedJobID = loadingRowsJobID.get(initialRow); + if (currentRow < 0 || currentRow == n5ExportTableModel.getRowCount()){ return -1; } - else if (n5ExportTableModel.getRowData(row).jobID.equals(loadingRowsJobID.get(row)) && - row < n5ExportTableModel.getRowCount()){ - return row; + else if (n5ExportTableModel.getRowData(currentRow).jobID.equals(expectedJobID) && + currentRow < n5ExportTableModel.getRowCount()){ + if (currentRow != initialRow){ + loadingRowsJobID.put(currentRow, expectedJobID); + loadingRowsJobID.remove(initialRow); + } + return currentRow; } else { - return findLoadingRow(row + 1); + return findLoadingRow(currentRow + 1, initialRow); } } @@ -219,7 +221,7 @@ public void valueChanged(ListSelectionEvent e) { ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); exportDetailsPanel.addExportDetailEntries("Variables: " + rowData.variables, rowData.differentParameterValues); - int loadingRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row) : -1; + int loadingRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row, row) : -1; controlPanel.allowCancel(loadingRow != -1); }