diff --git a/src/main/java/ch/psi/mxsc/BasePlatePanel.java b/src/main/java/ch/psi/mxsc/BasePlatePanel.java
index 1fd6838..33c2a2b 100644
--- a/src/main/java/ch/psi/mxsc/BasePlatePanel.java
+++ b/src/main/java/ch/psi/mxsc/BasePlatePanel.java
@@ -1,339 +1,344 @@
-/*
- * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
- */
-package ch.psi.mxsc;
-
-import ch.psi.mxsc.BasePlate.DrawMode;
-import ch.psi.pshell.core.Context;
-import ch.psi.pshell.imaging.Data;
-import ch.psi.pshell.imaging.ImageListener;
-import ch.psi.pshell.imaging.Source;
-import ch.psi.pshell.swing.DevicePanel;
-import ch.psi.utils.State;
-import ch.psi.utils.swing.SwingUtils;
-import java.awt.Component;
-import java.awt.Point;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.awt.image.BufferedImage;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.JMenuItem;
-import javax.swing.JPopupMenu;
-
-/**
- *
- */
-public class BasePlatePanel extends DevicePanel {
- JPopupMenu samplePopupMenu;
- JMenuItem menuLoadSample;
- JMenuItem menuUnloadSample;
- /**
- * Creates new form BasePlatePanel
- */
- public BasePlatePanel() {
- initComponents();
- addMouseListener(mouseAdapter);
- samplePopupMenu = new JPopupMenu();
- menuLoadSample = new JMenuItem("Load");
- menuLoadSample.addActionListener((ActionEvent e) -> {
- try {
- getDevice().loadSample();
- } catch (Exception ex) {
- SwingUtils.showException(this, ex);
- }
- });
- menuUnloadSample = new JMenuItem("Unload");
- menuUnloadSample.addActionListener((ActionEvent e) -> {
- try {
- getDevice().unloadSample(getDevice().getSelectedSample());
- } catch (Exception ex) {
- SwingUtils.showException(this, ex);
- }
- });
- samplePopupMenu.add(menuLoadSample);
- samplePopupMenu.add(menuUnloadSample);
- }
-
- @Override
- public BasePlate getDevice() {
- return (BasePlate) super.getDevice();
- }
-
- Mode mode = Mode.horizontal;
-
- public enum Mode {
- single,
- horizontal,
- vertical,
- overlapped,
- }
-
- public Mode getMode() {
- return mode;
- }
-
- public void setMode(Mode mode) {
- this.mode = mode;
- repaint();
- }
-
-
- /**
- * 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() {
-
- javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
- this.setLayout(layout);
- layout.setHorizontalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 400, Short.MAX_VALUE)
- );
- layout.setVerticalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 300, Short.MAX_VALUE)
- );
- }// //GEN-END:initComponents
-
- @Override
- protected void onDeviceStateChanged(State state, State former) {
- repaint();
- }
-
- Rectangle platePlotRect;
- Rectangle puckPlotRect;
- Source source;
-
- @Override
- public void paint(Graphics g) {
- super.paint(g);
- if (getDevice() != null) {
- Graphics2D g2d = (Graphics2D) g;
- Dimension size = getSize();
- if ((size.width > 40) && (size.height > 40)) {
- int border = 0;
- int borderPuck = 20;
- Rectangle plotRect = new Rectangle(border, border, size.width - 2 * border, size.height - 2 * border);
- Puck selectedPuck = getDevice().getSelectedPuck();
- platePlotRect = null;
- puckPlotRect = null;
-
- switch (mode) {
- case single:
- platePlotRect = plotRect;
- puckPlotRect = null;
- getDevice().draw(g2d, platePlotRect, (img==null), false, true, DrawMode.center, img);
- break;
- case horizontal:
- platePlotRect = new Rectangle(plotRect.x, plotRect.y, plotRect.width / 2, plotRect.height);
- getDevice().draw(g2d, platePlotRect, false, true, true, DrawMode.fill, null);
- if (selectedPuck!=null){
- puckPlotRect = new Rectangle(plotRect.x + plotRect.width / 2 + borderPuck, plotRect.y + borderPuck, plotRect.width / 2 - 2 * borderPuck, plotRect.height - 2 * borderPuck);
- selectedPuck.draw(g2d, puckPlotRect, true, false, true, null);
- }
- break;
- case vertical:
- platePlotRect = new Rectangle(plotRect.x, plotRect.y, plotRect.width, plotRect.height / 2);
- getDevice().draw(g2d, platePlotRect, false, true, true, DrawMode.fill, null);
- if (selectedPuck!=null){
- puckPlotRect = new Rectangle(plotRect.x + borderPuck, plotRect.y + plotRect.height / 2 + borderPuck, plotRect.width - 2 * borderPuck, plotRect.height / 2 - 2 * borderPuck);
- selectedPuck.draw(g2d, puckPlotRect, true, false, true, null);
- }
- break;
- case overlapped:
- //getDevice().draw(g2d, plotRect, false, true);
- platePlotRect = new Rectangle(plotRect.x - ((int) (plotRect.width * 0.14)), plotRect.y - ((int) (plotRect.height * 0.14)), (int) (plotRect.width * 1.28), (int) (plotRect.height * 1.28));
- getDevice().draw(g2d, platePlotRect, false, true, false, DrawMode.fill, null);
- if (selectedPuck!=null){
- int overlappedSize = (int) (1.5 * selectedPuck.getDrawSize());
- puckPlotRect = new Rectangle((int) (plotRect.getCenterX() - overlappedSize / 2), (int) (plotRect.getCenterY() - overlappedSize / 2), overlappedSize, overlappedSize);
- selectedPuck.draw(g2d, puckPlotRect, true, false, true, null);
- }
- break;
- }
- }
- }
- }
-
- BufferedImage img;
- ImageListener imageListener = new ImageListener() {
- @Override
- public void onImage(Object origin, BufferedImage image, Data data) {
- img = image;
- repaint();
- }
-
- @Override
- public void onError(Object origin, Exception ex) {
- img = null;
- repaint();
- }
- };
- void setCameraView(Source source){
- img = null;
- if (this.source!=null){
- this.source.removeListener(imageListener);
- }
- this.source = source;
- if (source!=null){
- source.addListener(imageListener);
- }
- repaint();
- }
-
- MouseAdapter mouseAdapter = new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- checkMouseEvent(e, true);
- }
-
- @Override
- public void mouseReleased(MouseEvent e) {
- checkMouseEvent(e, false);
- }
-
- private void checkMouseEvent(MouseEvent e, boolean pressed) {
- if (isEnabled() && (getDevice()!=null) && getDevice().isSelectable()) {
- try {
- Sample sample = getSample(e.getX(), e.getY());
- Puck puck = getPuck(e.getX(), e.getY());
- if (e.isPopupTrigger()) {
- if (sample != null) {
- onSamplePopupMenu(e, sample);
- } else if (puck != null){
- onPuckPopupMenu(e, puck);
- } else {
- onBasePlatePopupMenu(e);
- }
- } else if ((pressed) && (e.getClickCount() % 2 == 0)) {
- if (sample != null) {
- onSampleDoubleClicked(e, sample);
- } else if (puck != null){
- onPuckDoubleClicked(e, puck);
- }
- } else if ((e.getButton() == java.awt.event.MouseEvent.BUTTON1)) {
- if (sample != null) {
- if (pressed) {
- onSamplePressed(e, sample);
- } else {
- onSampleReleased(e, sample);
- }
- }else if (puck != null){
- if (pressed) {
- onPuckPressed(e, puck);
- } else {
- onPuckReleased(e, puck);
- }
- }
- }
- } catch (Exception ex) {
- Logger.getLogger(BasePlatePanel.class.getName()).log(Level.WARNING, null, ex);
- }
- }
- }
-
- @Override
- public void mouseClicked(MouseEvent e) {
- if (isEnabled()&& (getDevice()!=null)) {
- if (e.getButton() == java.awt.event.MouseEvent.BUTTON1) {
- Sample sample = getSample(e.getX(), e.getY());
- Puck puck = getPuck(e.getX(), e.getY());
- if (sample != null) {
- onSampleClicked(e, sample);
- } else {
- onPuckClicked(e, puck);
- }
- }
- }
- }
- };
-
- Sample getSample(int x, int y) {
- Point p = new Point(x, y);
- for (Puck puck : getDevice().getPucks()){
- if (puck.isSelected() || (mode==Mode.single)){
- for (Sample sample :puck.getSamples()){
- if (sample.getDrawPosition().distance(p) <= (sample.getDrawSize() / 2)) {
- return sample;
- }
- }
- }
- }
-
- return null;
-
- }
-
- Puck getPuck(int x, int y) {
- Point p = new Point(x, y);
- for (Puck puck : getDevice().getPucks()){
- if (puck.getDrawPosition().distance(p) <= (puck.getDrawSize() / 2)) {
- return puck;
- }
- }
- return null;
- }
-
-
- void onSampleClicked(MouseEvent e, Sample sample){
-
- }
-
- void onSamplePressed(MouseEvent e, Sample sample){
- sample.setSelected(true);
- repaint();
-
- }
-
- void onSampleReleased(MouseEvent e, Sample sample){
-
- }
-
- void onSamplePopupMenu(MouseEvent e,Sample sample){
- System.out.println(sample);
- menuLoadSample.setEnabled(sample.isPresent() && getDevice().getLoadedSample()==null);
- menuUnloadSample.setEnabled(!sample.isPresent() && getDevice().getLoadedSample()!=null);
- samplePopupMenu.show(e.getComponent(), e.getX(), e.getY());
- }
-
- void onSampleDoubleClicked(MouseEvent e,Sample sample){
-
- }
-
- void onPuckClicked(MouseEvent e, Puck puck){
-
- }
-
- void onPuckPressed(MouseEvent e, Puck puck){
- puck.setSelected(true);
- repaint();
- }
-
- void onPuckReleased(MouseEvent e, Puck puck){
-
- }
-
- void onPuckPopupMenu(MouseEvent e, Puck puck){
- System.out.println(puck);
- }
-
- void onPuckDoubleClicked(MouseEvent e, Puck puck){
-
- }
-
- void onBasePlatePopupMenu(MouseEvent e){
-
- }
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- // End of variables declaration//GEN-END:variables
-}
+/*
+ * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
+ */
+package ch.psi.mxsc;
+
+import ch.psi.mxsc.BasePlate.DrawMode;
+import ch.psi.pshell.core.Context;
+import ch.psi.pshell.imaging.Data;
+import ch.psi.pshell.imaging.ImageListener;
+import ch.psi.pshell.imaging.Source;
+import ch.psi.pshell.swing.DevicePanel;
+import ch.psi.utils.State;
+import ch.psi.utils.swing.SwingUtils;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.image.BufferedImage;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+/**
+ *
+ */
+public class BasePlatePanel extends DevicePanel {
+ JPopupMenu samplePopupMenu;
+ JMenuItem menuLoadSample;
+ JMenuItem menuUnloadSample;
+ /**
+ * Creates new form BasePlatePanel
+ */
+ public BasePlatePanel() {
+ initComponents();
+ addMouseListener(mouseAdapter);
+ samplePopupMenu = new JPopupMenu();
+ menuLoadSample = new JMenuItem("Load");
+ menuLoadSample.addActionListener((ActionEvent e) -> {
+ try {
+ getDevice().loadSample();
+ } catch (Exception ex) {
+ SwingUtils.showException(this, ex);
+ }
+ });
+ menuUnloadSample = new JMenuItem("Unload");
+ menuUnloadSample.addActionListener((ActionEvent e) -> {
+ try {
+ getDevice().unloadSample(getDevice().getSelectedSample());
+ } catch (Exception ex) {
+ SwingUtils.showException(this, ex);
+ }
+ });
+ samplePopupMenu.add(menuLoadSample);
+ samplePopupMenu.add(menuUnloadSample);
+ }
+
+ @Override
+ public BasePlate getDevice() {
+ return (BasePlate) super.getDevice();
+ }
+
+ Mode mode = Mode.horizontal;
+
+ public enum Mode {
+ single,
+ horizontal,
+ vertical,
+ overlapped,
+ }
+
+ public Mode getMode() {
+ return mode;
+ }
+
+ public void setMode(Mode mode) {
+ this.mode = mode;
+ repaint();
+ }
+
+
+ /**
+ * 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() {
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 400, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 300, Short.MAX_VALUE)
+ );
+ }// //GEN-END:initComponents
+
+ @Override
+ protected void onDeviceStateChanged(State state, State former) {
+ repaint();
+ }
+
+ Rectangle platePlotRect;
+ Rectangle puckPlotRect;
+ Source source;
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ if (getDevice() != null) {
+ Graphics2D g2d = (Graphics2D) g;
+ Dimension size = getSize();
+ if ((size.width > 40) && (size.height > 40)) {
+ int border = 0;
+ int borderPuck = 20;
+ Rectangle plotRect = new Rectangle(border, border, size.width - 2 * border, size.height - 2 * border);
+ Puck selectedPuck = getDevice().getSelectedPuck();
+ platePlotRect = null;
+ puckPlotRect = null;
+
+ switch (mode) {
+ case single:
+ platePlotRect = plotRect;
+ puckPlotRect = null;
+ getDevice().draw(g2d, platePlotRect, (img==null), false, true, DrawMode.center, img);
+ break;
+ case horizontal:
+ platePlotRect = new Rectangle(plotRect.x, plotRect.y, plotRect.width / 2, plotRect.height);
+ getDevice().draw(g2d, platePlotRect, false, true, true, DrawMode.fill, null);
+ if (selectedPuck!=null){
+ puckPlotRect = new Rectangle(plotRect.x + plotRect.width / 2 + borderPuck, plotRect.y + borderPuck, plotRect.width / 2 - 2 * borderPuck, plotRect.height - 2 * borderPuck);
+ selectedPuck.draw(g2d, puckPlotRect, true, false, true, null);
+ }
+ break;
+ case vertical:
+ platePlotRect = new Rectangle(plotRect.x, plotRect.y, plotRect.width, plotRect.height / 2);
+ getDevice().draw(g2d, platePlotRect, false, true, true, DrawMode.fill, null);
+ if (selectedPuck!=null){
+ puckPlotRect = new Rectangle(plotRect.x + borderPuck, plotRect.y + plotRect.height / 2 + borderPuck, plotRect.width - 2 * borderPuck, plotRect.height / 2 - 2 * borderPuck);
+ selectedPuck.draw(g2d, puckPlotRect, true, false, true, null);
+ }
+ break;
+ case overlapped:
+ //getDevice().draw(g2d, plotRect, false, true);
+ platePlotRect = new Rectangle(plotRect.x - ((int) (plotRect.width * 0.14)), plotRect.y - ((int) (plotRect.height * 0.14)), (int) (plotRect.width * 1.28), (int) (plotRect.height * 1.28));
+ getDevice().draw(g2d, platePlotRect, false, true, false, DrawMode.fill, null);
+ if (selectedPuck!=null){
+ int overlappedSize = (int) (1.5 * selectedPuck.getDrawSize());
+ puckPlotRect = new Rectangle((int) (plotRect.getCenterX() - overlappedSize / 2), (int) (plotRect.getCenterY() - overlappedSize / 2), overlappedSize, overlappedSize);
+ selectedPuck.draw(g2d, puckPlotRect, true, false, true, null);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ BufferedImage img;
+ ImageListener imageListener = new ImageListener() {
+ @Override
+ public void onImage(Object origin, BufferedImage image, Data data) {
+ img = image;
+ repaint();
+ }
+
+ @Override
+ public void onError(Object origin, Exception ex) {
+ img = null;
+ repaint();
+ }
+ };
+ void setCameraView(Source source){
+ img = null;
+ if (this.source!=null){
+ this.source.removeListener(imageListener);
+ }
+ this.source = source;
+ if (source!=null){
+ source.addListener(imageListener);
+ }
+ repaint();
+ }
+
+ MouseAdapter mouseAdapter = new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ checkMouseEvent(e, true);
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ checkMouseEvent(e, false);
+ }
+
+ private void checkMouseEvent(MouseEvent e, boolean pressed) {
+ if (isEnabled() && (getDevice()!=null)) {
+ try {
+ Sample sample = getSample(e.getX(), e.getY());
+ Puck puck = getPuck(e.getX(), e.getY());
+ if (e.isPopupTrigger()) {
+ if (sample != null) {
+ onSamplePopupMenu(e, sample);
+ } else if (puck != null){
+ onPuckPopupMenu(e, puck);
+ } else {
+ onBasePlatePopupMenu(e);
+ }
+ } else if ((pressed) && (e.getClickCount() % 2 == 0)) {
+ if (sample != null) {
+ onSampleDoubleClicked(e, sample);
+ } else if (puck != null){
+ onPuckDoubleClicked(e, puck);
+ }
+ } else if ((e.getButton() == java.awt.event.MouseEvent.BUTTON1)) {
+ if (sample != null) {
+ if (pressed) {
+ onSamplePressed(e, sample);
+ } else {
+ onSampleReleased(e, sample);
+ }
+ }else if (puck != null){
+ if (pressed) {
+ onPuckPressed(e, puck);
+ } else {
+ onPuckReleased(e, puck);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ Logger.getLogger(BasePlatePanel.class.getName()).log(Level.WARNING, null, ex);
+ }
+ }
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (isEnabled()&& (getDevice()!=null)) {
+ if (e.getButton() == java.awt.event.MouseEvent.BUTTON1) {
+ Sample sample = getSample(e.getX(), e.getY());
+ Puck puck = getPuck(e.getX(), e.getY());
+ if (sample != null) {
+ onSampleClicked(e, sample);
+ } else {
+ onPuckClicked(e, puck);
+ }
+ }
+ }
+ }
+ };
+
+ Sample getSample(int x, int y) {
+ Point p = new Point(x, y);
+ for (Puck puck : getDevice().getPucks()){
+ if (puck.isSelected() || (mode==Mode.single)){
+ for (Sample sample :puck.getSamples()){
+ if (sample.getDrawPosition().distance(p) <= (sample.getDrawSize() / 2)) {
+ return sample;
+ }
+ }
+ }
+ }
+
+ return null;
+
+ }
+
+ Puck getPuck(int x, int y) {
+ Point p = new Point(x, y);
+ for (Puck puck : getDevice().getPucks()){
+ if (puck.getDrawPosition().distance(p) <= (puck.getDrawSize() / 2)) {
+ return puck;
+ }
+ }
+ return null;
+ }
+
+
+ void onSampleClicked(MouseEvent e, Sample sample){
+
+ }
+
+ void onSamplePressed(MouseEvent e, Sample sample){
+ if (getDevice().isSelectable()){
+ sample.toggleSelected(true);
+ repaint();
+ }
+ Controller.getInstance().onSamplePressed(sample);
+ }
+
+ void onSampleReleased(MouseEvent e, Sample sample){
+
+ }
+
+ void onSamplePopupMenu(MouseEvent e,Sample sample){
+ System.out.println(sample);
+ menuLoadSample.setEnabled(sample.isPresent() && getDevice().getLoadedSample()==null);
+ menuUnloadSample.setEnabled(!sample.isPresent() && getDevice().getLoadedSample()!=null);
+ samplePopupMenu.show(e.getComponent(), e.getX(), e.getY());
+ }
+
+ void onSampleDoubleClicked(MouseEvent e,Sample sample){
+
+ }
+
+ void onPuckClicked(MouseEvent e, Puck puck){
+
+ }
+
+ void onPuckPressed(MouseEvent e, Puck puck){
+ if (getDevice().isSelectable()){
+ puck.toggleSelected(true);
+ repaint();
+ }
+ Controller.getInstance().onPuckPressed(puck);
+ }
+
+ void onPuckReleased(MouseEvent e, Puck puck){
+
+ }
+
+ void onPuckPopupMenu(MouseEvent e, Puck puck){
+ System.out.println(puck);
+ }
+
+ void onPuckDoubleClicked(MouseEvent e, Puck puck){
+
+ }
+
+ void onBasePlatePopupMenu(MouseEvent e){
+
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/main/java/ch/psi/mxsc/Controller.java b/src/main/java/ch/psi/mxsc/Controller.java
index 773061f..df8f879 100644
--- a/src/main/java/ch/psi/mxsc/Controller.java
+++ b/src/main/java/ch/psi/mxsc/Controller.java
@@ -13,9 +13,11 @@ import ch.psi.pshell.device.ProcessVariableBase;
import ch.psi.pshell.device.ReadbackDevice;
import ch.psi.pshell.ui.Panel;
import ch.psi.utils.State;
+import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.script.ScriptException;
import javax.swing.JComponent;
/**
@@ -25,7 +27,7 @@ public class Controller {
static Controller instance;
final BasePlate basePlate;
- final Panel mainFrame;
+ final /*Panel*/ MainPanel mainFrame;
Device hexaposi;
public static Controller getInstance() {
@@ -53,11 +55,12 @@ public class Controller {
for (int i = 0; i < NUMBER_OF_PUCKS; i++) {
puckState[i] = new PuckState(i + 1);
}
- this.mainFrame = mainFrame;
+ this.mainFrame = (MainPanel)mainFrame;
instance = this;
}
- public Panel getMainFrame() {
+ //public Panel getMainFrame() {
+ public MainPanel getMainFrame() {
return mainFrame;
}
@@ -165,14 +168,7 @@ public class Controller {
getMainFrame().runAsync("imgproc/LedDetectionProc", args).handle((ret, ex) -> {
if (ex == null) {
Map> map = (Map>) ret;
- for (Puck.ImageDetection id : Puck.ImageDetection.values()) {
- for (String name : map.get(id.toString())) {
- Puck p = basePlate.getPuckByName(name);
- if (p != null) {
- p.setImageDetection(id);
- }
- }
- }
+ setImageDetection(map);
} else {
getMainFrame().showException((Exception)ex);
}
@@ -181,9 +177,31 @@ public class Controller {
updateView();
}
- public void clearImageDetection() throws Context.ContextStateException {
- getMainFrame().evalAsync("clear_detection(None)");
+ public void clearImageDetection() throws Context.ContextStateException, ScriptException, IOException, InterruptedException {
+ Map> map = (Map>) getMainFrame().eval("clear_detection(None)");
+ setImageDetection(map);
updateView();
}
+ void setImageDetection(Map> map){
+ for (Puck.ImageDetection id : Puck.ImageDetection.values()) {
+ for (String name : map.get(id.toString())) {
+ Puck p = basePlate.getPuckByName(name);
+ if (p != null) {
+ p.setImageDetection(id);
+ }
+ }
+ }
+ }
+
+ void onPuckPressed(Puck puck){
+ getMainFrame().textDetSensors.setText(String.valueOf(puck.getDetection()));
+ getMainFrame().textDetImage.setText(String.valueOf(puck.getImageDetection()));
+ }
+
+ void onSamplePressed(Sample sample){
+ onPuckPressed(sample.getPuck());
+ }
+
+
}
diff --git a/src/main/java/ch/psi/mxsc/MainPanel.form b/src/main/java/ch/psi/mxsc/MainPanel.form
index e8a3696..f449694 100644
--- a/src/main/java/ch/psi/mxsc/MainPanel.form
+++ b/src/main/java/ch/psi/mxsc/MainPanel.form
@@ -100,8 +100,10 @@
-
-
+
+
+
+
@@ -115,9 +117,12 @@
-
-
-
+
+
+
+
+
+
@@ -182,7 +187,7 @@
-
+
@@ -269,6 +274,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/ch/psi/mxsc/MainPanel.java b/src/main/java/ch/psi/mxsc/MainPanel.java
index 712cd62..27e89c9 100644
--- a/src/main/java/ch/psi/mxsc/MainPanel.java
+++ b/src/main/java/ch/psi/mxsc/MainPanel.java
@@ -48,7 +48,7 @@ public class MainPanel extends Panel {
public void onInitialize(int runCount) {
Controller.getInstance().onInitialize(runCount);
basePlatePanel.setDevice((Device) getDevice("BasePlate"));
- basePlatePanel.getDevice().setSelectable(false);
+ basePlatePanel.getDevice().setSelectable(true);
((Device) getDevice("dewar_level")).addListener(new DeviceAdapter() {
@Override
public void onValueChanged(Device device, Object value, Object former) {
@@ -223,6 +223,11 @@ public class MainPanel extends Panel {
ledLidControlActive4 = new ch.psi.pshell.swing.Led();
ledLidControlActive3 = new ch.psi.pshell.swing.Led();
buttonClearDet = new javax.swing.JButton();
+ panelDet = new javax.swing.JPanel();
+ jLabel21 = new javax.swing.JLabel();
+ textDetSensors = new javax.swing.JTextField();
+ jLabel22 = new javax.swing.JLabel();
+ textDetImage = new javax.swing.JTextField();
jPanel1 = new javax.swing.JPanel();
jPanel3 = new javax.swing.JPanel();
jSeparator1 = new javax.swing.JSeparator();
@@ -348,7 +353,7 @@ public class MainPanel extends Panel {
jPanel11Layout.setVerticalGroup(
jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel11Layout.createSequentialGroup()
- .addGap(0, 0, Short.MAX_VALUE)
+ .addGap(0, 0, 0)
.addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ledLidControlActive4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel20))
@@ -373,6 +378,49 @@ public class MainPanel extends Panel {
}
});
+ panelDet.setBorder(javax.swing.BorderFactory.createTitledBorder("Detection"));
+
+ jLabel21.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ jLabel21.setText("Sensor:");
+
+ textDetSensors.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+ textDetSensors.setDisabledTextColor(new java.awt.Color(0, 0, 0));
+ textDetSensors.setEnabled(false);
+
+ jLabel22.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ jLabel22.setText("Image:");
+
+ textDetImage.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+ textDetImage.setDisabledTextColor(new java.awt.Color(0, 0, 0));
+ textDetImage.setEnabled(false);
+
+ javax.swing.GroupLayout panelDetLayout = new javax.swing.GroupLayout(panelDet);
+ panelDet.setLayout(panelDetLayout);
+ panelDetLayout.setHorizontalGroup(
+ panelDetLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelDetLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelDetLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel21, javax.swing.GroupLayout.DEFAULT_SIZE, 55, Short.MAX_VALUE)
+ .addComponent(textDetSensors)
+ .addComponent(jLabel22, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(textDetImage))
+ .addContainerGap())
+ );
+ panelDetLayout.setVerticalGroup(
+ panelDetLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelDetLayout.createSequentialGroup()
+ .addGap(0, 0, 0)
+ .addComponent(jLabel21)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(textDetSensors, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel22)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(textDetImage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
javax.swing.GroupLayout basePlatePanelLayout = new javax.swing.GroupLayout(basePlatePanel);
basePlatePanel.setLayout(basePlatePanelLayout);
basePlatePanelLayout.setHorizontalGroup(
@@ -388,8 +436,13 @@ public class MainPanel extends Panel {
.addComponent(buttonClearDet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(basePlatePanelLayout.createSequentialGroup()
.addComponent(jPanel11, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(0, 415, Short.MAX_VALUE))))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(panelDet, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(4, 4, 4))))
);
+
+ basePlatePanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jPanel11, panelDet});
+
basePlatePanelLayout.setVerticalGroup(
basePlatePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(basePlatePanelLayout.createSequentialGroup()
@@ -398,9 +451,11 @@ public class MainPanel extends Panel {
.addComponent(buttonPuckDet)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(buttonClearDet)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jPanel11, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap())
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 273, Short.MAX_VALUE)
+ .addGroup(basePlatePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(jPanel11, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(panelDet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGap(4, 4, 4))
);
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("LN2 Level"));
@@ -928,8 +983,8 @@ public class MainPanel extends Panel {
private void buttonExpertActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonExpertActionPerformed
try{
- this.showRenderer("img");
- //getContext().getPluginManager().loadInitializePlugin(getContext().getSetup().expandPath("{plugins}/Expert.java"));
+ //this.showRenderer("img");
+ getContext().getPluginManager().loadInitializePlugin(getContext().getSetup().expandPath("{plugins}/Expert.java"));
} catch (Exception ex) {
showException(ex);
}
@@ -999,6 +1054,8 @@ public class MainPanel extends Panel {
private javax.swing.JLabel jLabel19;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel20;
+ private javax.swing.JLabel jLabel21;
+ private javax.swing.JLabel jLabel22;
private javax.swing.JLabel jLabel24;
private javax.swing.JLabel jLabel25;
private javax.swing.JLabel jLabel26;
@@ -1042,10 +1099,13 @@ public class MainPanel extends Panel {
private ch.psi.pshell.swing.Led ledLocalSafety;
private ch.psi.pshell.swing.Led ledN2Pressure;
private ch.psi.pshell.swing.Led ledPsysSafety;
+ private javax.swing.JPanel panelDet;
private ch.psi.pshell.swing.ProcessVariablePanel panelDewar;
private javax.swing.JProgressBar progressLN2;
private javax.swing.JProgressBar progressWater;
private ch.psi.mxsc.RoomTempBasePlatePanel roomTempBasePlatePanel1;
+ javax.swing.JTextField textDetImage;
+ javax.swing.JTextField textDetSensors;
private javax.swing.JTextField textSample;
private javax.swing.JTextField textState;
private javax.swing.JTextField textType;
diff --git a/src/main/java/ch/psi/mxsc/Puck.java b/src/main/java/ch/psi/mxsc/Puck.java
index cc95568..0fee793 100644
--- a/src/main/java/ch/psi/mxsc/Puck.java
+++ b/src/main/java/ch/psi/mxsc/Puck.java
@@ -82,7 +82,7 @@ public class Puck extends DeviceBase {
final static PointDouble labelPositionWithImage = new PointDouble(0.0, 36.0);
- ImageDetection imageDetection = null;
+ ImageDetection imageDetection = ImageDetection.Unknown;
public ImageDetection getImageDetection(){
return imageDetection;
@@ -97,6 +97,7 @@ public class Puck extends DeviceBase {
Minispine,
Unipuck,
Error,
+ Unknown,
}
public double getAngle() {
@@ -270,12 +271,19 @@ public class Puck extends DeviceBase {
return selected && getBasePlate().isSelectable();
}
+ public void toggleSelected(boolean value) {
+ setSelected(!selected);
+ }
+
public void setSelected(boolean value) {
if (value != selected) {
if (value == true) {
for (Device d : getParent().getChildren()) {
if (d instanceof Puck) {
((Puck) d).selected = false;
+ for (Sample sample : ((Puck) d).getSamples()) {
+ sample.selected = false;
+ }
}
}
}
@@ -297,7 +305,7 @@ public class Puck extends DeviceBase {
ret = isHighlithted() ? new Color(224, 224, 224) : Color.LIGHT_GRAY;
break;
case Present:
- if (imageDetection != null){
+ if ((imageDetection != null) && (imageDetection != ImageDetection.Unknown)){
switch (imageDetection){
case Minispine:
ret = isHighlithted() ? new Color(0, 200, 80) : new Color(128, 232, 152);
@@ -337,7 +345,7 @@ public class Puck extends DeviceBase {
(int) ((getSize().getWidth() / getBasePlate().getSize().getWidth()) * plotRect.width),
(int) ((getSize().getHeight() / getBasePlate().getSize().getHeight()) * plotRect.height)
);
- if (isHighlithted()) {
+ if (isSelected()) {
ret += 2;
}
return ret;
@@ -396,7 +404,7 @@ public class Puck extends DeviceBase {
}
int getBorderWidth(boolean drawBackground) {
- return drawBackground ? isHighlithted() ? 2 : 1 : isHighlithted() ? 2 : 1;
+ return drawBackground ? isSegmentSelected() ? 2 : 1 : isSegmentSelected() ? 2 : 1;
}
int getReferenceDrawSize() {
diff --git a/src/main/java/ch/psi/mxsc/PuckDetection.java b/src/main/java/ch/psi/mxsc/PuckDetection.java
index c7dd003..dda1c8b 100644
--- a/src/main/java/ch/psi/mxsc/PuckDetection.java
+++ b/src/main/java/ch/psi/mxsc/PuckDetection.java
@@ -1,176 +1,176 @@
-package ch.psi.mxsc;
-
-import ch.psi.pshell.core.JsonSerializer;
-import ch.psi.pshell.device.DeviceBase;
-import ch.psi.utils.Arr;
-import ch.psi.utils.Chrono;
-import ch.psi.utils.State;
-import ch.psi.utils.Str;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-
-public class PuckDetection extends DeviceBase {
-
- final String server;
- public volatile Chrono chrono;
- boolean debug;
-
- public PuckDetection(String name, String server) {
- super(name);
- this.server = server.startsWith("tcp://") ? server : "tcp://" + server;
- }
-
- public boolean isDebug() {
- return debug;
- }
-
- public void setDebug(boolean value) {
- debug = value;
- }
-
- Thread thread;
- Thread watchDog;
-
- @Override
- protected void doInitialize() throws IOException, InterruptedException {
- doClose();
- super.doInitialize();
-
- chrono = new Chrono();
- thread = new Thread(new Runnable() {
- @Override
- public void run() {
- subscriberTask();
- }
- });
- thread.setDaemon(true);
- thread.start();
-
- watchDog = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- while (!Thread.currentThread().isInterrupted()) {
- if (chrono.isTimeout(3000)) {
- setState(State.Offline);
- if (Controller.getInstance() != null) {
- Controller.getInstance().clearPuckStates();
- }
- }
- Thread.sleep(1000);
- }
- } catch (Exception ex) {
- getLogger().log(Level.INFO, null, ex);
- }
- }
- });
- watchDog.setDaemon(true);
- watchDog.start();
- }
-
- void subscriberTask() {
- try {
- setState(State.Ready);
- if (isSimulated()) {
- while (!Thread.currentThread().isInterrupted()) {
- 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 (Controller.getInstance() != null) {
- Controller.getInstance().updateView();
- }
- chrono = new Chrono();
- Thread.sleep(2000);
- }
- } else {
- org.zeromq.ZMQ.Context context = org.zeromq.ZMQ.context(1);
- org.zeromq.ZMQ.Socket subscriber = context.socket(org.zeromq.ZMQ.SUB);
- subscriber.connect(server);
- //subscriber.subscribe("Status".getBytes());
- subscriber.subscribe("".getBytes());
- try {
- if (debug) {
- System.out.println("Start listening");
- }
- while (!Thread.currentThread().isInterrupted()) {
- //String type = subscriber.recvStr();
- //System.out.println(type);
- String contents = subscriber.recvStr();
- if (debug) {
- System.out.println(contents);
- }
- processMessage(contents);
-
- if (Controller.getInstance() != null) {
- Controller.getInstance().updateView();
- }
- setState(State.Ready);
- chrono = new Chrono();
- }
- } finally {
- if (debug) {
- System.out.println("Stop listening");
- }
-
- if (Controller.getInstance() != null) {
- Controller.getInstance().clearPuckStates();
- }
- subscriber.close();
- context.term();
- }
- }
- } catch (Exception ex) {
- getLogger().log(Level.INFO, null, ex);
- }
- setState(State.Offline);
- }
-
- void processMessage(String str) {
- try {
- //System.out.println(str);
- List detection = (List) JsonSerializer.decode(str, List.class);
-
- int address = 1;
- for (List bus : detection) {
- for (List sensor : bus) {
- Integer indDetector = sensor.get(0);
- Integer mecDetector = sensor.get(1);
- int index = Controller.getInstance().getPuckIndex(address);
- PuckState puck = Controller.getInstance().getPuckState(index);
- puck.set(mecDetector, indDetector);
-
- address++;
- }
- }
- } catch (Exception ex) {
- getLogger().log(Level.INFO, null, ex);
- }
- }
-
- @Override
- protected void doClose() {
- if (watchDog != null) {
- watchDog.interrupt();
- watchDog = null;
- }
- if (thread != null) {
- thread.interrupt();
- thread = null;
- }
- }
-
- public static void main(String[] args) throws IOException, InterruptedException {
- PuckDetection pd = new PuckDetection("PD", "129.129.110.99:5556");
- //PuckDetection pd = new PuckDetection("PD","raspberrypi:5556");
- pd.setDebug(true);
- pd.initialize();
- Thread.sleep(100000);
- }
-}
+package ch.psi.mxsc;
+
+import ch.psi.pshell.core.JsonSerializer;
+import ch.psi.pshell.device.DeviceBase;
+import ch.psi.utils.Arr;
+import ch.psi.utils.Chrono;
+import ch.psi.utils.State;
+import ch.psi.utils.Str;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+
+public class PuckDetection extends DeviceBase {
+
+ final String server;
+ public volatile Chrono chrono;
+ boolean debug;
+
+ public PuckDetection(String name, String server) {
+ super(name);
+ this.server = server.startsWith("tcp://") ? server : "tcp://" + server;
+ }
+
+ public boolean isDebug() {
+ return debug;
+ }
+
+ public void setDebug(boolean value) {
+ debug = value;
+ }
+
+ Thread thread;
+ Thread watchDog;
+
+ @Override
+ protected void doInitialize() throws IOException, InterruptedException {
+ doClose();
+ super.doInitialize();
+
+ chrono = new Chrono();
+ thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ subscriberTask();
+ }
+ });
+ thread.setDaemon(true);
+ thread.start();
+
+ watchDog = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ while (!Thread.currentThread().isInterrupted()) {
+ if (chrono.isTimeout(3000)) {
+ setState(State.Offline);
+ if (Controller.getInstance() != null) {
+ Controller.getInstance().clearPuckStates();
+ }
+ }
+ Thread.sleep(1000);
+ }
+ } catch (Exception ex) {
+ getLogger().log(Level.INFO, null, ex);
+ }
+ }
+ });
+ watchDog.setDaemon(true);
+ watchDog.start();
+ }
+
+ void subscriberTask() {
+ try {
+ setState(State.Ready);
+ if (isSimulated()) {
+ while (!Thread.currentThread().isInterrupted()) {
+ 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 (Controller.getInstance() != null) {
+ Controller.getInstance().updateView();
+ }
+ chrono = new Chrono();
+ Thread.sleep(2000);
+ }
+ } else {
+ org.zeromq.ZMQ.Context context = org.zeromq.ZMQ.context(1);
+ org.zeromq.ZMQ.Socket subscriber = context.socket(org.zeromq.ZMQ.SUB);
+ subscriber.connect(server);
+ //subscriber.subscribe("Status".getBytes());
+ subscriber.subscribe("".getBytes());
+ try {
+ if (debug) {
+ System.out.println("Start listening");
+ }
+ while (!Thread.currentThread().isInterrupted()) {
+ //String type = subscriber.recvStr();
+ //System.out.println(type);
+ String contents = subscriber.recvStr();
+ if (debug) {
+ System.out.println(contents);
+ }
+ processMessage(contents);
+
+ if (Controller.getInstance() != null) {
+ Controller.getInstance().updateView();
+ }
+ setState(State.Ready);
+ chrono = new Chrono();
+ }
+ } finally {
+ if (debug) {
+ System.out.println("Stop listening");
+ }
+
+ if (Controller.getInstance() != null) {
+ Controller.getInstance().clearPuckStates();
+ }
+ subscriber.close();
+ context.term();
+ }
+ }
+ } catch (Exception ex) {
+ getLogger().log(Level.INFO, null, ex);
+ }
+ setState(State.Offline);
+ }
+
+ void processMessage(String str) {
+ try {
+ //System.out.println(str);
+ List detection = (List) JsonSerializer.decode(str, List.class);
+
+ int address = 1;
+ for (List bus : detection) {
+ for (List sensor : bus) {
+ Integer indDetector = sensor.get(0);
+ Integer mecDetector = sensor.get(1);
+ int index = Controller.getInstance().getPuckIndex(address);
+ PuckState puck = Controller.getInstance().getPuckState(index);
+ puck.set(mecDetector, indDetector);
+ address++;
+ }
+ }
+ setCache(str);
+ } catch (Exception ex) {
+ getLogger().log(Level.INFO, null, ex);
+ }
+ }
+
+ @Override
+ protected void doClose() {
+ if (watchDog != null) {
+ watchDog.interrupt();
+ watchDog = null;
+ }
+ if (thread != null) {
+ thread.interrupt();
+ thread = null;
+ }
+ }
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ PuckDetection pd = new PuckDetection("PD", "129.129.110.99:5556");
+ //PuckDetection pd = new PuckDetection("PD","raspberrypi:5556");
+ pd.setDebug(true);
+ pd.initialize();
+ Thread.sleep(100000);
+ }
+}
diff --git a/src/main/java/ch/psi/mxsc/Sample.java b/src/main/java/ch/psi/mxsc/Sample.java
index 32b020f..864a112 100644
--- a/src/main/java/ch/psi/mxsc/Sample.java
+++ b/src/main/java/ch/psi/mxsc/Sample.java
@@ -58,6 +58,10 @@ public class Sample extends DeviceBase {
return selected && getPuck().getBasePlate().isSelectable();
}
+ public void toggleSelected(boolean value) {
+ setSelected(!selected);
+ }
+
public void setSelected(boolean value) {
if (value != selected){
if (value == true){