diff --git a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java index 708038ab..587fb3d4 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java +++ b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java @@ -1,12 +1,7 @@ package org.micromanager.lightsheetmanager; -import com.google.common.eventbus.Subscribe; import net.miginfocom.swing.MigLayout; -import org.micromanager.Studio; -import org.micromanager.events.ExposureChangedEvent; -import org.micromanager.events.LiveModeEvent; - import org.micromanager.lightsheetmanager.api.data.GeometryType; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.data.Icons; @@ -23,24 +18,25 @@ */ public class LightSheetManagerFrame extends JFrame { - private final Studio studio_; private TabPanel tabPanel_; - private final LightSheetManager model_; public LightSheetManagerFrame(final LightSheetManager model, final boolean isLoaded) { model_ = Objects.requireNonNull(model); - studio_ = model_.studio(); // save window position - WindowPositioning.setUpBoundsMemory( - this, this.getClass(), this.getClass().getSimpleName()); + WindowPositioning.setUpBoundsMemory(this, + this.getClass(), this.getClass().getSimpleName()); + + // window setup + setTitle(LightSheetManagerPlugin.menuName); + setIconImage(Icons.MICROSCOPE.getImage()); + setResizable(false); - // create the user interface if (isLoaded) { - initDialogs(); - final GeometryType geometryType = model_.devices().adapter().geometry(); - switch (geometryType) { + openDialogs(); // ask the user to change settings + final GeometryType geometry = model_.devices().adapter().geometry(); + switch (geometry) { case DISPIM: createUserInterface(); break; @@ -55,54 +51,38 @@ public LightSheetManagerFrame(final LightSheetManager model, final boolean isLoa model_.acquisitions().updateDurationLabels(); break; default: - model_.setErrorText("Microscope geometry type " - + geometryType + " is not supported yet."); + model_.setErrorText("Microscope geometry type " + geometry + " is not supported yet."); createErrorUserInterface(); break; } } else { - // error text set in model_ setup createErrorUserInterface(); } - } /** - * This is the window that opens when the plugin encounters an error. + * The window that opens when the plugin encounters an error, it + * displays the error message set during {@code model_.setup()}. */ private void createErrorUserInterface() { - setTitle(LightSheetManagerPlugin.menuName); - setResizable(false); - // use MigLayout as the layout manager setLayout(new MigLayout( "insets 10 10 10 10", "[]10[]", "[]10[]" )); - final Label lblTitle = new Label("Light Sheet Manager", Font.BOLD, 16); + + final Label lblTitle = new Label(LightSheetManagerPlugin.menuName, Font.BOLD, 16); final Label lblError = new Label(model_.getErrorText(), Font.BOLD, 14); add(lblTitle, "wrap"); add(lblError, ""); - - pack(); // fit window size to layout - setIconImage(Icons.MICROSCOPE.getImage()); - - // clean up resources when the frame is closed - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } /** * The user interface for diSPIM or SCAPE. */ private void createUserInterface() { - setTitle(LightSheetManagerPlugin.menuName); - setResizable(false); - - final Label lblTitle = new Label(LightSheetManagerPlugin.menuName, Font.BOLD, 20); - lblTitle.setFont(new Font(Font.MONOSPACED, Font.BOLD, 20)); - // use MigLayout as the layout manager setLayout(new MigLayout( "insets 10 10 10 10", @@ -115,63 +95,32 @@ private void createUserInterface() { final int height = 680; tabPanel_ = new TabPanel(model_, this, width, height); - // add ui elements to the panel - add(lblTitle, "wrap"); - add(tabPanel_, "wrap"); - - pack(); // fit window size to layout - setIconImage(Icons.MICROSCOPE.getImage()); - - // clean up resources when the frame is closed - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - - // register micro-manager events - studio_.events().registerForEvents(this); + final Label lblTitle = new Label(LightSheetManagerPlugin.menuName, Font.BOLD, 20); + lblTitle.setFont(new Font(Font.MONOSPACED, Font.BOLD, 20)); + // restore the polling state from settings if (model_.pluginSettings().isPollingPositions()) { model_.positions().startPolling(); } + // TODO: make this better, put it in plugin class // window close event WindowUtils.registerWindowClosingEvent(this, event -> { - tabPanel_.getAcquisitionTab().getMultiPositionPanel().getXYZGridFrame().dispose(); - model_.positions().stopPolling(); - model_.userSettings().save(); - studio_.logs().logMessage("user settings saved"); + if (tabPanel_ != null) { + tabPanel_.getAcquisitionTab().getMultiPositionPanel().getXYZGridFrame().dispose(); + } }); + add(lblTitle, "wrap"); + add(tabPanel_, "wrap"); } /** * Detect settings after the model is loaded, * ask to change settings with dialogs. */ - private void initDialogs() { + private void openDialogs() { model_.devices().checkDevices(this); } - public void toggleLiveMode() { - if (studio_.live().isLiveModeOn()) { - studio_.live().setLiveModeOn(false); - // close the live mode window if it exists - if (studio_.live().getDisplay() != null) { - studio_.live().getDisplay().close(); - } - } else { - studio_.live().setLiveModeOn(true); - } - } - - // Note: doesn't seem to work for all cameras - @Subscribe - public void liveModeListener(LiveModeEvent event) { -// if (!studio_.live().isLiveModeOn()) { -// } - } - - @Subscribe - public void onExposureChanged(ExposureChangedEvent event) { -// System.out.println("Exposure changed!"); - } - } diff --git a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java index eb50cb07..85ef4585 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java +++ b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java @@ -7,6 +7,8 @@ import org.scijava.plugin.Plugin; import org.scijava.plugin.SciJavaPlugin; +import javax.swing.JFrame; + @Plugin(type = MenuPlugin.class) public class LightSheetManagerPlugin implements MenuPlugin, SciJavaPlugin { public static final String copyright = "Applied Scientific Instrumentation (ASI), 2022-2026"; @@ -30,24 +32,50 @@ public String getSubMenu() { @Override public void onPluginSelected() { - // only one instance of the plugin can be open + // restore the window if the plugin is already open if (WindowUtils.isOpen(frame_)) { - WindowUtils.close(frame_); + if (WindowUtils.isMinimized(frame_)) { + frame_.setState(JFrame.NORMAL); + } + frame_.setVisible(true); + frame_.toFront(); + frame_.requestFocus(); + return; // early exit => plugin is already open } - // TODO: capture all errors like this? + // start the plugin try { + // create the data model and load settings model_ = new LightSheetManager(studio_); final boolean isLoaded = model_.setup(); + + // create the ui; show an error ui on failure frame_ = new LightSheetManagerFrame(model_, isLoaded); + frame_.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + if (isLoaded) { model_.acquisitions().setFrame(frame_); } + + WindowUtils.registerWindowClosingEvent(frame_, event -> { + model_.positions().stopPolling(); + model_.userSettings().save(); + }); + + WindowUtils.registerWindowClosedEvent(frame_, event -> { + frame_ = null; + model_ = null; + }); + + frame_.pack(); frame_.setVisible(true); frame_.toFront(); } catch (Exception e) { + // cleanup resources + frame_ = null; + model_ = null; if (studio_ != null) { - studio_.logs().showError(e); + studio_.logs().showError(e, "Error starting Light Sheet Manager"); } } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Button.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Button.java index 8b8259eb..4a773441 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Button.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Button.java @@ -52,7 +52,7 @@ public void setAbsoluteSize(final int width, final int height) { setMaximumSize(size); } - public void registerListener(final Method method) { - addActionListener(method::run); + public void registerListener(final Runnable listener) { + addActionListener(e -> listener.run()); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java index 2a7fe970..1ae050d8 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java @@ -3,6 +3,8 @@ import javax.swing.JCheckBox; import javax.swing.SwingConstants; import java.awt.Font; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; public class CheckBox extends JCheckBox { @@ -38,10 +40,10 @@ public CheckBox(final String text, final int fontSize, final boolean defaultStat */ public void setLocked(final boolean locked) { isLocked_ = locked; - if (locked) { - setFont(getFont().deriveFont(java.awt.Font.BOLD)); + if (isLocked_) { + setFont(getFont().deriveFont(Font.BOLD)); } else { - setFont(getFont().deriveFont(java.awt.Font.PLAIN)); + setFont(getFont().deriveFont(Font.PLAIN)); } } @@ -61,10 +63,6 @@ public void setSelected(boolean state, boolean shouldFire) { } } - public void registerListener(final Method method) { - addActionListener(method::run); - } - @Override public void setSelected(boolean state) { // default to true, always fires events @@ -72,17 +70,21 @@ public void setSelected(boolean state) { } @Override - protected void processMouseEvent(java.awt.event.MouseEvent e) { + protected void processMouseEvent(MouseEvent e) { if (!isLocked_) { super.processMouseEvent(e); } } @Override - protected void processKeyEvent(java.awt.event.KeyEvent e) { + protected void processKeyEvent(KeyEvent e) { if (!isLocked_) { super.processKeyEvent(e); } } + public void registerListener(final Runnable listener) { + addActionListener(e -> listener.run()); + } + } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/ComboBox.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/ComboBox.java index 8883cf09..24d7043f 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/ComboBox.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/ComboBox.java @@ -3,7 +3,6 @@ import javax.swing.JComboBox; import java.awt.Dimension; -import java.util.Arrays; public class ComboBox extends JComboBox { @@ -30,8 +29,8 @@ public void setAbsoluteSize(final int width, final int height) { setMaximumSize(size); } - public void registerListener(final Method method) { - addActionListener(method::run); + public void registerListener(final Runnable listener) { + addActionListener(e -> listener.run()); } } \ No newline at end of file diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Label.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Label.java index de933263..50868d80 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Label.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Label.java @@ -2,7 +2,8 @@ import javax.swing.JLabel; -import java.awt.*; +import java.awt.Color; +import java.awt.Font; public class Label extends JLabel { diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Method.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Method.java deleted file mode 100644 index b13dff0f..00000000 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Method.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.micromanager.lightsheetmanager.gui.components; - -import java.util.EventObject; - -@FunctionalInterface -public interface Method { - void run(EventObject event); -} \ No newline at end of file diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java index c24d3756..d8d3b818 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java @@ -99,9 +99,9 @@ public int getSelectedIndex() { return -1; } - public void registerListener(final Method method) { + public void registerListener(final Runnable listener) { for (final JRadioButton button : buttons) { - button.addActionListener(method::run); + button.addActionListener(e -> listener.run()); } } } \ No newline at end of file diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/SettingsListener.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/SettingsListener.java new file mode 100644 index 00000000..c32cb82a --- /dev/null +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/SettingsListener.java @@ -0,0 +1,8 @@ +package org.micromanager.lightsheetmanager.gui.components; + +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; + +@FunctionalInterface +public interface SettingsListener { + void onSettingsChanged(final AcquisitionSettings settings); +} diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Slider.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Slider.java index 9bcb30bf..bebb8b72 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Slider.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Slider.java @@ -5,7 +5,6 @@ import javax.swing.UIManager; import java.util.Hashtable; - /** * Create a slider that uses double values using a scale factor. *

@@ -39,18 +38,10 @@ public Slider(final int min, final int max, final int scaleFactor) { setSnapToTicks(false); } - public void registerListener(final Method method) { - addChangeListener(e -> { - if (!this.getValueIsAdjusting()) { - method.run(e); - } - }); - } - /** * Returns the actual value that the slider is meant to represent. * - * @return the unscaled + * @return the unscaled value */ public double getDouble() { return (double) getValue() / scaleFactor_; @@ -59,4 +50,13 @@ public double getDouble() { public void setDouble(final double value) { setValue((int)(value*scaleFactor_)); } + + public void registerListener(final Runnable listener) { + addChangeListener(e -> { + if (!this.getValueIsAdjusting()) { + listener.run(); + } + }); + } + } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Spinner.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Spinner.java index a8121d36..e4f059cc 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/Spinner.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/Spinner.java @@ -1,6 +1,5 @@ package org.micromanager.lightsheetmanager.gui.components; -import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; @@ -39,8 +38,7 @@ public static Spinner createDoubleSpinner( } public void setColumnSize(final int width) { - final JComponent editor = getEditor(); - final JFormattedTextField textField = ((NumberEditor)editor).getTextField(); + final JFormattedTextField textField = ((NumberEditor)getEditor()).getTextField(); textField.setColumns(width); } @@ -64,7 +62,7 @@ public void setDouble(final double n) { setValue(n); } - public void registerListener(final Method method) { - addChangeListener(method::run); + public void registerListener(final Runnable listener) { + addChangeListener(e -> listener.run()); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/TabbedPane.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/TabbedPane.java index 25c95852..f5a7c581 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/TabbedPane.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/TabbedPane.java @@ -41,7 +41,7 @@ public void setAbsoluteSize(final int width, final int height) { } // @Override -// public void addTab(String title, java.awt.Component component) throws Exception { +// public void addTab(String title, Component component) throws Exception { // if (component instanceof ListeningPanel) { // super.addTab(title, component); // } else { diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextField.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextField.java index 8c055a04..6e0e49aa 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextField.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextField.java @@ -17,8 +17,8 @@ public TextField(final String text, final int size) { setColumns(size); } - public void registerListener(final Method method) { - addActionListener(method::run); + public void registerListener(final Runnable listener) { + addActionListener(e -> listener.run()); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextPane.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextPane.java index efc7b8cb..b8163c3d 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextPane.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/TextPane.java @@ -1,5 +1,7 @@ package org.micromanager.lightsheetmanager.gui.components; +import org.micromanager.internal.MMStudio; + import javax.swing.JTextPane; import javax.swing.event.HyperlinkEvent; import java.awt.Desktop; @@ -19,10 +21,8 @@ public void registerHyperlinkListener() { if (HyperlinkEvent.EventType.ACTIVATED.equals(event.getEventType())) { try { Desktop.getDesktop().browse(new URI(event.getURL().toString())); - } catch (URISyntaxException e) { - //MyDialogUtils.showError("Could not open web browser."); - } catch (IOException e) { - //MyDialogUtils.showError("Could not open web browser."); + } catch (URISyntaxException | IOException e) { + MMStudio.getInstance().logs().logMessage("Could not open web browser."); } } }); diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/ToggleButton.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/ToggleButton.java index d9dc1431..476f8359 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/ToggleButton.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/ToggleButton.java @@ -71,10 +71,10 @@ public void setSize(final int width, final int height) { setMaximumSize(size); } - public void registerListener(final Method method) { + public void registerListener(final Runnable listener) { addActionListener(event -> { setState(isSelected()); - method.run(event); + listener.run(); }); } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/frames/XYZGridFrame.java b/src/main/java/org/micromanager/lightsheetmanager/gui/frames/XYZGridFrame.java index 93909269..cba73c29 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/frames/XYZGridFrame.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/frames/XYZGridFrame.java @@ -209,57 +209,47 @@ private void createEventHandlers() { final XYZGrid grid = model_.pluginSettings().xyzGrid(); // Check Boxes - cbxUseX_.registerListener(e -> { + cbxUseX_.registerListener(() -> { final boolean selected = cbxUseX_.isSelected(); grid.setUseX(selected); setEnabledX(selected); }); - cbxUseY_.registerListener(e -> { + cbxUseY_.registerListener(() -> { final boolean selected = cbxUseY_.isSelected(); grid.setUseY(selected); setEnabledY(selected); }); - cbxUseZ_.registerListener(e -> { + cbxUseZ_.registerListener(() -> { final boolean selected = cbxUseZ_.isSelected(); grid.setUseZ(selected); setEnabledZ(selected); }); - cbxClearPositions_.registerListener(e -> - grid.setClearYZ(cbxClearPositions_.isSelected())); + cbxClearPositions_.registerListener( + () -> grid.setClearYZ(cbxClearPositions_.isSelected())); // Spinners X - spnXStart_.registerListener(e -> - grid.setStartX(spnXStart_.getDouble())); - spnXStop_.registerListener(e -> - grid.setStopX(spnXStop_.getDouble())); - spnXDelta_.registerListener(e -> - grid.setDeltaX(spnXDelta_.getDouble())); + spnXStart_.registerListener(() -> grid.setStartX(spnXStart_.getDouble())); + spnXStop_.registerListener(() -> grid.setStopX(spnXStop_.getDouble())); + spnXDelta_.registerListener(() -> grid.setDeltaX(spnXDelta_.getDouble())); // Spinners Y - spnYStart_.registerListener(e -> - grid.setStartY(spnYStart_.getDouble())); - spnYStop_.registerListener(e -> - grid.setStopY(spnYStop_.getDouble())); - spnYDelta_.registerListener(e -> - grid.setDeltaY(spnYDelta_.getDouble())); + spnYStart_.registerListener(() -> grid.setStartY(spnYStart_.getDouble())); + spnYStop_.registerListener(() -> grid.setStopY(spnYStop_.getDouble())); + spnYDelta_.registerListener(() -> grid.setDeltaY(spnYDelta_.getDouble())); // Spinners Z - spnZStart_.registerListener(e -> - grid.setStartZ(spnZStart_.getDouble())); - spnZStop_.registerListener(e -> - grid.setStopZ(spnZStop_.getDouble())); - spnZDelta_.registerListener(e -> - grid.setDeltaZ(spnZDelta_.getDouble())); + spnZStart_.registerListener(() -> grid.setStartZ(spnZStart_.getDouble())); + spnZStop_.registerListener(() -> grid.setStopZ(spnZStop_.getDouble())); + spnZDelta_.registerListener(() -> grid.setDeltaZ(spnZDelta_.getDouble())); // Overlap - spnOverlapYZ_.registerListener(e -> - grid.setOverlapYZ(spnOverlapYZ_.getInt())); + spnOverlapYZ_.registerListener(() -> grid.setOverlapYZ(spnOverlapYZ_.getInt())); // compute XYZ grid - btnComputeGrid_.registerListener(e -> { + btnComputeGrid_.registerListener(() -> { final PositionList positionList = model_.studio().positions().getPositionList(); if (positionList.getNumberOfPositions() != 0) { final boolean result = DialogUtils.showYesNoDialog(this, "Warning", @@ -273,10 +263,10 @@ private void createEventHandlers() { loadFromSettings(); }); - btnEditPositionList_.registerListener(e -> - model_.studio().app().showPositionList()); - btnRunOverviewAcq_.registerListener(e -> - model_.studio().logs().showError("Not implemented yet!")); // TODO: !!! + btnEditPositionList_.registerListener( + () -> model_.studio().app().showPositionList()); + btnRunOverviewAcq_.registerListener( + () -> model_.studio().logs().showError("Not implemented yet!")); // TODO: !!! } private void loadFromSettings() { diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java index c20121a7..a82abc7a 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java @@ -4,8 +4,10 @@ import java.util.concurrent.Future; import javax.swing.SwingUtilities; import org.micromanager.lightsheetmanager.LightSheetManagerFrame; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.ListeningPanel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.data.Icons; import org.micromanager.lightsheetmanager.LightSheetManager; import org.micromanager.lightsheetmanager.gui.tabs.acquisition.AdvancedTimingPanel; @@ -28,7 +30,7 @@ import javax.swing.JLabel; import java.util.Objects; -public class AcquisitionTab extends Panel implements ListeningPanel { +public class AcquisitionTab extends Panel implements ListeningPanel, SettingsListener { // layout panel private Panel pnlRight_; @@ -83,6 +85,7 @@ public AcquisitionTab(final LightSheetManager model, final LightSheetManagerFram acqTableFrame_ = new AcquisitionTableFrame(model_.studio()); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } /** @@ -222,8 +225,8 @@ private void createUserInterface() { */ private void createEventHandlers() { - // start/stop acquisitions - btnRunAcquisition_.registerListener(e -> { + // toggle acquisition running + btnRunAcquisition_.registerListener(() -> { if (btnRunAcquisition_.isSelected()) { runAcquisition(false); } else { @@ -231,7 +234,7 @@ private void createEventHandlers() { } }); - btnPauseAcquisition_.registerListener(e -> { + btnPauseAcquisition_.registerListener(() -> { if (btnPauseAcquisition_.isSelected()) { model_.acquisitions().requestPause(); } else { @@ -239,16 +242,16 @@ private void createEventHandlers() { } }); - btnOpenPlaylist_.registerListener(e -> acqTableFrame_.setVisible(true)); + btnOpenPlaylist_.registerListener(() -> acqTableFrame_.setVisible(true)); btnOpenPlaylist_.setEnabled(false); // TODO: enable when playlist is implemented - btnSpeedTest_.registerListener(e -> runAcquisition(true)); - btnRunOverviewAcq_.registerListener(e -> { + btnSpeedTest_.registerListener(() -> runAcquisition(true)); + btnRunOverviewAcq_.registerListener(() -> { // TODO: run the overview acq }); // multiple positions - cbxUseMultiplePositions_.registerListener(e -> { + cbxUseMultiplePositions_.registerListener(() -> { final boolean selected = cbxUseMultiplePositions_.isSelected(); model_.acquisitions().settingsBuilder().useMultiplePositions(selected); model_.acquisitions().updateDurationLabels(); @@ -256,7 +259,7 @@ private void createEventHandlers() { }); // time points - cbxUseTimePoints_.registerListener(e -> { + cbxUseTimePoints_.registerListener(() -> { final boolean selected = cbxUseTimePoints_.isSelected(); model_.acquisitions().settingsBuilder().useTimePoints(selected); model_.acquisitions().updateDurationLabels(); @@ -264,7 +267,7 @@ private void createEventHandlers() { }); // use channels - cbxUseChannels_.registerListener(e -> { + cbxUseChannels_.registerListener(() -> { final boolean selected = cbxUseChannels_.isSelected(); model_.acquisitions().settingsBuilder().channelBuilder().enabled(selected); model_.acquisitions().updateDurationLabels(); @@ -272,11 +275,12 @@ private void createEventHandlers() { }); // select the acquisition mode - cmbAcquisitionModes_.registerListener(e -> - model_.acquisitions().settingsBuilder().acquisitionMode(cmbAcquisitionModes_.getSelected())); + cmbAcquisitionModes_.registerListener( + () -> model_.acquisitions().settingsBuilder() + .acquisitionMode(cmbAcquisitionModes_.getSelected())); // switches timing panels based on check box - cbxUseAdvancedTiming_.registerListener(e -> { + cbxUseAdvancedTiming_.registerListener(() -> { final boolean selected = cbxUseAdvancedTiming_.isSelected(); model_.acquisitions().settingsBuilder().useAdvancedTiming(selected); swapTimingSettingsPanels(selected); @@ -304,10 +308,6 @@ private void swapTimingSettingsPanels(final boolean useAdvancedTiming) { pnlRight_.repaint(); } - public SlicePanel getSliceSettingsPanel() { - return pnlSliceSettings_; - } - public PositionPanel getMultiPositionPanel() { return pnlMultiPositions_; } @@ -352,4 +352,24 @@ public void unselected() { } + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + // update ui elements + cmbAcquisitionModes_.setSelected(settingsScape.acquisitionMode()); + cbxUseTimePoints_.setSelected(settingsScape.isUsingTimePoints()); + cbxUseMultiplePositions_.setSelected(settingsScape.isUsingMultiplePositions()); + cbxUseChannels_.setSelected(settingsScape.channels().enabled()); + cbxUseAdvancedTiming_.setSelected(settingsScape.isUsingAdvancedTiming()); + // enable or disable ui + pnlTimePoints_.setPanelEnabled(settingsScape.isUsingTimePoints()); + pnlMultiPositions_.setPanelEnabled(settingsScape.isUsingMultiplePositions()); + pnlChannelTable_.setItemsEnabled(settingsScape.channels().enabled()); + swapTimingSettingsPanels(settingsScape.isUsingAdvancedTiming()); + // display the updates + revalidate(); + repaint(); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AutofocusTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AutofocusTab.java index 4dd4e1a8..4868cd17 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AutofocusTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AutofocusTab.java @@ -193,51 +193,51 @@ private void setSetupOptionsState(final boolean state) { private void createEventHandlers() { // general autofocus settings - cbxShowImages_.registerListener(e -> model_.acquisitions().settingsBuilder() + cbxShowImages_.registerListener(() -> model_.acquisitions().settingsBuilder() .autofocusSettingsBuilder().showImages(cbxShowImages_.isSelected())); - cbxShowGraph_.registerListener(e -> model_.acquisitions().settingsBuilder() + cbxShowGraph_.registerListener(() -> model_.acquisitions().settingsBuilder() .autofocusSettingsBuilder().showGraph(cbxShowGraph_.isSelected())); - spnNumImages_.registerListener(e -> model_.acquisitions().settingsBuilder() + spnNumImages_.registerListener(() -> model_.acquisitions().settingsBuilder() .autofocusSettingsBuilder().numImages(spnNumImages_.getInt())); - spnStepSize_.registerListener(e -> model_.acquisitions().settingsBuilder() + spnStepSize_.registerListener(() -> model_.acquisitions().settingsBuilder() .autofocusSettingsBuilder().stepSizeUm(spnStepSize_.getDouble())); - // spnToleranceUm_.registerListener(e -> model_.acquisitions().settingsBuilder() + // spnToleranceUm_.registerListener(() -> model_.acquisitions().settingsBuilder() // .autofocusSettingsBuilder().toleranceUm(spnToleranceUm_.getDouble())); - cmbAutofocusMode_.registerListener(e -> model_.acquisitions().settingsBuilder() + cmbAutofocusMode_.registerListener(() -> model_.acquisitions().settingsBuilder() .autofocusSettingsBuilder().mode(cmbAutofocusMode_.getSelected())); - cmbScoringMethod_.registerListener(e -> model_.acquisitions().settingsBuilder() + cmbScoringMethod_.registerListener(() -> model_.acquisitions().settingsBuilder() .autofocusSettingsBuilder().scoringMethod(cmbScoringMethod_.getSelected())); - btnRunAutofocus_.registerListener(e -> model_.acquisitions().autofocus().run()); + btnRunAutofocus_.registerListener(() -> model_.acquisitions().autofocus().run()); // autofocus options during acquisition - cbxAutofocusEveryPass_.registerListener(e -> { + cbxAutofocusEveryPass_.registerListener(() -> { //System.out.println("cbxAutofocusEveryPass_: " + cbxAutofocusEveryPass_.isSelected()); }); - cbxAutofocusBeforeAcq_.registerListener(e -> { + cbxAutofocusBeforeAcq_.registerListener(() -> { //System.out.println("cbxAutofocusBeforeAcq_: " + cbxAutofocusBeforeAcq_.isSelected()); }); - cmbAutofocusChannel_.registerListener(e -> { + cmbAutofocusChannel_.registerListener(() -> { //System.out.println("cmbAutofocusChannel_"); }); - spnAutofocusEveryX_.registerListener(e -> { + spnAutofocusEveryX_.registerListener(() -> { }); - spnMaxOffsetSetup_.registerListener(e -> { + spnMaxOffsetSetup_.registerListener(() -> { }); // autofocus options during setup - cbxAutoUpdateFocusFound_.registerListener(e -> - setSetupOptionsState(cbxAutoUpdateFocusFound_.isSelected())); + cbxAutoUpdateFocusFound_.registerListener( + () -> setSetupOptionsState(cbxAutoUpdateFocusFound_.isSelected())); } @Override diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/DeviceTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/DeviceTab.java index 6291d291..b6c6a062 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/DeviceTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/DeviceTab.java @@ -59,9 +59,8 @@ private void createUserInterface() { } private void createEventHandlers() { - btnCreateConfigGroup_.registerListener(e -> { - devices_.createConfigGroup(); - }); + btnCreateConfigGroup_.registerListener( + () -> devices_.createConfigGroup()); } @Override diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SettingsTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SettingsTab.java index ce16913f..3a09aa44 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SettingsTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SettingsTab.java @@ -140,27 +140,27 @@ private void createEventHandlers() { // Scan Settings if (isUsingScanSettings_) { - spnScanAcceleration_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + spnScanAcceleration_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .accelerationFactor(spnScanAcceleration_.getDouble())); - spnScanOvershootDist_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + spnScanOvershootDist_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .overshootDistance(spnScanOvershootDist_.getInt())); - spnScanRetraceSpeed_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + spnScanRetraceSpeed_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .retraceSpeed(spnScanRetraceSpeed_.getDouble())); - spnScanFirstViewAngle_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + spnScanFirstViewAngle_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .firstViewAngle(spnScanFirstViewAngle_.getDouble())); - cbxScanFromCurrentPosition_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + cbxScanFromCurrentPosition_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .fromCurrentPosition(cbxScanFromCurrentPosition_.isSelected())); - cbxScanNegativeDirection_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + cbxScanNegativeDirection_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .fromNegativeDirection(cbxScanNegativeDirection_.isSelected())); - cbxReturnToStart_.registerListener(e -> - model_.acquisitions().settingsBuilder().stageScanBuilder() + cbxReturnToStart_.registerListener( + () -> model_.acquisitions().settingsBuilder().stageScanBuilder() .returnToStart(cbxReturnToStart_.isSelected())); } @@ -169,10 +169,10 @@ private void createEventHandlers() { final ASIScanner scanner = model_.devices().device("IllumSlice"); spnSheetAxisFilterFreq_.registerListener( - e -> scanner.setFilterFreqX(spnSheetAxisFilterFreq_.getDouble())); + () -> scanner.setFilterFreqX(spnSheetAxisFilterFreq_.getDouble())); spnSliceAxisFilterFreq_.registerListener( - e -> scanner.setFilterFreqY(spnSliceAxisFilterFreq_.getDouble())); + () -> scanner.setFilterFreqY(spnSliceAxisFilterFreq_.getDouble())); } // TODO: make this work with diSPIM settings diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/AdvancedTimingPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/AdvancedTimingPanel.java index 25b81b19..b30c4d7a 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/AdvancedTimingPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/AdvancedTimingPanel.java @@ -1,17 +1,20 @@ package org.micromanager.lightsheetmanager.gui.tabs.acquisition; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.TimingSettings; import org.micromanager.lightsheetmanager.api.internal.DefaultTimingSettings; +import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.Panel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.components.Spinner; import org.micromanager.lightsheetmanager.LightSheetManager; import org.micromanager.lightsheetmanager.model.utils.NumberUtils; import java.util.Objects; -public class AdvancedTimingPanel extends Panel { +public class AdvancedTimingPanel extends Panel implements SettingsListener { private Spinner spnDelayBeforeScan_; private Spinner spnDelayBeforeLaser_; @@ -31,6 +34,7 @@ public AdvancedTimingPanel(final LightSheetManager model) { model_ = Objects.requireNonNull(model); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -92,7 +96,7 @@ private void createUserInterface() { private void createEventHandlers() { - spnDelayBeforeScan_.registerListener(e -> { + spnDelayBeforeScan_.registerListener(() -> { final double value = spnDelayBeforeScan_.getDouble(); final double rounded = NumberUtils.roundToQuarterMs(value); if (Math.abs(value - rounded) > 1e-6) { @@ -105,13 +109,13 @@ private void createEventHandlers() { model_.acquisitions().updateDurationLabels(); }); - spnScansPerSlice_.registerListener(e -> { + spnScansPerSlice_.registerListener(() -> { model_.acquisitions().settingsBuilder() .timingBuilder().scansPerSlice(spnScansPerSlice_.getInt()); model_.acquisitions().updateDurationLabels(); }); - spnScanDuration_.registerListener(e -> { + spnScanDuration_.registerListener(() -> { final double value = spnScanDuration_.getDouble(); final double rounded = NumberUtils.roundToQuarterMs(value); if (Math.abs(value - rounded) > 1e-6) { @@ -124,7 +128,7 @@ private void createEventHandlers() { model_.acquisitions().updateDurationLabels(); }); - spnDelayBeforeLaser_.registerListener(e -> { + spnDelayBeforeLaser_.registerListener(() -> { final double value = spnDelayBeforeLaser_.getDouble(); final double rounded = NumberUtils.roundToQuarterMs(value); if (Math.abs(value - rounded) > 1e-6) { @@ -137,7 +141,7 @@ private void createEventHandlers() { model_.acquisitions().updateDurationLabels(); }); - spnLaserTriggerDuration_.registerListener(e -> { + spnLaserTriggerDuration_.registerListener(() -> { final double value = spnLaserTriggerDuration_.getDouble(); final double rounded = NumberUtils.roundToQuarterMs(value); if (Math.abs(value - rounded) > 1e-6) { @@ -150,7 +154,7 @@ private void createEventHandlers() { model_.acquisitions().updateDurationLabels(); }); - spnDelayBeforeCamera_.registerListener(e -> { + spnDelayBeforeCamera_.registerListener(() -> { final double value = spnDelayBeforeCamera_.getDouble(); final double rounded = NumberUtils.roundToQuarterMs(value); if (Math.abs(value - rounded) > 1e-6) { @@ -163,7 +167,7 @@ private void createEventHandlers() { model_.acquisitions().updateDurationLabels(); }); - spnCameraTriggerDuration_.registerListener(e -> { + spnCameraTriggerDuration_.registerListener(() -> { final double value = spnCameraTriggerDuration_.getDouble(); final double rounded = NumberUtils.roundToQuarterMs(value); if (Math.abs(value - rounded) > 1e-6) { @@ -176,13 +180,13 @@ private void createEventHandlers() { model_.acquisitions().updateDurationLabels(); }); - spnCameraExposure_.registerListener(e -> { + spnCameraExposure_.registerListener(() -> { model_.acquisitions().settingsBuilder() .timingBuilder().cameraExposure(spnCameraExposure_.getDouble()); model_.acquisitions().updateDurationLabels(); }); - cbxAlternateScanDirection_.registerListener(e -> { + cbxAlternateScanDirection_.registerListener(() -> { model_.acquisitions().settingsBuilder() .timingBuilder().useAlternateScanDirection(cbxAlternateScanDirection_.isSelected()); }); @@ -204,4 +208,22 @@ public void updateSpinners() { spnCameraExposure_.setDouble(timingSettings.cameraExposure()); cbxAlternateScanDirection_.setSelected(timingSettings.useAlternateScanDirection()); } + + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + spnDelayBeforeScan_.setValue(settingsScape.timing().delayBeforeScan()); + spnScansPerSlice_.setValue(settingsScape.timing().scansPerSlice()); + spnScanDuration_.setValue(settingsScape.timing().scanDuration()); + spnDelayBeforeLaser_.setValue(settingsScape.timing().delayBeforeLaser()); + spnLaserTriggerDuration_.setValue(settingsScape.timing().laserTriggerDuration()); + spnDelayBeforeCamera_.setValue(settingsScape.timing().cameraTriggerDuration()); + spnLaserTriggerDuration_.setValue(settingsScape.timing().cameraTriggerDuration()); + spnDelayBeforeCamera_.setDouble(settingsScape.timing().cameraTriggerDuration()); + spnCameraTriggerDuration_.setDouble(settingsScape.timing().cameraTriggerDuration()); + spnCameraExposure_.setValue(settingsScape.timing().cameraExposure()); + cbxAlternateScanDirection_.setSelected(settingsScape.timing().useAlternateScanDirection()); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/CameraPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/CameraPanel.java index 1d291760..96bb898a 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/CameraPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/CameraPanel.java @@ -1,13 +1,16 @@ package org.micromanager.lightsheetmanager.gui.tabs.acquisition; import org.micromanager.lightsheetmanager.LightSheetManager; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.data.CameraData; import org.micromanager.lightsheetmanager.api.data.CameraLibrary; import org.micromanager.lightsheetmanager.api.data.CameraMode; +import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.ComboBox; import org.micromanager.lightsheetmanager.gui.components.Panel; import org.micromanager.lightsheetmanager.gui.components.RadioButton; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.model.devices.cameras.CameraBase; import javax.swing.JLabel; @@ -15,9 +18,9 @@ import java.util.List; import java.util.Objects; -public class CameraPanel extends Panel { +public class CameraPanel extends Panel implements SettingsListener { - private ComboBox cmbCameraTriggerMode_; + private ComboBox cmbCameraMode_; private RadioButton radPrimaryCamera_; private List cbxCameras_; private int selectedIndex_; @@ -29,6 +32,7 @@ public CameraPanel(final LightSheetManager model) { model_ = Objects.requireNonNull(model); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -48,7 +52,7 @@ private void createUserInterface() { modes = CameraMode.modesByDeviceLibrary(camLib); } - cmbCameraTriggerMode_ = new ComboBox<>(modes, + cmbCameraMode_ = new ComboBox<>(modes, model_.acquisitions().settings().cameraMode(), 140, 20); // validate that the logical device name exists @@ -98,22 +102,22 @@ private void createUserInterface() { add(pnlCameraSelectionRow, "wrap"); add(new JLabel("Camera Trigger Mode:"), "wrap"); - add(cmbCameraTriggerMode_, "wrap"); + add(cmbCameraMode_, "wrap"); } private void createEventHandlers() { // camera trigger mode - cmbCameraTriggerMode_.registerListener(e -> { - final CameraMode cameraMode = cmbCameraTriggerMode_.getSelected(); + cmbCameraMode_.registerListener(() -> { + final CameraMode cameraMode = cmbCameraMode_.getSelected(); model_.acquisitions().settingsBuilder().cameraMode(cameraMode); }); // select primary camera - radPrimaryCamera_.registerListener(e -> computeCameraOrder()); + radPrimaryCamera_.registerListener(this::computeCameraOrder); // active camera check boxes for (CheckBox cbx : cbxCameras_) { - cbx.registerListener(e -> computeCameraOrder()); + cbx.registerListener(this::computeCameraOrder); } } @@ -160,4 +164,18 @@ private void computeCameraOrder() { .imagingCameraOrder(cameraData.toArray(CameraData[]::new)); } + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + // TODO: add remaining props + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + cmbCameraMode_.setSelectedItem(settingsScape.cameraMode()); + // set the primary camera +// final CameraData[] cameraOrder = settingsScape.imagingCameraOrder(); +// if (cameraOrder.length > 0) { +// final String primaryCamera = cameraOrder[0].name(); +// radPrimaryCamera_.setSelected(primaryCamera, true); +// } + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/PositionPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/PositionPanel.java index 79ea6859..afe3e9a3 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/PositionPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/PositionPanel.java @@ -1,16 +1,19 @@ package org.micromanager.lightsheetmanager.gui.tabs.acquisition; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; +import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.Button; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.Panel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.components.Spinner; import org.micromanager.lightsheetmanager.gui.frames.XYZGridFrame; import org.micromanager.lightsheetmanager.LightSheetManager; import java.util.Objects; -public class PositionPanel extends Panel { +public class PositionPanel extends Panel implements SettingsListener { private Label lblPostMoveDelay_; private Spinner spnPostMoveDelay_; @@ -26,6 +29,7 @@ public PositionPanel(final LightSheetManager model, final CheckBox checkBox) { xyzGridFrame_ = new XYZGridFrame(model_); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -50,7 +54,7 @@ private void createUserInterface() { private void createEventHandlers() { // open XYZ grid - btnOpenXYZGrid_.registerListener(e -> { + btnOpenXYZGrid_.registerListener(() -> { if (model_.devices().hasDevice("SampleXY") && model_.devices().hasDevice("SampleZ")) { xyzGridFrame_.setVisible(true); @@ -61,9 +65,9 @@ private void createEventHandlers() { }); // open position list - btnEditPositionList_.registerListener(e -> model_.studio().app().showPositionList()); + btnEditPositionList_.registerListener(() -> model_.studio().app().showPositionList()); - spnPostMoveDelay_.registerListener(e -> model_.acquisitions() + spnPostMoveDelay_.registerListener(() -> model_.acquisitions() .settingsBuilder().postMoveDelay(spnPostMoveDelay_.getInt())); } @@ -77,4 +81,13 @@ public void setPanelEnabled(final boolean state) { public XYZGridFrame getXYZGridFrame() { return xyzGridFrame_; } + + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + // TODO: multi positions should probably be a part of the base acq settings + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + spnPostMoveDelay_.setValue(settingsScape.postMoveDelay()); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SavePanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SavePanel.java index 1ebdea2f..b67c00e4 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SavePanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SavePanel.java @@ -3,13 +3,16 @@ import org.micromanager.internal.utils.FileDialogs; import org.micromanager.lightsheetmanager.LightSheetManager; import org.micromanager.lightsheetmanager.LightSheetManagerFrame; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.Button; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.ComboBox; import org.micromanager.lightsheetmanager.gui.components.Panel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.components.TextField; import org.micromanager.lightsheetmanager.gui.data.Icons; +import org.micromanager.lightsheetmanager.gui.utils.DialogUtils; import org.micromanager.lightsheetmanager.model.DataStorage; import org.micromanager.lightsheetmanager.model.utils.FileUtils; @@ -20,7 +23,7 @@ import java.io.IOException; import java.util.Objects; -public class SavePanel extends Panel { +public class SavePanel extends Panel implements SettingsListener { private TextField txtSaveDirectory_; private TextField txtSaveFileName_; @@ -72,6 +75,8 @@ public SavePanel(final LightSheetManager model, final LightSheetManagerFrame fra createUserInterface(); createEventHandlers(); + + model.userSettings().addChangeListener(this); } public void createUserInterface() { @@ -125,7 +130,7 @@ public void createUserInterface() { } public void createEventHandlers() { - btnBrowse_.registerListener(e -> { + btnBrowse_.registerListener(() -> { final File result = FileDialogs.openDir(frame_, "Please select the directory to save images to...", directorySelect_ @@ -137,39 +142,47 @@ public void createEventHandlers() { }); // use the text field so we don't need to update settings - btnOpen_.registerListener(e -> - openDirectory(txtSaveDirectory_.getText())); + btnOpen_.registerListener( + () -> openDirectory(txtSaveDirectory_.getText())); - cbxSaveWhileAcquiring_.registerListener(e -> - model_.acquisitions().settingsBuilder().saveImagesDuringAcquisition( - cbxSaveWhileAcquiring_.isSelected())); + cbxSaveWhileAcquiring_.registerListener( + () -> model_.acquisitions().settingsBuilder() + .saveImagesDuringAcquisition(cbxSaveWhileAcquiring_.isSelected())); - txtSaveFileName_.registerListener(e -> - model_.acquisitions().settingsBuilder().saveNamePrefix(txtSaveFileName_.getText())); + txtSaveFileName_.registerListener( + () -> model_.acquisitions().settingsBuilder() + .saveNamePrefix(txtSaveFileName_.getText())); - cbxSaveMode_.registerListener(e -> - model_.acquisitions().settingsBuilder().saveMode(cbxSaveMode_.getSelected())); + cbxSaveMode_.registerListener( + () -> model_.acquisitions().settingsBuilder() + .saveMode(cbxSaveMode_.getSelected())); - btnSaveSettings_.registerListener(e -> { + btnSaveSettings_.registerListener(() -> { final File file = FileDialogs.save(frame_, "Save the acquisition settings to JSON...", jsonFileSave_ ); if (file != null) { - // TODO: prompt if file exists + if (file.exists()) { + final boolean clickedYes = DialogUtils.showYesNoDialog(frame_, "Confirm Overwrite", + "The file already exists, would you like to overwrite the file?"); + if (!clickedYes) { + return; // early exit => do not overwrite! + } + } + // update settings and save to file + model_.acquisitions().updateAcquisitionSettings(); FileUtils.writeStringToFile(file.toString(), model_.acquisitions().settings().toPrettyJson()); model_.studio().logs().logMessage("Acquisition settings saved to: " + file); } }); - btnLoadSettings_.registerListener(e -> { + btnLoadSettings_.registerListener(() -> { final File file = FileDialogs.openFile(frame_, "Load the acquisition settings from JSON...", jsonFileLoad_ ); if (file != null) { - // TODO: prompt to overwrite settings final String json = FileUtils.readFileToString(file.toString()); - model_.acquisitions().setAcquisitionSettingsAndBuilder( - ScapeAcquisitionSettings.fromJson(json, ScapeAcquisitionSettings.class)); + model_.userSettings().loadFromJson(json, true); model_.studio().logs().logMessage("Acquisition settings loaded from: " + file); } }); @@ -197,4 +210,11 @@ private void openDirectory(final String path) { } } + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + txtSaveDirectory_.setText(settings.saveDirectory()); + txtSaveFileName_.setText(settings.saveNamePrefix()); + cbxSaveMode_.setSelected(settings.saveMode()); + cbxSaveWhileAcquiring_.setSelected(settings.isSavingImagesDuringAcquisition()); + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SlicePanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SlicePanel.java index 7516719e..79bca30f 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SlicePanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/SlicePanel.java @@ -1,16 +1,20 @@ package org.micromanager.lightsheetmanager.gui.tabs.acquisition; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.SliceSettings; import org.micromanager.lightsheetmanager.api.data.CameraMode; +import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.Panel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.components.Spinner; import org.micromanager.lightsheetmanager.LightSheetManager; import java.util.Objects; -public class SlicePanel extends Panel { +// TODO: make a separate panel for diSPIM? +public class SlicePanel extends Panel implements SettingsListener { // regular panel private CheckBox cbxMinimizeSlicePeriod_; @@ -36,6 +40,7 @@ public SlicePanel(final LightSheetManager model) { model_ = Objects.requireNonNull(model); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -46,22 +51,19 @@ private void createUserInterface() { ); final SliceSettings sliceSettings = model_.acquisitions().settings().slice(); - final boolean isSlicePeriodMinimized = sliceSettings.periodMinimized(); + final boolean periodMinimized = sliceSettings.periodMinimized(); // regular panel lblSlicePeriod_ = new Label("Slice period [ms]:"); lblSampleExposure_ = new Label("Sample exposure [ms]:"); cbxMinimizeSlicePeriod_ = new CheckBox( - "Minimize slice period", 12, isSlicePeriodMinimized, CheckBox.RIGHT); + "Minimize slice period", 12, periodMinimized, CheckBox.RIGHT); spnSlicePeriod_ = Spinner.createDoubleSpinner( sliceSettings.period(), 0.0, Double.MAX_VALUE, 0.25); spnSampleExposure_ = Spinner.createDoubleSpinner( sliceSettings.sampleExposure(), 0.0, Double.MAX_VALUE, 0.25); - if (isSlicePeriodMinimized) { - lblSlicePeriod_.setEnabled(false); - spnSlicePeriod_.setEnabled(false); - } + setSpinnerEnabled(!periodMinimized); // TODO: this should added back in for diSPIM // if (model_.devices().adapter().geometry() == GeometryType.DISPIM) { @@ -83,7 +85,7 @@ private void createUserInterface() { // } // create the ui based on the camera trigger mode - switchUI(model_.acquisitions().settings().cameraMode()); + switchDisplayPanel(model_.acquisitions().settings().cameraMode()); } /** @@ -92,7 +94,7 @@ private void createUserInterface() { private void createEventHandlers() { // regular panel - cbxMinimizeSlicePeriod_.registerListener(e -> { + cbxMinimizeSlicePeriod_.registerListener(() -> { final boolean selected = cbxMinimizeSlicePeriod_.isSelected(); lblSlicePeriod_.setEnabled(!selected); spnSlicePeriod_.setEnabled(!selected); @@ -103,7 +105,7 @@ private void createEventHandlers() { model_.acquisitions().recalculateSliceTiming(); }); - spnSlicePeriod_.registerListener(e -> { + spnSlicePeriod_.registerListener(() -> { model_.acquisitions().settingsBuilder() .sliceBuilder().period(spnSlicePeriod_.getDouble()); // update slice timing @@ -111,7 +113,7 @@ private void createEventHandlers() { model_.acquisitions().recalculateSliceTiming(); }); - spnSampleExposure_.registerListener(e -> { + spnSampleExposure_.registerListener(() -> { model_.acquisitions().settingsBuilder() .sliceBuilder().sampleExposure(spnSampleExposure_.getDouble()); // update slice timing @@ -122,22 +124,22 @@ private void createEventHandlers() { // if (model_.devices().adapter().geometry() == GeometryType.DISPIM) { // // // virtual slit panel -// spnScanResetTime_.registerListener(e -> { +// spnScanResetTime_.registerListener(() -> { // model_.acquisitions().settingsBuilder() // .sliceLSBuilder().scanResetTime(spnScanResetTime_.getDouble()); // }); // -// spnScanSettleTime_.registerListener(e -> { +// spnScanSettleTime_.registerListener(() -> { // model_.acquisitions().settingsBuilder() // .sliceLSBuilder().scanSettleTime(spnScanSettleTime_.getDouble()); // }); // -// spnShutterWidth_.registerListener(e -> { +// spnShutterWidth_.registerListener(() -> { // model_.acquisitions().settingsBuilder() // .sliceLSBuilder().shutterWidth(spnShutterWidth_.getDouble()); // }); // -// spnShutterSpeed_.registerListener(e -> { +// spnShutterSpeed_.registerListener(() -> { // model_.acquisitions().settingsBuilder() // .sliceLSBuilder().shutterSpeedFactor(spnShutterSpeed_.getDouble()); // }); @@ -149,7 +151,7 @@ private void createEventHandlers() { * * @param cameraMode the current camera trigger mode */ - public void switchUI(final CameraMode cameraMode) { + private void switchDisplayPanel(final CameraMode cameraMode) { removeAll(); if (cameraMode != CameraMode.VIRTUAL_SLIT) { add(cbxMinimizeSlicePeriod_, "wrap"); @@ -171,4 +173,21 @@ public void switchUI(final CameraMode cameraMode) { repaint(); } + private void setSpinnerEnabled(final boolean state) { + lblSlicePeriod_.setEnabled(state); + spnSlicePeriod_.setEnabled(state); + } + + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + // TODO: add dispim part + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + spnSlicePeriod_.setDouble(settingsScape.slice().period()); + spnSampleExposure_.setDouble(settingsScape.slice().sampleExposure()); + final boolean periodMinimized = settingsScape.slice().periodMinimized(); + cbxMinimizeSlicePeriod_.setSelected(periodMinimized); + setSpinnerEnabled(!periodMinimized); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/TimePointsPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/TimePointsPanel.java index 4df9941d..00120623 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/TimePointsPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/TimePointsPanel.java @@ -1,15 +1,17 @@ package org.micromanager.lightsheetmanager.gui.tabs.acquisition; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.Panel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.components.Spinner; import org.micromanager.lightsheetmanager.LightSheetManager; import java.util.Objects; -public class TimePointsPanel extends Panel { +public class TimePointsPanel extends Panel implements SettingsListener { private Label lblNumTimePoints_; private Label lblTimePointInterval_; @@ -23,6 +25,7 @@ public TimePointsPanel(final LightSheetManager model, final CheckBox cbxUseTimeP model_ = Objects.requireNonNull(model); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -52,12 +55,12 @@ private void createUserInterface() { // TODO: update duration labels private void createEventHandlers() { - spnNumTimePoints_.registerListener(e -> { + spnNumTimePoints_.registerListener(() -> { model_.acquisitions().settingsBuilder().numTimePoints(spnNumTimePoints_.getInt()); model_.acquisitions().updateDurationLabels(); }); - spnTimePointInterval_.registerListener(e -> { + spnTimePointInterval_.registerListener(() -> { model_.acquisitions().settingsBuilder().timePointInterval(spnTimePointInterval_.getDouble()); model_.acquisitions().updateDurationLabels(); }); @@ -70,4 +73,13 @@ public void setPanelEnabled(final boolean state) { spnTimePointInterval_.setEnabled(state); } + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + // TODO: timepoints should probably be a part of the base acq settings + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + spnNumTimePoints_.setValue(settingsScape.numTimePoints()); + spnTimePointInterval_.setValue(settingsScape.timePointInterval()); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/VolumePanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/VolumePanel.java index ecba902d..cd445d76 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/VolumePanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/acquisition/VolumePanel.java @@ -1,17 +1,22 @@ package org.micromanager.lightsheetmanager.gui.tabs.acquisition; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.VolumeSettings; import org.micromanager.lightsheetmanager.api.data.GeometryType; -import org.micromanager.lightsheetmanager.api.internal.DefaultVolumeSettings; import org.micromanager.lightsheetmanager.LightSheetManager; +import org.micromanager.lightsheetmanager.api.internal.DispimAcquisitionSettings; +import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.ComboBox; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.Panel; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.gui.components.Spinner; import java.util.Objects; -public class VolumePanel extends Panel { +public class VolumePanel extends Panel implements SettingsListener { + + private GeometryType geometryType_; private ComboBox cmbNumViews_; private ComboBox cmbFirstView_; @@ -27,6 +32,7 @@ public VolumePanel(final LightSheetManager model) { model_ = Objects.requireNonNull(model); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -38,12 +44,10 @@ private void createUserInterface() { setAbsoluteSize(275, 115); - final GeometryType geometryType = model_.devices().adapter().geometry(); - final int numImagingPaths = model_.devices().adapter().numImagingPaths(); - - final VolumeSettings volumeSettings = model_.acquisitions().settings().volume(); + geometryType_ = model_.devices().adapter().geometry(); // create labels for combo boxes + final int numImagingPaths = model_.devices().adapter().numImagingPaths(); Integer[] viewOptions = new Integer[numImagingPaths]; for (int i = 0; i < numImagingPaths; i++) { viewOptions[i] = i + 1; @@ -57,6 +61,7 @@ private void createUserInterface() { // if the number of sides has changed and the firstView or numViews is larger // than the number of sides, default to 1. + final VolumeSettings volumeSettings = model_.acquisitions().settings().volume(); int numViews = volumeSettings.numViews(); int firstView = volumeSettings.firstView(); if (numViews > viewOptions.length) { @@ -70,13 +75,16 @@ private void createUserInterface() { cmbFirstView_ = new ComboBox<>(viewOptions, firstView, 60, 20); spnViewDelay_ = Spinner.createDoubleSpinner( - volumeSettings.delayBeforeView(), 0.0, Double.MAX_VALUE, 0.25); + volumeSettings.delayBeforeView(), + 0.0, Double.MAX_VALUE, 0.25); spnSliceStepSize_ = Spinner.createDoubleSpinner( - volumeSettings.sliceStepSize(), 0.0, Double.MAX_VALUE, 0.1); + volumeSettings.sliceStepSize(), + 0.0, Double.MAX_VALUE, 0.1); spnNumSlices_ = Spinner.createIntegerSpinner( - volumeSettings.slicesPerView(), 1, Integer.MAX_VALUE, 1); + volumeSettings.slicesPerView(), + 1, Integer.MAX_VALUE, 1); - switch (geometryType) { + switch (geometryType_) { case DISPIM: add(lblNumViews, ""); add(cmbNumViews_, "wrap"); @@ -104,31 +112,50 @@ private void createUserInterface() { private void createEventHandlers() { - cmbNumViews_.registerListener(e -> { - model_.acquisitions().settingsBuilder().volumeBuilder() - .numViews(cmbNumViews_.getSelected()); - }); + if (geometryType_ == GeometryType.DISPIM) { + cmbNumViews_.registerListener(() -> { + model_.acquisitions().settingsBuilder().volumeBuilder() + .numViews(cmbNumViews_.getSelected()); + }); - cmbFirstView_.registerListener(e -> { - model_.acquisitions().settingsBuilder().volumeBuilder() - .firstView(cmbFirstView_.getSelected()); - }); + cmbFirstView_.registerListener(() -> { + model_.acquisitions().settingsBuilder().volumeBuilder() + .firstView(cmbFirstView_.getSelected()); + }); + } - spnViewDelay_.registerListener(e -> { + spnViewDelay_.registerListener(() -> { model_.acquisitions().settingsBuilder().volumeBuilder() .delayBeforeView(spnViewDelay_.getDouble()); model_.acquisitions().updateDurationLabels(); }); - spnNumSlices_.registerListener(e -> { + spnNumSlices_.registerListener(() -> { model_.acquisitions().settingsBuilder().volumeBuilder() .slicesPerView(spnNumSlices_.getInt()); model_.acquisitions().updateDurationLabels(); }); - spnSliceStepSize_.registerListener(e -> { + spnSliceStepSize_.registerListener(() -> { model_.acquisitions().settingsBuilder().volumeBuilder() .sliceStepSize(spnSliceStepSize_.getDouble()); }); } + + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + spnViewDelay_.setValue(settingsScape.volume().delayBeforeView()); + spnNumSlices_.setValue(settingsScape.volume().slicesPerView()); + spnSliceStepSize_.setValue(settingsScape.volume().sliceStepSize()); + } else if (settings instanceof DispimAcquisitionSettings) { + var settingsDispim = (DispimAcquisitionSettings) settings; + cmbNumViews_.setSelectedItem(settingsDispim.volume().numViews()); + cmbFirstView_.setSelectedItem(settingsDispim.volume().firstView()); + spnViewDelay_.setValue(settingsDispim.volume().delayBeforeView()); + spnNumSlices_.setValue(settingsDispim.volume().slicesPerView()); + spnSliceStepSize_.setValue(settingsDispim.volume().sliceStepSize()); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/channels/ChannelTablePanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/channels/ChannelTablePanel.java index 0a7a118d..a687f878 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/channels/ChannelTablePanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/channels/ChannelTablePanel.java @@ -1,11 +1,14 @@ package org.micromanager.lightsheetmanager.gui.tabs.channels; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; +import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; import org.micromanager.lightsheetmanager.gui.components.Button; import org.micromanager.lightsheetmanager.gui.components.CheckBox; import org.micromanager.lightsheetmanager.gui.components.ComboBox; import org.micromanager.lightsheetmanager.gui.components.Panel; import org.micromanager.lightsheetmanager.LightSheetManager; import org.micromanager.lightsheetmanager.api.data.ChannelMode; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.lightsheetmanager.model.channels.ChannelSpec; import javax.swing.JLabel; @@ -14,7 +17,7 @@ /** * This panel contains the ChannelTable and controls. */ -public class ChannelTablePanel extends Panel { +public class ChannelTablePanel extends Panel implements SettingsListener { private JLabel lblChannelGroup_; private JLabel lblChangeChannel_; @@ -35,6 +38,7 @@ public ChannelTablePanel(final LightSheetManager model, final CheckBox checkBox) table_ = new ChannelTable(model_); createUserInterface(); createEventHandlers(); + model.userSettings().addChangeListener(this); } private void createUserInterface() { @@ -71,7 +75,7 @@ private void createUserInterface() { private void createEventHandlers() { // select channel group - cmbChannelGroup_.registerListener(e -> { + cmbChannelGroup_.registerListener(() -> { final String channelGroup = cmbChannelGroup_.getSelected(); table_.updatePresetComboBoxes(channelGroup); // set the channel group to use when we get the channels @@ -84,7 +88,7 @@ private void createEventHandlers() { }); // add channel - btnAddChannel_.registerListener(e -> { + btnAddChannel_.registerListener(() -> { table_.getTableModel().addEmptyChannel(); final ChannelSpec[] channels = table_.getData().getChannels(); model_.acquisitions().settingsBuilder().channelBuilder().data(channels); @@ -93,7 +97,7 @@ private void createEventHandlers() { }); // remove channel - btnRemoveChannel_.registerListener(e -> { + btnRemoveChannel_.registerListener(() -> { final int row = table_.getTable().getSelectedRow(); if (row != -1) { // is any row selected? table_.getTableModel().removeChannel(row); @@ -104,7 +108,7 @@ private void createEventHandlers() { }); // refresh channel table - btnRefresh_.registerListener(e -> { + btnRefresh_.registerListener(() -> { final String channelGroup = model_.acquisitions().settings().channels().group(); final String[] groups = table_.getChannelGroups(); cmbChannelGroup_.removeAllItems(); @@ -120,7 +124,7 @@ private void createEventHandlers() { }); // select channel mode - cmbChannelMode_.registerListener(e -> { + cmbChannelMode_.registerListener(() -> { model_.acquisitions().settingsBuilder().channelBuilder() .mode(cmbChannelMode_.getSelected()); }); @@ -144,4 +148,13 @@ public void setItemsEnabled(final boolean state) { table_.setHeaderRowColor(state); } + @Override + public void onSettingsChanged(final AcquisitionSettings settings) { + if (settings instanceof ScapeAcquisitionSettings) { + var settingsScape = (ScapeAcquisitionSettings) settings; + cmbChannelGroup_.setSelectedItem(settingsScape.channels().group()); + cmbChannelMode_.setSelected(settingsScape.channels().mode()); + setItemsEnabled(settingsScape.channels().enabled()); + } + } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/ControlPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/ControlPanel.java index c317c5e1..ddfc4a09 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/ControlPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/ControlPanel.java @@ -10,8 +10,8 @@ import org.micromanager.lightsheetmanager.model.positions.Subscriber; import javax.swing.JLabel; +import javax.swing.SwingUtilities; import java.awt.Dimension; -import java.awt.EventQueue; import java.awt.geom.Point2D; import java.util.Objects; @@ -154,14 +154,14 @@ private void createEventHandlers() { if (deviceType_ == DeviceType.XYStageDevice) { switch (axis_) { case X: - txtAbsoluteMove_.registerListener(e -> - setXPosition(Double.parseDouble(txtAbsoluteMove_.getText()))); - btnRelMovePlus_.registerListener(e -> - setRelativeXPosition(Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnRelMoveMinus_.registerListener(e -> - setRelativeXPosition(-Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnMoveToZero_.registerListener(e -> setXPosition(0.0)); - btnSetZero_.registerListener(e -> { + txtAbsoluteMove_.registerListener( + () -> setXPosition(Double.parseDouble(txtAbsoluteMove_.getText()))); + btnRelMovePlus_.registerListener( + () -> setRelativeXPosition(Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnRelMoveMinus_.registerListener( + () -> setRelativeXPosition(-Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnMoveToZero_.registerListener(() -> setXPosition(0.0)); + btnSetZero_.registerListener(() -> { final boolean result = DialogUtils.showYesNoDialog(btnSetZero_, "", "This will change the coordinate system. Are you sure you would like to proceed?"); if (result) { @@ -170,14 +170,14 @@ private void createEventHandlers() { }); break; case Y: - txtAbsoluteMove_.registerListener(e -> - setYPosition(Double.parseDouble(txtAbsoluteMove_.getText()))); - btnRelMovePlus_.registerListener(e -> - setRelativeYPosition(Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnRelMoveMinus_.registerListener(e -> - setRelativeYPosition(-Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnMoveToZero_.registerListener(e -> setYPosition(0.0)); - btnSetZero_.registerListener(e -> { + txtAbsoluteMove_.registerListener( + () -> setYPosition(Double.parseDouble(txtAbsoluteMove_.getText()))); + btnRelMovePlus_.registerListener( + () -> setRelativeYPosition(Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnRelMoveMinus_.registerListener( + () -> setRelativeYPosition(-Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnMoveToZero_.registerListener(() -> setYPosition(0.0)); + btnSetZero_.registerListener(() -> { final boolean result = DialogUtils.showYesNoDialog(btnSetZero_, "", "This will change the coordinate system. Are you sure you would like to proceed?"); if (result) { @@ -191,14 +191,14 @@ private void createEventHandlers() { } else if (deviceType_ == DeviceType.StageDevice) { // single axis device - txtAbsoluteMove_.registerListener(e -> - setPosition(Double.parseDouble(txtAbsoluteMove_.getText()))); - btnRelMovePlus_.registerListener(e -> - setRelativePosition(Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnRelMoveMinus_.registerListener(e -> - setRelativePosition(-Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnMoveToZero_.registerListener(e -> setPosition(0.0)); - btnSetZero_.registerListener(e -> { + txtAbsoluteMove_.registerListener( + () -> setPosition(Double.parseDouble(txtAbsoluteMove_.getText()))); + btnRelMovePlus_.registerListener( + () -> setRelativePosition(Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnRelMoveMinus_.registerListener( + () -> setRelativePosition(-Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnMoveToZero_.registerListener(() -> setPosition(0.0)); + btnSetZero_.registerListener(() -> { final boolean result = DialogUtils.showYesNoDialog(btnSetZero_, "", "This will change the coordinate system. Are you sure you would like to proceed?"); if (result) { @@ -209,22 +209,22 @@ private void createEventHandlers() { // do not add btnSetZero_ to GalvoDevices switch (axis_) { case X: - txtAbsoluteMove_.registerListener(e -> - setPositionGalvoX(Double.parseDouble(txtAbsoluteMove_.getText()))); - btnRelMovePlus_.registerListener(e -> - setRelativeGalvoPositionX(Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnRelMoveMinus_.registerListener(e -> - setRelativeGalvoPositionX(-Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnMoveToZero_.registerListener(e -> setPositionGalvoX(0.0)); + txtAbsoluteMove_.registerListener( + () -> setPositionGalvoX(Double.parseDouble(txtAbsoluteMove_.getText()))); + btnRelMovePlus_.registerListener( + () -> setRelativeGalvoPositionX(Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnRelMoveMinus_.registerListener( + () -> setRelativeGalvoPositionX(-Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnMoveToZero_.registerListener(() -> setPositionGalvoX(0.0)); break; case Y: - txtAbsoluteMove_.registerListener(e -> - setPositionGalvoY(Double.parseDouble(txtAbsoluteMove_.getText()))); - btnRelMovePlus_.registerListener(e -> - setRelativeGalvoPositionY(Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnRelMoveMinus_.registerListener(e -> - setRelativeGalvoPositionY(-Double.parseDouble(txtRelMoveStepSize_.getText()))); - btnMoveToZero_.registerListener(e -> setPositionGalvoY(0.0)); + txtAbsoluteMove_.registerListener( + () -> setPositionGalvoY(Double.parseDouble(txtAbsoluteMove_.getText()))); + btnRelMovePlus_.registerListener( + () -> setRelativeGalvoPositionY(Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnRelMoveMinus_.registerListener( + () -> setRelativeGalvoPositionY(-Double.parseDouble(txtRelMoveStepSize_.getText()))); + btnMoveToZero_.registerListener(() -> setPositionGalvoY(0.0)); break; default: break; @@ -494,10 +494,10 @@ private double getGalvoPositionY() { @Override public void update(String topic, Object value) { - //System.out.println("topic: " + topic + " obj:" + value); - EventQueue.invokeLater(() -> { - lblPosition_.setText(String.format("%.3f %s", updateMethod_.update(), units_)); - }); + //System.out.println("topic: " + topic + " obj:" + value); + SwingUtilities.invokeLater(() -> { + lblPosition_.setText(String.format("%.3f %s", updateMethod_.update(), units_)); + }); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/NavigationPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/NavigationPanel.java index 6fc011f9..8387d9c6 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/NavigationPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/navigation/NavigationPanel.java @@ -222,7 +222,7 @@ private void createUserInterface() { private void createEventHandlers() { // refresh devices and ui - btnRefreshPanel_.registerListener(e -> { + btnRefreshPanel_.registerListener(() -> { removeAll(); createUserInterface(); createEventHandlers(); @@ -234,10 +234,10 @@ private void createEventHandlers() { }); // halt stage devices - btnHaltDevices_.registerListener(e -> model_.devices().haltDevices()); + btnHaltDevices_.registerListener(() -> model_.devices().haltDevices()); // position polling - cbxPollPositions_.registerListener(e -> { + cbxPollPositions_.registerListener(() -> { final boolean isSelected = cbxPollPositions_.isSelected(); model_.pluginSettings().setPollingPositions(isSelected); if (isSelected) { diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java index 7754fccf..caf5bebe 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java @@ -158,51 +158,51 @@ private void createUserInterface() { private void createEventHandlers() { // first panel - //btnPlotProfile_.registerListener(e -> { + //btnPlotProfile_.registerListener(() -> { //System.out.println("do something here..."); //}); // second panel -// cbxAutoSheetWidth_.registerListener(e -> { +// cbxAutoSheetWidth_.registerListener(() -> { // final boolean state = cbxAutoSheetWidth_.isSelected(); // model_.acquisitions().settingsBuilder() // .sheetCalibrationBuilder(pathNum_).useAutoSheetWidth(state); // setEnabledSheetWidth(state); // }); // -// sldSheetWidth_.registerListener(e -> { +// sldSheetWidth_.registerListener(() -> { // final double value = sldSheetWidth_.getDouble(); // model_.acquisitions().settingsBuilder() // .sheetCalibrationBuilder(pathNum_).sheetWidth(value); // //System.out.println("sheetWidth value: " + value); // }); // -// sldSheetOffset_.registerListener(e -> { +// sldSheetOffset_.registerListener(() -> { // final double value = sldSheetOffset_.getDouble(); // model_.acquisitions().settingsBuilder() // .sheetCalibrationBuilder(pathNum_).sheetOffset(value); // final String strValue = String.format("%.3f", value); // currentOffset_ = value; -// EventQueue.invokeLater(() -> { +// SwingUtilities.invokeLater(() -> { // txtSheetOffset_.setText(strValue); // lblSlopeOffset_.setText(strValue); // }); // //System.out.println("sheetOffset value: " + strValue); // }); - txtSheetOffset_.registerListener(e -> { + txtSheetOffset_.registerListener(() -> { final double value = Double.parseDouble(txtSheetOffset_.getText()); //final double total = Math.max(-1.0, Math.min(1.0, value)); model_.acquisitions().settingsBuilder() .sheetCalibrationBuilder().sheetOffset(value); // currentOffset_ = total; -// EventQueue.invokeLater(() -> { +// SwingUtilities.invokeLater(() -> { // lblSlopeOffset_.setText(String.format("%.3f", total)); // //sldSheetOffset_.setDouble(total); // }); }); -// btnCenterOffset_.registerListener(e -> { +// btnCenterOffset_.registerListener(() -> { // //System.out.println("center offset pressed"); // model_.acquisitions().settingsBuilder() // .sheetCalibrationBuilder(pathNum_).sheetOffset(0.0); @@ -213,7 +213,7 @@ private void createEventHandlers() { // }); // // // TODO: buttons -// btnSheetOffsetMinus_.registerListener(e -> { +// btnSheetOffsetMinus_.registerListener(() -> { // //final double value = model_.acquisitions().getAcquisitionSettings() // // .sheetCalibration(pathNum_).sheetOffset() - 0.01; // currentOffset_ -= 0.01; @@ -225,7 +225,7 @@ private void createEventHandlers() { // sldSheetOffset_.setDouble(value); // }); // -// btnSheetOffsetPlus_.registerListener(e -> { +// btnSheetOffsetPlus_.registerListener(() -> { //// final double value = model_.acquisitions().getAcquisitionSettings() //// .sheetCalibration(pathNum_).sheetOffset() + 0.01; // currentOffset_ += 0.01; @@ -237,10 +237,10 @@ private void createEventHandlers() { // sldSheetOffset_.setDouble(value); // }); -// btnSheetWidthMinus_.registerListener(e -> { +// btnSheetWidthMinus_.registerListener(() -> { // }); // -// btnSheetWidthPlus_.registerListener(e -> { +// btnSheetWidthPlus_.registerListener(() -> { // }); } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CameraPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CameraPanel.java index 927f9481..a87f8fa3 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CameraPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CameraPanel.java @@ -47,9 +47,6 @@ private void createUserInterface() { "[]5[]" ); - // register micro-manager events - model_.studio().events().registerForEvents(this); - Button.setDefaultSize(80, 26); btnImagingPath_ = new Button("Imaging"); btnMultiPath_ = new Button("Multi"); @@ -74,7 +71,6 @@ private void createUserInterface() { add(btnLiveMode_, "span 2"); break; case SCAPE: - //btnInvertedPath_.setAbsoluteSize(165, 26); add(btnInvertedPath_, "wrap"); add(btnLiveMode_, ""); break; @@ -88,29 +84,28 @@ private void createEventHandlers() { switch (geometryType) { case DISPIM: - btnImagingPath_.registerListener(e -> { + btnImagingPath_.registerListener(() -> { }); - btnMultiPath_.registerListener(e -> { + btnMultiPath_.registerListener(() -> { }); - btnEpiPath_.registerListener(e -> { + btnEpiPath_.registerListener(() -> { }); - btnInvertedPath_.registerListener(e -> { + btnInvertedPath_.registerListener(() -> { }); - btnLiveMode_.registerListener(e -> { + btnLiveMode_.registerListener(() -> { }); break; case SCAPE: - //btnInvertedPath_.setText("Preview"); - btnInvertedPath_.registerListener(e -> { + btnInvertedPath_.registerListener(() -> { closeLiveModeWindow(); final CameraBase camera = model_.devices().device("PreviewCamera"); if (camera != null) { @@ -131,7 +126,7 @@ private void createEventHandlers() { }); // live mode - btnLiveMode_.registerListener(e -> { + btnLiveMode_.registerListener(() -> { closeLiveModeWindow(); final CameraBase camera = model_.devices().firstImagingCamera(); if (camera != null) { @@ -170,18 +165,19 @@ private void closeLiveModeWindow() { } } - @Subscribe - public void liveModeListener(LiveModeEvent event) { - if (!model_.studio().live().isLiveModeOn()) { - if (isPreviewPressed) { - isPreviewPressed = false; - btnInvertedPath_.setState(false); - } - if (isLivePressed) { - isLivePressed = false; - btnLiveMode_.setState(false);; - } - } - } + // TODO: do we want to subscribe to events? +// @Subscribe +// public void liveModeListener(LiveModeEvent event) { +// if (!model_.studio().live().isLiveModeOn()) { +// if (isPreviewPressed) { +// isPreviewPressed = false; +// btnInvertedPath_.setState(false); +// } +// if (isLivePressed) { +// isLivePressed = false; +// btnLiveMode_.setState(false);; +// } +// } +// } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java index 1c99beeb..533269da 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java @@ -72,21 +72,21 @@ private void createEventHandlers() { if (isUsingPLogic_) { final ASIScanner scanner = model_.devices().device("IllumSlice"); - cbxBeamExc_.registerListener(e -> { + cbxBeamExc_.registerListener(() -> { scanner.setBeamOn(cbxBeamExc_.isSelected()); //System.out.println("set beam on: " + cbxBeamExc_.isSelected()); }); } - cbxSheetExc_.registerListener(e -> { + cbxSheetExc_.registerListener(() -> { }); - cbxBeamEpi_.registerListener(e -> { + cbxBeamEpi_.registerListener(() -> { }); - cbxSheetEpi_.registerListener(e -> { + cbxSheetEpi_.registerListener(() -> { }); } @@ -99,7 +99,6 @@ public void selected() { if (isUsingPLogic_) { final ASIScanner scanner = model_.devices().device("IllumSlice"); - if (scanner != null && isBeamOn && !scanner.isBeamOn()) { scanner.setBeamOn(true); } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java index e0453263..cc8a69d9 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java @@ -51,15 +51,15 @@ private void createUserInterface() { private void createEventHandlers() { - cmbJoystick_.registerListener(e -> { + cmbJoystick_.registerListener(() -> { }); - cmbLeftWheel_.registerListener(e -> { + cmbLeftWheel_.registerListener(() -> { }); - cmbRightWheel_.registerListener(e -> { + cmbRightWheel_.registerListener(() -> { }); diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java index df961c89..10e2e289 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java @@ -154,7 +154,7 @@ private void createEventHandlers() { final ASIPiezo piezo = model_.devices().device("ImagingFocus"); final ASIScanner scanner = model_.devices().device("IllumSlice"); - btnUpdate_.registerListener(e -> { + btnUpdate_.registerListener(() -> { if (scanner.isBeamOn()) { final double rate = model_.acquisitions().settings() .sliceCalibration().slope(); @@ -184,14 +184,14 @@ private void createEventHandlers() { // txtStepSize_.registerListener(e -> { // }); - txtSlope_.registerListener(e -> { + txtSlope_.registerListener(() -> { final double slope = Double.parseDouble(txtSlope_.getText()); model_.acquisitions().settingsBuilder() .sliceCalibrationBuilder().slope(slope); lblSlopeValue_.setText(String.format("%.3f μm/°", slope)); }); - txtOffset_.registerListener(e -> { + txtOffset_.registerListener(() -> { final double offset = Double.parseDouble(txtOffset_.getText()); model_.acquisitions().settingsBuilder() .sliceCalibrationBuilder().offset(offset); @@ -202,7 +202,7 @@ private void createEventHandlers() { .sheetCalibrationBuilder().imagingCenter(offset); }); - btnRunAutofocus_.registerListener(e -> { + btnRunAutofocus_.registerListener(() -> { model_.acquisitions().autofocus().run(); }); } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PositionPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PositionPanel.java index 39d8f9a1..aa64a431 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PositionPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PositionPanel.java @@ -10,8 +10,8 @@ import org.micromanager.lightsheetmanager.model.positions.Subscriber; import javax.swing.JLabel; +import javax.swing.SwingUtilities; import java.awt.Dimension; -import java.awt.EventQueue; import java.awt.geom.Point2D; import java.util.Objects; @@ -183,7 +183,7 @@ private void createEventHandlers() { final ASIPiezo piezo = model_.devices().device("ImagingFocus"); final ASIScanner scanner = model_.devices().device("IllumSlice"); - btnImagingCenterSet_.registerListener(e -> { + btnImagingCenterSet_.registerListener(() -> { // FIXME: check for piezo limits! final double piezoPosition = piezo.getPosition(); model_.acquisitions().settingsBuilder() @@ -191,7 +191,7 @@ private void createEventHandlers() { lblImagingCenterValue_.setText(String.format("%.3f μm", piezoPosition)); }); - btnImagingCenterGo_.registerListener(e -> { + btnImagingCenterGo_.registerListener(() -> { // FIXME: make sure this is the same as original plugin, diSPIM also moves Scanner with computeGalvoFromPiezo final double imagingCenter = model_.acquisitions().settingsBuilder().build() .sheetCalibration().imagingCenter(); @@ -199,23 +199,23 @@ private void createEventHandlers() { lblImagingPositionValue_.setText(String.format("%.3f μm", piezo.getPosition())); }); - btnImagingZero_.registerListener(e -> { + btnImagingZero_.registerListener(() -> { piezo.setPosition(0.0); lblImagingPositionValue_.setText(String.format("%.3f μm", piezo.getPosition())); }); - btnSliceZero_.registerListener(e -> { + btnSliceZero_.registerListener(() -> { final double xValue = scanner.getPosition().x; scanner.setPosition(xValue, 0.0); lblSlicePositionValue_.setText(String.format("%.3f °", scanner.getPosition().y)); }); - txtImagingPosition_.registerListener(e -> { + txtImagingPosition_.registerListener(() -> { piezo.setPosition(Double.parseDouble(txtImagingPosition_.getText())); lblImagingPositionValue_.setText(String.format("%.3f μm", piezo.getPosition())); }); - txtSlicePosition_.registerListener(e -> { + txtSlicePosition_.registerListener(() -> { final double xValue = scanner.getPosition().x; scanner.setPosition(xValue, Double.parseDouble(txtSlicePosition_.getText())); lblSlicePositionValue_.setText(String.format("%.3f °", scanner.getPosition().y)); @@ -229,7 +229,7 @@ public void setImagingCenterValue(final double value) { @Override public void update(String topic, Object value) { - EventQueue.invokeLater(() -> { + SwingUtilities.invokeLater(() -> { if (topic.equals("ImagingFocus")) { lblImagingPositionValue_.setText(String.format("%.3f μm", (double)value)); } else if (topic.equals("IllumSlice")) { diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SingleAxisPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SingleAxisPanel.java index 03b82f9d..18562c88 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SingleAxisPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SingleAxisPanel.java @@ -69,20 +69,16 @@ private void createUserInterface() { private void createEventHandlers() { if (isUsingPLogic_) { - final ASIScanner galvo = model_.devices() - .device("IllumSlice"); + final ASIScanner galvo = model_.devices().device("IllumSlice"); - cbxPattern_.registerListener(e -> { - galvo.sa().setPatternY(cbxPattern_.getSelected()); - }); + cbxPattern_.registerListener( + () -> galvo.sa().setPatternY(cbxPattern_.getSelected())); - spnAmplitude_.registerListener(e -> { - galvo.sa().setAmplitudeY(spnAmplitude_.getDouble()); - }); + spnAmplitude_.registerListener( + () -> galvo.sa().setAmplitudeY(spnAmplitude_.getDouble())); - spnPeriod_.registerListener(e -> { - galvo.sa().setPeriodY(spnPeriod_.getInt()); - }); + spnPeriod_.registerListener( + () -> galvo.sa().setPeriodY(spnPeriod_.getInt())); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowEventMethod.java b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowEventMethod.java deleted file mode 100644 index f747e6fd..00000000 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowEventMethod.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.micromanager.lightsheetmanager.gui.utils; - -import java.util.EventObject; - -@FunctionalInterface -public interface WindowEventMethod { - void run(EventObject event); -} diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java index 87a4b214..fa2dd994 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java @@ -2,9 +2,14 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.Objects; +import java.util.function.Consumer; import javax.swing.JFrame; +/** + * Utilities for + */ public final class WindowUtils { /** This class should not be instantiated. */ @@ -13,38 +18,76 @@ private WindowUtils() { } /** - * Returns true if the window is displayable and not null. + * Returns true if the window is open. * * @param frame the frame to check * @return true if the window is open */ public static boolean isOpen(final JFrame frame) { - return frame != null && frame.isDisplayable(); + return frame != null && frame.isDisplayable() && frame.isVisible(); } /** - * Creates a window event object and dispatches the close event. + * Returns true if the window is minimized. + * + * @param frame the frame to check + * @return true if the window is minimized + */ + public static boolean isMinimized(final JFrame frame) { + return frame != null && frame.getState() == JFrame.ICONIFIED; + } + + /** + * Creates a window event object and dispatches the "window is closing" event. * * @param frame the frame to close */ public static void close(final JFrame frame) { - final WindowEvent windowEvent = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING); - frame.dispatchEvent(windowEvent); + frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); } /** - * Registers a listener on the JFrame object that listens for the window closing event. + * Registers a listener on the {@link JFrame} that listens for the "window is closing" event. + * Window's 'X' button clicked, use for save dialogs and shutting down hardware. * * @param frame the frame to register the listener - * @param method the method to run on the window closing event + * @param action the {@link Consumer} to run when the window is closing; + * receives the {@link WindowEvent} as an argument. */ - public static void registerWindowClosingEvent(final JFrame frame, final WindowEventMethod method) { + public static void registerWindowClosingEvent(final JFrame frame, final Consumer action) { + Objects.requireNonNull(action, "The closing event cannot be null"); + if (frame == null) { + return; // early exit => do nothing + } + frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent event) { - method.run(event); + action.accept(event); + } + }); + } + + /** + * Registers a listener on the {@link JFrame} that listens for the "window is closed" event. + * Window is fully disposed, use to set references to null and free memory. + * + * @param frame the frame to register the listener + * @param action the {@link Consumer} to run when the window is closed; + * receives the {@link WindowEvent} as an argument. + */ + public static void registerWindowClosedEvent(final JFrame frame, final Consumer action) { + Objects.requireNonNull(action, "The closed event cannot be null"); + if (frame == null) { + return; // early exit => do nothing + } + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(final WindowEvent event) { + action.accept(event); } }); } -} \ No newline at end of file +} diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/PLogicDispim.java b/src/main/java/org/micromanager/lightsheetmanager/model/PLogicDispim.java index 37811cec..6430e743 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/PLogicDispim.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/PLogicDispim.java @@ -10,7 +10,6 @@ import org.micromanager.lightsheetmanager.api.data.DispimDevice; import org.micromanager.lightsheetmanager.api.data.GeometryType; import org.micromanager.lightsheetmanager.api.internal.DispimAcquisitionSettings; -import org.micromanager.lightsheetmanager.api.internal.DefaultTimingSettings; import org.micromanager.lightsheetmanager.model.channels.ChannelSpec; import org.micromanager.lightsheetmanager.api.data.AcquisitionMode; import org.micromanager.lightsheetmanager.api.data.ChannelMode; diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/PLogicScape.java b/src/main/java/org/micromanager/lightsheetmanager/model/PLogicScape.java index ce49ac8e..587f0da3 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/PLogicScape.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/PLogicScape.java @@ -10,7 +10,6 @@ import org.micromanager.lightsheetmanager.api.data.GeometryType; import org.micromanager.lightsheetmanager.api.data.ChannelMode; import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; -import org.micromanager.lightsheetmanager.api.internal.DefaultTimingSettings; import org.micromanager.lightsheetmanager.model.channels.ChannelSpec; import org.micromanager.lightsheetmanager.model.devices.cameras.CameraBase; import org.micromanager.lightsheetmanager.model.devices.vendor.ASIPLogic; diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java b/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java index b3bddf6c..c6bcf870 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java @@ -4,11 +4,16 @@ import mmcorej.org.json.JSONObject; import org.micromanager.UserProfile; import org.micromanager.lightsheetmanager.LightSheetManager; +import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.api.data.GeometryType; import org.micromanager.lightsheetmanager.api.internal.ScapeAcquisitionSettings; +import org.micromanager.lightsheetmanager.gui.components.SettingsListener; import org.micromanager.propertymap.MutablePropertyMapView; +import javax.swing.SwingUtilities; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Objects; import java.util.Optional; @@ -33,6 +38,8 @@ public class UserSettings { // Note: increase this value based on the amount of nested json in the settings private static final int MAX_RECURSION_DEPTH_JSON = 4; + private final List listeners = new ArrayList<>(); + private final LightSheetManager model_; public UserSettings(final LightSheetManager model) { @@ -57,7 +64,7 @@ public MutablePropertyMapView get() { * * @return a {@code String} containing the name */ - public String getUserName() { + public String userName() { return userName_; } @@ -75,6 +82,7 @@ public void load() { // get JSON from settings based on microscope geometry type final GeometryType geometryType = model_.devices().adapter().geometry(); + // get the JSON from the user settings based on geometry type final String key = SETTINGS_PREFIX + geometryType.toString().toUpperCase(); final String json = settings_.getString(key, SETTINGS_NOT_FOUND); @@ -83,17 +91,12 @@ public void load() { model_.studio().logs().logDebugMessage( "settings not found, using default settings for " + geometryType); } else { - // validate user settings and create settings object - final Optional loadedJson = validateUserSettings(json); - if (loadedJson.isPresent()) { - // TODO: switch this based on microscope geometry type - final ScapeAcquisitionSettings acqSettings = ScapeAcquisitionSettings.fromJson( - loadedJson.get().toString(), ScapeAcquisitionSettings.class); - // update both the settings and builder - model_.acquisitions().setAcquisitionSettingsAndBuilder(acqSettings); - model_.studio().logs().logDebugMessage("loaded JSON from " + key + ": " - + model_.acquisitions().settings().toPrettyJson()); - } + // validate user settings and create AcquisitionSettings object + final Optional settingsJson = validateUserSettings(json); + settingsJson.ifPresent(jsonObject -> + loadFromJson(jsonObject.toString(), false)); + model_.studio().logs().logDebugMessage("loaded JSON from " + key + ": " + + model_.acquisitions().settings().toPrettyJson()); } // load plugin settings or default plugin settings @@ -107,6 +110,18 @@ public void load() { } } + /** + * Load {@link AcquisitionSettings} from a JSON file. + */ + public void loadFromJson(final String json, final boolean notify) { + // TODO: switch this based on microscope geometry type + var settings = ScapeAcquisitionSettings.fromJson(json, ScapeAcquisitionSettings.class); + model_.acquisitions().setAcquisitionSettingsAndBuilder(settings); + if (notify) { + notifyListeners(settings); // update the ui + } + } + /** * Save user settings. */ @@ -225,4 +240,33 @@ private int countKeysJson(final JSONObject obj) throws JSONException { return numKeys; } + /** + * Adds a listener that will update when the settings are loaded. + * + * @param listener listens to the settings object + */ + public void addChangeListener(final SettingsListener listener) { + listeners.add(listener); + } + + /** + * Updates all listeners on the Event Dispatch Thread (EDT). + * + * @param settings the acquisition settings + */ + private void notifyListeners(final AcquisitionSettings settings) { + // always update listeners on the EDT regardless of where we are called from + if (SwingUtilities.isEventDispatchThread()) { + for (SettingsListener listener : listeners) { + listener.onSettingsChanged(settings); + } + } else { + SwingUtilities.invokeLater(() -> { + for (SettingsListener listener : listeners) { + listener.onSettingsChanged(settings); + } + }); + } + } + } diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java index fc04145a..7db63fc2 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java @@ -240,14 +240,18 @@ boolean run() { // TODO: put this in AcquisitionEngine base class, between setup and run once structure is better // save settings as JSON to the save directory FileUtils.writeStringToFile(saveDir + File.separator + "acq_settings.json", settingsJson); - final PositionList positionList = model_.studio().positions().getPositionList(); - if (positionList.getNumberOfPositions() > 0) { - try { - final String path = saveDir + File.separator + "position_list.pos"; - positionList.save(path); - model_.studio().logs().logMessage("Position list saved to " + path); - } catch (Exception e) { - model_.studio().logs().logError(e, "Could not save position list."); + + // write the position list if we are using multiple positions + if (model_.acquisitions().settings().isUsingMultiplePositions()) { + final PositionList positionList = model_.studio().positions().getPositionList(); + if (positionList.getNumberOfPositions() > 0) { + try { + final String path = saveDir + File.separator + "position_list.pos"; + positionList.save(path); + model_.studio().logs().logMessage("Position list saved to " + path); + } catch (Exception e) { + model_.studio().logs().logError(e, "Could not save position list."); + } } }