From 83a1ae739dfc4e5bd9d1c17623fca4696030eb4a Mon Sep 17 00:00:00 2001 From: gobbo_a Date: Wed, 20 Aug 2025 15:18:55 +0200 Subject: [PATCH] Add send_event to scripting API --- nb-configuration.xml | 18 ++ pom.xml | 4 +- src/main/java/ch/psi/mxsc/Controller.java | 29 ++- src/main/java/ch/psi/mxsc/PuckDetection.java | 15 +- .../ch/psi/mxsc/PuckDetectionErrorDialog.form | 149 +++++++++++ .../ch/psi/mxsc/PuckDetectionErrorDialog.java | 244 ++++++++++++++++++ .../java/ch/psi/mxsc/PuckLoadingDialog.java | 1 - 7 files changed, 452 insertions(+), 8 deletions(-) create mode 100644 nb-configuration.xml create mode 100644 src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.form create mode 100644 src/main/java/ch/psi/mxsc/PuckDetectionErrorDialog.java 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 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="rowHeight" type="int" value="40"/> + <Property name="selectionMode" type="int" value="0"/> + <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> + <JTableSelectionModel selectionMode="0"/> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="false" resizingAllowed="true"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="tableMouseReleased"/> + <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="tableKeyReleased"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="buttonOk"> + <Properties> + <Property name="text" type="java.lang.String" value="Ok"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonOkActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JLabel" name="labelSuggestion1"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Lucida Grande" size="24" style="0"/> + </Property> + <Property name="horizontalAlignment" type="int" value="0"/> + <Property name="text" type="java.lang.String" value="and must be manually removed."/> + </Properties> + </Component> + </SubComponents> +</Form> 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<Puck> failing) { + List<String> names = failing.stream().map(Puck::getName).toList(); + initialize(names); + } + + public void initialize(List<String> 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") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//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(); + }// </editor-fold>//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 */ + //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> + /* 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); + } + //</editor-fold> + + /* 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;