diff --git a/src/main/java/ch/psi/mxsc/Controller.java b/src/main/java/ch/psi/mxsc/Controller.java index e7e590d..1fa43ed 100644 --- a/src/main/java/ch/psi/mxsc/Controller.java +++ b/src/main/java/ch/psi/mxsc/Controller.java @@ -13,6 +13,7 @@ import ch.psi.pshell.device.DeviceAdapter; import ch.psi.pshell.device.DeviceListener; import ch.psi.pshell.device.GenericDevice; import ch.psi.pshell.device.ReadbackDevice; +import ch.psi.pshell.ui.App; import ch.psi.pshell.ui.Panel; import ch.psi.utils.Audio; import ch.psi.utils.State; @@ -54,6 +55,7 @@ public class Controller { Device puck_detection; JDialog dialogAskPuckDatamatrix; String currentMountedSample; + PuckLoadingDialog dialogPuckLoading; public static Controller getInstance() { return instance; @@ -62,7 +64,14 @@ public class Controller { static void createInstance(Panel mainFrame) { instance = new Controller(mainFrame); } + + enum PuckMountMode{ + Direct, + Dialog + } + final PuckMountMode puckMountMode = App.hasArgument("direct") ? PuckMountMode.Direct : PuckMountMode.Dialog; + enum PuckSensorAccess { RaspberryPi, Esera; @@ -657,7 +666,7 @@ public class Controller { dialogAskPuckDatamatrix.setVisible(false); } puckLoading = value; - getMainFrame().setPuckDatamatrix(null); + onPuckScanned(null); Device reader = getPuckBarcodeReader(); if (reader != null) { final String name = reader.getName(); @@ -682,11 +691,12 @@ public class Controller { currentDetection = basePlate.getDetection(); } else if (getState().isInitialized()) { getMainFrame().evalAsync(name + ".polling = 0; " + name + ".disable()", true).handle(errorHandler); - getMainFrame().setPuckDatamatrix(null); + onPuckScanned(null); } } catch (Exception ex) { errorHandler.apply(null, ex); } + onPuckLoadingModeChange(puckLoading); } } } @@ -705,22 +715,22 @@ public class Controller { Logger.getLogger(Controller.class.getName()).log(Level.FINE, null, ex); } } - void onPuckBarcode(String datamatrix) { + + public void onPuckBarcode(String datamatrix) { if (isPuckLoading()) { playSound("scanned"); - getMainFrame().setPuckDatamatrix(datamatrix); System.out.println("Detected Puck: " + datamatrix); + onPuckScanned(datamatrix); } } - void onSampleBarcode(String datamatrix) { + public void onSampleBarcode(String datamatrix) { getMainFrame().setSampleDatamatrix(datamatrix); System.out.println("Detected Sample: " + datamatrix); } void onPuckDetectionChanged() { if (isPuckLoading()) { - String datamatrix = getMainFrame().getPuckDatamatrix(); Puck.Detection[] detection = basePlate.getDetection(); for (int i = 0; i < Controller.NUMBER_OF_PUCKS; i++) { Puck puck = basePlate.getPucks()[i]; @@ -729,16 +739,11 @@ public class Controller { boolean detectedPuckInserted = (currentDetection[i] != Puck.Detection.Present) && (detection[i] == Puck.Detection.Present); boolean detectedPuckRemoved = (currentDetection[i] != Puck.Detection.Empty) && (detection[i] == Puck.Detection.Empty); if (detectedPuckInserted) { - playSound("mounted"); - if (!datamatrix.isEmpty()) { - getMainFrame().setPuckDatamatrix(null); - linkPuckDatamatrix(puck, datamatrix); - } else { - askPuckDatamatrix(puck); - } + onPuckInserted(puck); + } else if (detectedPuckRemoved) { playSound("unmounted"); - linkPuckDatamatrix(puck, null); + onPuckUnmounted(puck); } } } @@ -746,8 +751,20 @@ public class Controller { currentDetection = detection; } } + + public void onPuckInserted(Puck puck){ + playSound("mounted"); + String datamatrix = getMainFrame().getPuckDatamatrix(); + onPuckScanned(null); + onPuckMounted(puck, datamatrix); + } + + public void onPuckRemoved(Puck puck){ + playSound("unmounted"); + onPuckUnmounted(puck); + } - public void linkPuckDatamatrix(Puck puck, String datamatrix) { + void linkPuckDatamatrix(Puck puck, String datamatrix, boolean showMessage) { // if ( ((puck.getId()==null) && (datamatrix!=null)) || // (puck.getId()!=null) && (!puck.getId().equals(datamatrix))){ String puckName = (puck == null) ? "" : puck.getName(); @@ -756,8 +773,6 @@ public class Controller { } datamatrix = datamatrix.trim(); - boolean showMessage = (puck != null) && !datamatrix.isEmpty(); - System.out.println("Setting datamatrix '" + datamatrix + "' to puck: " + puckName); try { @@ -768,7 +783,7 @@ public class Controller { basePlate.clearId(datamatrix); } - if (showMessage) { + if (showMessage && (puck != null) && !datamatrix.isEmpty()) { SwingUtils.showMessage(getMainFrame(), "Puck loading", "Puck '" + datamatrix + "' set to position " + puckName, 5000); @@ -790,7 +805,7 @@ public class Controller { } } - public void askPuckDatamatrix(Puck puck) { + void askPuckDatamatrix(Puck puck) { if ((dialogAskPuckDatamatrix != null) && (dialogAskPuckDatamatrix.isShowing())) { dialogAskPuckDatamatrix.setVisible(false); } @@ -844,12 +859,77 @@ public class Controller { String dm = (row >= 0) ? String.valueOf(table.getValueAt(row, 0)) : null; dialogAskPuckDatamatrix.setVisible(false); if (dm != null) { - linkPuckDatamatrix(puck, dm); + linkPuckDatamatrix(puck, dm, true); } }); } } - + + + void showDialogPuckLoading (){ + if ((dialogPuckLoading!=null) && (dialogPuckLoading.isVisible())){ + return; + } + dialogPuckLoading = new PuckLoadingDialog(mainFrame.getTopLevel(), false); + dialogPuckLoading.setLocationRelativeTo(mainFrame); + dialogPuckLoading.setVisible(true); + } + + void hideDialogPuckLoading (){ + if (dialogPuckLoading!=null){ + dialogPuckLoading.setVisible(false); + dialogPuckLoading.dispose(); + dialogPuckLoading = null; + } + } + + void onPuckLoadingModeChange(boolean puckLoadMode) { + if (puckMountMode == PuckMountMode.Dialog){ + if (puckLoadMode){ + showDialogPuckLoading(); + } else { + hideDialogPuckLoading (); + } + } + } + + void onPuckScanned(String datamatrix){ + if (isPuckLoading()) { + getMainFrame().setPuckDatamatrix(datamatrix); + if (puckMountMode == PuckMountMode.Dialog){ + showDialogPuckLoading(); + dialogPuckLoading.onPuckScanned(datamatrix); + } + } else{ + getMainFrame().setPuckDatamatrix(null); + } + } + + void onPuckMounted(Puck puck, String datamatrix){ + if (isPuckLoading()) { + if (puckMountMode == PuckMountMode.Dialog){ + showDialogPuckLoading(); + dialogPuckLoading.onPuckMounted(puck, datamatrix); + } else { + if (!datamatrix.isEmpty()) { + linkPuckDatamatrix(puck, datamatrix, true); + } else { + askPuckDatamatrix(puck); + } + } + } + } + + void onPuckUnmounted(Puck puck){ + if (isPuckLoading()) { + if (puckMountMode == PuckMountMode.Dialog){ + showDialogPuckLoading(); + dialogPuckLoading.onPuckUnmounted(puck); + } else { + linkPuckDatamatrix(puck, null, true); + } + } + } } diff --git a/src/main/java/ch/psi/mxsc/MainPanel.java b/src/main/java/ch/psi/mxsc/MainPanel.java index daf84b0..7878aa3 100644 --- a/src/main/java/ch/psi/mxsc/MainPanel.java +++ b/src/main/java/ch/psi/mxsc/MainPanel.java @@ -13,6 +13,7 @@ import ch.psi.pshell.imaging.Source; import ch.psi.pshell.scripting.ViewPreference; import ch.psi.pshell.ui.App; import ch.psi.pshell.ui.Panel; +import ch.psi.pshell.ui.StatusBar; import ch.psi.utils.Chrono; import ch.psi.utils.State; import ch.psi.utils.swing.SwingUtils; @@ -24,12 +25,10 @@ import java.awt.Dimension; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Window; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; -import java.util.logging.Logger; import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JComponent; @@ -51,6 +50,7 @@ public class MainPanel extends Panel { Boolean manualMode; Boolean roomTemperature; public final String PUCK_LOADING_STATUS = "Puck loading"; + StatusBar statusBar; public enum BasePlateLayout { normal, @@ -128,7 +128,7 @@ public class MainPanel extends Panel { showException(ex); } } - }); + }); } @Override @@ -139,6 +139,11 @@ public class MainPanel extends Panel { } basePlatePanel.setSelectionMode(SelectionMode.Pucks); basePlatePanel.setDevice(Controller.getInstance().basePlate); + + try{ + statusBar = (StatusBar) SwingUtils.getComponentsByType(getTopLevel(), StatusBar.class)[0]; + } catch (Exception ex){ + } } @Override @@ -228,7 +233,7 @@ public class MainPanel extends Panel { public void onStateChange(State state, State former) { Controller.getInstance().onStateChange(state, former); } - + @Override protected void onTimer() { try { @@ -273,17 +278,23 @@ public class MainPanel extends Panel { String status; void setStatus(String status) { - if (!status.equals(this.status)) { + String current = current = (statusBar==null) ? this.status : statusBar.getStatusLabel().getText(); + if (!status.equals(current)) { getContext().setPreference(ViewPreference.STATUS, status); - this.status = status; } + this.status = status; } + volatile boolean refreshing; void refresh() { if (!SwingUtilities.isEventDispatchThread()) { - SwingUtilities.invokeLater(() -> { - refresh(); - }); + if (!refreshing){ + refreshing = true; + SwingUtilities.invokeLater(() -> { + refreshing = false; + refresh(); + }); + } return; } repaint(); diff --git a/src/main/java/ch/psi/mxsc/PuckDetection.java b/src/main/java/ch/psi/mxsc/PuckDetection.java index 646adb2..44f1dc0 100644 --- a/src/main/java/ch/psi/mxsc/PuckDetection.java +++ b/src/main/java/ch/psi/mxsc/PuckDetection.java @@ -90,16 +90,21 @@ public class PuckDetection extends DeviceBase { setState(State.Ready); if (isSimulated()) { while (!Thread.currentThread().isInterrupted()) { + boolean changed = false; for (int address = 1; address <= Controller.NUMBER_OF_PUCKS; address++) { Integer indDetector = ((address <= 6) || (address==30)) ? 1 : 0; Integer mecDetector = ((address <= 6) || (address==29)) ? 1 : 0; int index = Controller.getInstance().getPuckIndex(address); PuckState puck = Controller.getInstance().getPuckState(index); - puck.set(mecDetector, indDetector); + if (puck.set(mecDetector, indDetector)){ + changed = true; + } + } + if (changed){ + if (Controller.getInstance() != null) { + Controller.getInstance().updateView(); + } } - if (Controller.getInstance() != null) { - Controller.getInstance().updateView(); - } chrono = new Chrono(); Thread.sleep(2000); } diff --git a/src/main/java/ch/psi/mxsc/PuckLoadingDialog.form b/src/main/java/ch/psi/mxsc/PuckLoadingDialog.form new file mode 100644 index 0000000..72e8df7 --- /dev/null +++ b/src/main/java/ch/psi/mxsc/PuckLoadingDialog.form @@ -0,0 +1,191 @@ + + +
diff --git a/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java b/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java new file mode 100644 index 0000000..98e626f --- /dev/null +++ b/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java @@ -0,0 +1,407 @@ +package ch.psi.mxsc; + +import ch.psi.pshell.core.Context; +import ch.psi.pshell.swing.DataPanel; +import ch.psi.utils.swing.MainFrame; +import ch.psi.utils.swing.SwingUtils; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JDialog; +import javax.swing.Timer; +import javax.swing.table.DefaultTableModel; + +/** + * + */ +public class PuckLoadingDialog extends JDialog { + Path dialogPersistPath; + DefaultTableModel model; + + /** + * Creates new form PuckLoadingDialog + */ + public PuckLoadingDialog(java.awt.Frame parent, boolean modal) { + super(parent, "Puck Loading", modal); + initComponents(); + this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); + this.setName("PuckLoadingDialog"); + dialogPersistPath = Paths.get(Context.getInstance().getSetup().getContextPath(), getClass().getSimpleName()); + setStatusLabel(null,-1); + setSugestionLabel(null,-1); + model = (DefaultTableModel) table.getModel(); + table.getTableHeader().setFont(table.getTableHeader().getFont().deriveFont(20.0f)); + } + + @Override + public void setVisible(boolean value){ + boolean visible = isVisible(); + if (visible && !value){ + try { + MainFrame.save(PuckLoadingDialog.this, dialogPersistPath); + } catch (Exception ex) { + Logger.getLogger(DataPanel.class.getName()).log(Level.WARNING, null, ex); + } + } + super.setVisible(value); + if (!visible && value){ + try { + MainFrame.restore(PuckLoadingDialog.this, dialogPersistPath); + } catch (Exception ex) { + Logger.getLogger(DataPanel.class.getName()).log(Level.WARNING, null, ex); + } + update(); + } + } + + + + void update() { + Map dms = Controller.getInstance().getPuckDatamatrix(); + if (dms == null) { + dms = new HashMap(); + } + Object[] keys = dms.keySet().toArray(); + Arrays.sort(keys); + if (keys.length != model.getRowCount()){ + model.setRowCount(keys.length); + } + for (int i=0; i< keys.length; i++) { + model.setValueAt(keys[i], i, 0); + model.setValueAt(dms.get(keys[i]), i, 1); + } + } + + + + void onPuckScanned(String datamatrix){ + textScannedDatamatrix.setText((datamatrix == null) ? "" : datamatrix.trim()); + if ((datamatrix != null) && (!datamatrix.isEmpty())){ + setStatusLabel("Scanned puck " + datamatrix, 5000); + makeVisible(datamatrix); + } else { + setStatusLabel(null, -1); + } + setSugestionLabel(null, -1); + buttonSet.setEnabled(false); + detectedPuck = null; + textDetectedPuck.setText(""); + } + + Puck detectedPuck; + String detectedDatamatrix; + void onPuckMounted(Puck puck, String datamatrix){ + if ((datamatrix != null) && (!datamatrix.isEmpty())) { + Controller.getInstance().linkPuckDatamatrix(puck, datamatrix, false); + setStatusLabel("Mounted puck " + datamatrix + " at " + puck.getName(), 5000); + setSugestionLabel(null, -1); + buttonSet.setEnabled(false); + textDetectedPuck.setText(""); + detectedPuck = null; + } else { + setStatusLabel("Detected puck at " + puck.getName(), -1); + setSugestionLabel("Select the datamatrix and press 'Set'", -1); + detectedPuck = puck; + textDetectedPuck.setText(puck.getName()); + buttonSet.setEnabled(true); + table.clearSelection(); + } + update(); + } + + Timer timerClear; + void onPuckUnmounted(Puck puck){ + if (puck == detectedPuck){ + + } + Controller.getInstance().linkPuckDatamatrix(puck, null, false); + setStatusLabel("Unmounted puck from "+ puck.getName(), 5000); + if (puck == detectedPuck){ + buttonSet.setEnabled(false); + detectedPuck = null; + } + makeVisible(puck); + update(); + } + + + void onManualSetPuckLocation(String datamatrix){ + if (detectedPuck!=null){ + Controller.getInstance().linkPuckDatamatrix(detectedPuck, datamatrix, false); + setStatusLabel("Set puck " + datamatrix + " at " + detectedPuck.getName(), 5000); + setSugestionLabel(null, -1); + buttonSet.setEnabled(false); + detectedPuck = null; + textDetectedPuck.setText(""); + } + update(); + } + + Timer timerLabelStatus; + void setStatusLabel(String message, int delay){ + final String defaultStatus = " "; //Waiting for Puck Detection"; + if (timerLabelStatus!=null){ + timerLabelStatus.stop(); + timerLabelStatus = null; + } + + labelStatus.setText(message==null ? defaultStatus : message); + + if (delay>0){ + timerLabelStatus = new Timer(delay, (e)->{ + labelStatus.setText(defaultStatus); + }); + timerLabelStatus.start(); + } + } + + Timer timerLabelSuggestion; + void setSugestionLabel(String message, int delay){ + final String defaultSuggestion = "Scan, Insert or Remove Pucks"; //Waiting for Puck Detection"; + if (timerLabelSuggestion!=null){ + timerLabelSuggestion.stop(); + timerLabelSuggestion = null; + } + + labelSuggestion.setText(message==null ? defaultSuggestion : message); + + if (delay>0){ + timerLabelSuggestion = new Timer(delay, (e)->{ + labelSuggestion.setText(defaultSuggestion); + }); + timerLabelSuggestion.start(); + } + } + + + void makeVisible(String datamatrix){ + if (datamatrix!=null){ + datamatrix = datamatrix.trim(); + for (int i=0; i