diff --git a/nb-configuration.xml b/nb-configuration.xml
new file mode 100644
index 0000000..5b0f1f8
--- /dev/null
+++ b/nb-configuration.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ true
+
+
diff --git a/pom.xml b/pom.xml
index 4fd1d5e..00b4ce4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,8 +19,8 @@
UTF-8
- 11
- 11
+ 21
+ 21
diff --git a/src/main/java/ch/psi/mxsc/Controller.java b/src/main/java/ch/psi/mxsc/Controller.java
index fc9e26b..c09a019 100644
--- a/src/main/java/ch/psi/mxsc/Controller.java
+++ b/src/main/java/ch/psi/mxsc/Controller.java
@@ -965,7 +965,34 @@ public class Controller {
try{
showingPuckLoadingDialog = (dialogPuckLoading != null) && (dialogPuckLoading.isShowing());
if ("loading".equals(Context.getSetting("puck_detection"))){
- puck_detection.setEnabled(showingPuckLoadingDialog);
+
+ if (showingPuckLoadingDialog){
+ var werePresent = new ArrayList();
+ Puck[] pucks = basePlate.getPucks();
+ for (Puck p : pucks){
+ if (p.getDetection() == Puck.Detection.Present){
+ werePresent.add(p.getName());
+ }
+ }
+ puck_detection.applyCache();
+
+
+ var present = new ArrayList();
+ for (Puck p : pucks){
+ if (p.getDetection() == Puck.Detection.Present){
+ present.add(p.getName());
+ }
+ }
+ var removed = new ArrayList<>(werePresent);
+ removed.removeAll(present);
+
+ if (removed.size()>0){
+ PuckDetectionErrorDialog dlg = new PuckDetectionErrorDialog(mainFrame.getTopLevel());
+ dlg.initialize(removed);
+ dlg.setVisible(true);
+ }
+ }
+ puck_detection.setEnabled(showingPuckLoadingDialog);
}
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.WARNING, null, ex);
diff --git a/src/main/java/ch/psi/mxsc/PuckDetection.java b/src/main/java/ch/psi/mxsc/PuckDetection.java
index b6d3461..4c18ba7 100644
--- a/src/main/java/ch/psi/mxsc/PuckDetection.java
+++ b/src/main/java/ch/psi/mxsc/PuckDetection.java
@@ -133,9 +133,6 @@ public class PuckDetection extends DeviceBase {
setCache(contents);
if (isEnabled() || (take() == null)){
processMessage(contents);
- if (Controller.getInstance() != null) {
- Controller.getInstance().updateView();
- }
}
setState(State.Ready);
@@ -163,6 +160,13 @@ public class PuckDetection extends DeviceBase {
setState(State.Offline);
}
}
+
+ public void applyCache(){
+ Object cache = take();
+ if (cache instanceof String contents){
+ processMessage(contents);
+ }
+ }
void processMessage(String str) {
try {
@@ -185,7 +189,10 @@ public class PuckDetection extends DeviceBase {
} catch (Exception ex) {
getLogger().log(Level.INFO, null, ex);
}
- }
+ if (Controller.getInstance() != null) {
+ Controller.getInstance().updateView();
+ }
+ }
public PuckState getPuckState(int id) throws Exception {
if (Controller.getInstance() == null) {
diff --git a/src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.form b/src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.form
new file mode 100644
index 0000000..74ba968
--- /dev/null
+++ b/src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.form
@@ -0,0 +1,149 @@
+
+
+
diff --git a/src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.java b/src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.java
new file mode 100644
index 0000000..b59ada9
--- /dev/null
+++ b/src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.java
@@ -0,0 +1,244 @@
+
+package ch.psi.mxsc;
+
+import ch.psi.pshell.swing.StandardDialog;
+import ch.psi.pshell.utils.Str;
+import java.awt.Dimension;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ *
+ */
+public class PuckDetectionErrorDialog extends StandardDialog {
+ final DefaultTableModel model;
+
+ final int INDEX_USER = 0;
+ final int INDEX_DEWAR = 1;
+ final int INDEX_DATAMATRIX = 2;
+ final int INDEX_POSITION = 3;
+
+ public PuckDetectionErrorDialog(java.awt.Frame parent) {
+ super(parent, true);
+ setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+ model = (DefaultTableModel) table.getModel();
+ table.getTableHeader().setFont(table.getTableHeader().getFont().deriveFont(16.0f));
+ panelTable.getVerticalScrollBar().setPreferredSize(new Dimension(30, 0));
+ initComponents();
+ }
+
+ public void initializePucks(List failing) {
+ List names = failing.stream().map(Puck::getName).toList();
+ initialize(names);
+ }
+
+ public void initialize(List failing) {
+ Map dms = Controller.getInstance().getPuckDatamatrixInfo();
+ if (dms == null) {
+ dms = new HashMap();
+ }
+ Object[] keys = dms.keySet().toArray();
+
+ model.setRowCount(failing.size());
+ for (int i=0; i< failing.size(); i++) {
+ String pos = failing.get(i);
+ model.setValueAt(failing, i, INDEX_POSITION);
+ for (int j=0; j< keys.length; j++) {
+ Map info = (Map) dms.get(keys[j]);
+ String address = Str.toString(info.getOrDefault("address", ""));
+ if (pos.equals(address)){
+ model.setValueAt(keys[j], i, INDEX_DATAMATRIX);
+ model.setValueAt(info.getOrDefault("dewar", ""), i, INDEX_DEWAR);
+ model.setValueAt(info.getOrDefault("user", ""), i, INDEX_USER);
+ break;
+ }
+ }
+ }
+ }
+
+ public void updateLaser(){
+ try{
+ int sel = table.getSelectedRow();
+ if (sel>=0){
+ String pos = model.getValueAt(sel, INDEX_POSITION).toString();
+ Puck puck = Controller.getInstance().getPuck(pos);
+ if (puck!=null){
+ Controller.getInstance().setLaserPos(pos);
+ return;
+ }
+ }
+ Controller.getInstance().setLaserPos((Puck)null);
+ } catch (Exception ex){
+ showException(ex);
+ }
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ labelSuggestion = new javax.swing.JLabel();
+ panelTable = new javax.swing.JScrollPane();
+ table = new javax.swing.JTable();
+ buttonOk = new javax.swing.JButton();
+ labelSuggestion1 = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+
+ labelSuggestion.setFont(new java.awt.Font("Lucida Grande", 0, 24)); // NOI18N
+ labelSuggestion.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ labelSuggestion.setText("The following pucks were not detected ");
+
+ table.setAutoCreateRowSorter(true);
+ table.setFont(new java.awt.Font("Lucida Grande", 0, 30)); // NOI18N
+ table.setModel(new javax.swing.table.DefaultTableModel(
+ new Object [][] {
+
+ },
+ new String [] {
+ "User", "Dewar", "Puck Id/Datamatrix", "Puck Position"
+ }
+ ) {
+ Class[] types = new Class [] {
+ java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
+ };
+ boolean[] canEdit = new boolean [] {
+ false, false, false, false
+ };
+
+ public Class getColumnClass(int columnIndex) {
+ return types [columnIndex];
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return canEdit [columnIndex];
+ }
+ });
+ table.setRowHeight(40);
+ table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ table.getTableHeader().setReorderingAllowed(false);
+ table.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseReleased(java.awt.event.MouseEvent evt) {
+ tableMouseReleased(evt);
+ }
+ });
+ table.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ tableKeyReleased(evt);
+ }
+ });
+ panelTable.setViewportView(table);
+
+ buttonOk.setText("Ok");
+ buttonOk.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonOkActionPerformed(evt);
+ }
+ });
+
+ labelSuggestion1.setFont(new java.awt.Font("Lucida Grande", 0, 24)); // NOI18N
+ labelSuggestion1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ labelSuggestion1.setText("and must be manually removed.");
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(panelTable, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(labelSuggestion, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(buttonOk)
+ .addGap(0, 0, Short.MAX_VALUE))
+ .addComponent(labelSuggestion1, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(labelSuggestion)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(labelSuggestion1)
+ .addGap(18, 18, 18)
+ .addComponent(panelTable, javax.swing.GroupLayout.PREFERRED_SIZE, 172, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addComponent(buttonOk)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void buttonOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOkActionPerformed
+ cancel();
+ }//GEN-LAST:event_buttonOkActionPerformed
+
+ private void tableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableKeyReleased
+ updateLaser();
+ }//GEN-LAST:event_tableKeyReleased
+
+ private void tableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseReleased
+ updateLaser();
+ }//GEN-LAST:event_tableMouseReleased
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ /* Set the Nimbus look and feel */
+ //
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+ for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ javax.swing.UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ java.util.logging.Logger.getLogger(PuckDetectionErrorDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ java.util.logging.Logger.getLogger(PuckDetectionErrorDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ java.util.logging.Logger.getLogger(PuckDetectionErrorDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(PuckDetectionErrorDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //
+
+ /* Create and display the dialog */
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ PuckDetectionErrorDialog dialog = new PuckDetectionErrorDialog(new javax.swing.JFrame());
+ dialog.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent e) {
+ System.exit(0);
+ }
+ });
+ dialog.setVisible(true);
+ }
+ });
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton buttonOk;
+ private javax.swing.JLabel labelSuggestion;
+ private javax.swing.JLabel labelSuggestion1;
+ private javax.swing.JScrollPane panelTable;
+ javax.swing.JTable table;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java b/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java
index 1655a21..8eb2328 100644
--- a/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java
+++ b/src/main/java/ch/psi/mxsc/PuckLoadingDialog.java
@@ -1,6 +1,5 @@
package ch.psi.mxsc;
-import ch.psi.pshell.framework.Context;
import ch.psi.pshell.swing.DataPanel;
import ch.psi.pshell.app.MainFrame;
import ch.psi.pshell.framework.Setup;