/*
* Copyright (C) 2011 Jason von Nieda <jason@vonnieda.org>
*
* This file is part of OpenPnP.
*
* OpenPnP is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* OpenPnP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with OpenPnP. If not, see
* <http://www.gnu.org/licenses/>.
*
* For more information about OpenPnP visit http://openpnp.org
*/
package org.openpnp.machine.reference.feeder.wizards;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.Bindings;
import org.openpnp.gui.MainFrame;
import org.openpnp.gui.components.CameraView;
import org.openpnp.gui.components.ComponentDecorators;
import org.openpnp.gui.components.LocationButtonsPanel;
import org.openpnp.gui.support.BufferedImageIconConverter;
import org.openpnp.gui.support.DoubleConverter;
import org.openpnp.gui.support.IntegerConverter;
import org.openpnp.gui.support.LengthConverter;
import org.openpnp.gui.support.MessageBoxes;
import org.openpnp.gui.support.MutableLocationProxy;
import org.openpnp.gui.support.PercentConverter;
import org.openpnp.machine.reference.feeder.ReferenceDragFeeder;
import org.openpnp.model.Configuration;
import org.openpnp.spi.Camera;
import org.openpnp.util.UiUtils;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.FormSpecs;
import com.jgoodies.forms.layout.RowSpec;
@SuppressWarnings("serial")
public class ReferenceDragFeederConfigurationWizard
extends AbstractReferenceFeederConfigurationWizard {
private final ReferenceDragFeeder feeder;
private JTextField textFieldFeedStartX;
private JTextField textFieldFeedStartY;
private JTextField textFieldFeedStartZ;
private JTextField textFieldFeedEndX;
private JTextField textFieldFeedEndY;
private JTextField textFieldFeedEndZ;
private JTextField textFieldFeedRate;
private JLabel lblActuatorId;
private JTextField textFieldActuatorId;
private JPanel panelGeneral;
private JPanel panelVision;
private JPanel panelLocations;
private JCheckBox chckbxVisionEnabled;
private JPanel panelVisionEnabled;
private JPanel panelTemplate;
private JLabel labelTemplateImage;
private JButton btnChangeTemplateImage;
private JSeparator separator;
private JPanel panelVisionTemplateAndAoe;
private JPanel panelAoE;
private JLabel lblX_1;
private JLabel lblY_1;
private JTextField textFieldAoiX;
private JTextField textFieldAoiY;
private JTextField textFieldAoiWidth;
private JTextField textFieldAoiHeight;
private LocationButtonsPanel locationButtonsPanelFeedStart;
private LocationButtonsPanel locationButtonsPanelFeedEnd;
private JLabel lblWidth;
private JLabel lblHeight;
private JButton btnChangeAoi;
private JButton btnCancelChangeAoi;
private JPanel panel;
private JButton btnCancelChangeTemplateImage;
public ReferenceDragFeederConfigurationWizard(ReferenceDragFeeder feeder) {
super(feeder);
this.feeder = feeder;
JPanel panelFields = new JPanel();
panelFields.setLayout(new BoxLayout(panelFields, BoxLayout.Y_AXIS));
panelGeneral = new JPanel();
panelGeneral.setBorder(new TitledBorder(null, "General Settings", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
panelFields.add(panelGeneral);
panelGeneral.setLayout(new FormLayout(
new ColumnSpec[] {FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,},
new RowSpec[] {FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,
FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,}));
JLabel lblFeedRate = new JLabel("Feed Speed %");
panelGeneral.add(lblFeedRate, "2, 2");
textFieldFeedRate = new JTextField();
panelGeneral.add(textFieldFeedRate, "4, 2");
textFieldFeedRate.setColumns(5);
lblActuatorId = new JLabel("Actuator Name");
panelGeneral.add(lblActuatorId, "2, 4, right, default");
textFieldActuatorId = new JTextField();
panelGeneral.add(textFieldActuatorId, "4, 4");
textFieldActuatorId.setColumns(5);
panelLocations = new JPanel();
panelFields.add(panelLocations);
panelLocations.setBorder(new TitledBorder(null, "Locations", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
panelLocations.setLayout(new FormLayout(
new ColumnSpec[] {FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, ColumnSpec.decode("left:default:grow"),},
new RowSpec[] {FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,
FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,
FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,
FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,}));
JLabel lblX = new JLabel("X");
panelLocations.add(lblX, "4, 4");
JLabel lblY = new JLabel("Y");
panelLocations.add(lblY, "6, 4");
JLabel lblZ = new JLabel("Z");
panelLocations.add(lblZ, "8, 4");
JLabel lblFeedStartLocation = new JLabel("Feed Start Location");
panelLocations.add(lblFeedStartLocation, "2, 6, right, default");
textFieldFeedStartX = new JTextField();
panelLocations.add(textFieldFeedStartX, "4, 6");
textFieldFeedStartX.setColumns(8);
textFieldFeedStartY = new JTextField();
panelLocations.add(textFieldFeedStartY, "6, 6");
textFieldFeedStartY.setColumns(8);
textFieldFeedStartZ = new JTextField();
panelLocations.add(textFieldFeedStartZ, "8, 6");
textFieldFeedStartZ.setColumns(8);
locationButtonsPanelFeedStart = new LocationButtonsPanel(textFieldFeedStartX,
textFieldFeedStartY, textFieldFeedStartZ, null);
panelLocations.add(locationButtonsPanelFeedStart, "10, 6");
JLabel lblFeedEndLocation = new JLabel("Feed End Location");
panelLocations.add(lblFeedEndLocation, "2, 8, right, default");
textFieldFeedEndX = new JTextField();
panelLocations.add(textFieldFeedEndX, "4, 8");
textFieldFeedEndX.setColumns(8);
textFieldFeedEndY = new JTextField();
panelLocations.add(textFieldFeedEndY, "6, 8");
textFieldFeedEndY.setColumns(8);
textFieldFeedEndZ = new JTextField();
panelLocations.add(textFieldFeedEndZ, "8, 8");
textFieldFeedEndZ.setColumns(8);
locationButtonsPanelFeedEnd = new LocationButtonsPanel(textFieldFeedEndX, textFieldFeedEndY,
textFieldFeedEndZ, null);
panelLocations.add(locationButtonsPanelFeedEnd, "10, 8");
//
panelVision = new JPanel();
panelVision.setBorder(new TitledBorder(null, "Vision", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
panelFields.add(panelVision);
panelVision.setLayout(new BoxLayout(panelVision, BoxLayout.Y_AXIS));
panelVisionEnabled = new JPanel();
FlowLayout fl_panelVisionEnabled = (FlowLayout) panelVisionEnabled.getLayout();
fl_panelVisionEnabled.setAlignment(FlowLayout.LEFT);
panelVision.add(panelVisionEnabled);
chckbxVisionEnabled = new JCheckBox("Vision Enabled?");
panelVisionEnabled.add(chckbxVisionEnabled);
separator = new JSeparator();
panelVision.add(separator);
panelVisionTemplateAndAoe = new JPanel();
panelVision.add(panelVisionTemplateAndAoe);
panelVisionTemplateAndAoe.setLayout(new FormLayout(
new ColumnSpec[] {FormSpecs.LABEL_COMPONENT_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,},
new RowSpec[] {FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,}));
panelTemplate = new JPanel();
panelTemplate.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null),
"Template Image", TitledBorder.LEADING, TitledBorder.TOP, null,
new Color(0, 0, 0)));
panelVisionTemplateAndAoe.add(panelTemplate, "2, 2, center, fill");
panelTemplate.setLayout(new BoxLayout(panelTemplate, BoxLayout.Y_AXIS));
labelTemplateImage = new JLabel("");
labelTemplateImage.setAlignmentX(Component.CENTER_ALIGNMENT);
panelTemplate.add(labelTemplateImage);
labelTemplateImage.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
labelTemplateImage.setMinimumSize(new Dimension(150, 150));
labelTemplateImage.setMaximumSize(new Dimension(150, 150));
labelTemplateImage.setHorizontalAlignment(SwingConstants.CENTER);
labelTemplateImage.setSize(new Dimension(150, 150));
labelTemplateImage.setPreferredSize(new Dimension(150, 150));
panel = new JPanel();
panelTemplate.add(panel);
btnChangeTemplateImage = new JButton(selectTemplateImageAction);
panel.add(btnChangeTemplateImage);
btnChangeTemplateImage.setAlignmentX(Component.CENTER_ALIGNMENT);
btnCancelChangeTemplateImage = new JButton(cancelSelectTemplateImageAction);
panel.add(btnCancelChangeTemplateImage);
panelAoE = new JPanel();
panelAoE.setBorder(new TitledBorder(null, "Area of Interest", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
panelVisionTemplateAndAoe.add(panelAoE, "4, 2, fill, fill");
panelAoE.setLayout(new FormLayout(
new ColumnSpec[] {FormSpecs.RELATED_GAP_COLSPEC, ColumnSpec.decode("default:grow"),
FormSpecs.RELATED_GAP_COLSPEC, ColumnSpec.decode("default:grow"),
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,
FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC,},
new RowSpec[] {FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,
FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,}));
lblX_1 = new JLabel("X");
panelAoE.add(lblX_1, "2, 2");
lblY_1 = new JLabel("Y");
panelAoE.add(lblY_1, "4, 2");
lblWidth = new JLabel("Width");
panelAoE.add(lblWidth, "6, 2");
lblHeight = new JLabel("Height");
panelAoE.add(lblHeight, "8, 2");
textFieldAoiX = new JTextField();
panelAoE.add(textFieldAoiX, "2, 4, fill, default");
textFieldAoiX.setColumns(5);
textFieldAoiY = new JTextField();
panelAoE.add(textFieldAoiY, "4, 4, fill, default");
textFieldAoiY.setColumns(5);
textFieldAoiWidth = new JTextField();
panelAoE.add(textFieldAoiWidth, "6, 4, fill, default");
textFieldAoiWidth.setColumns(5);
textFieldAoiHeight = new JTextField();
panelAoE.add(textFieldAoiHeight, "8, 4, fill, default");
textFieldAoiHeight.setColumns(5);
btnChangeAoi = new JButton("Change");
btnChangeAoi.setAction(selectAoiAction);
panelAoE.add(btnChangeAoi, "10, 4");
btnCancelChangeAoi = new JButton("Cancel");
btnCancelChangeAoi.setAction(cancelSelectAoiAction);
panelAoE.add(btnCancelChangeAoi, "12, 4");
cancelSelectTemplateImageAction.setEnabled(false);
cancelSelectAoiAction.setEnabled(false);
contentPanel.add(panelFields);
}
@Override
public void createBindings() {
super.createBindings();
LengthConverter lengthConverter = new LengthConverter();
IntegerConverter intConverter = new IntegerConverter();
DoubleConverter doubleConverter =
new DoubleConverter(Configuration.get().getLengthDisplayFormat());
BufferedImageIconConverter imageConverter = new BufferedImageIconConverter();
PercentConverter percentConverter = new PercentConverter();
addWrappedBinding(feeder, "feedSpeed", textFieldFeedRate, "text", percentConverter);
addWrappedBinding(feeder, "actuatorName", textFieldActuatorId, "text");
MutableLocationProxy feedStartLocation = new MutableLocationProxy();
bind(UpdateStrategy.READ_WRITE, feeder, "feedStartLocation", feedStartLocation, "location");
addWrappedBinding(feedStartLocation, "lengthX", textFieldFeedStartX, "text",
lengthConverter);
addWrappedBinding(feedStartLocation, "lengthY", textFieldFeedStartY, "text",
lengthConverter);
addWrappedBinding(feedStartLocation, "lengthZ", textFieldFeedStartZ, "text",
lengthConverter);
MutableLocationProxy feedEndLocation = new MutableLocationProxy();
bind(UpdateStrategy.READ_WRITE, feeder, "feedEndLocation", feedEndLocation, "location");
addWrappedBinding(feedEndLocation, "lengthX", textFieldFeedEndX, "text", lengthConverter);
addWrappedBinding(feedEndLocation, "lengthY", textFieldFeedEndY, "text", lengthConverter);
addWrappedBinding(feedEndLocation, "lengthZ", textFieldFeedEndZ, "text", lengthConverter);
addWrappedBinding(feeder, "vision.enabled", chckbxVisionEnabled, "selected");
addWrappedBinding(feeder, "vision.templateImage", labelTemplateImage, "icon",
imageConverter);
addWrappedBinding(feeder, "vision.areaOfInterest.x", textFieldAoiX, "text", intConverter);
addWrappedBinding(feeder, "vision.areaOfInterest.y", textFieldAoiY, "text", intConverter);
addWrappedBinding(feeder, "vision.areaOfInterest.width", textFieldAoiWidth, "text",
intConverter);
addWrappedBinding(feeder, "vision.areaOfInterest.height", textFieldAoiHeight, "text",
intConverter);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedRate);
ComponentDecorators.decorateWithAutoSelect(textFieldActuatorId);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedStartX);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedStartY);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedStartZ);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedEndX);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedEndY);
ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldFeedEndZ);
ComponentDecorators.decorateWithAutoSelect(textFieldAoiX);
ComponentDecorators.decorateWithAutoSelect(textFieldAoiY);
ComponentDecorators.decorateWithAutoSelect(textFieldAoiWidth);
ComponentDecorators.decorateWithAutoSelect(textFieldAoiHeight);
BeanProperty actuatorIdProperty = BeanProperty.create("actuatorId");
Bindings.createAutoBinding(UpdateStrategy.READ, feeder, actuatorIdProperty,
locationButtonsPanelFeedStart, actuatorIdProperty).bind();
Bindings.createAutoBinding(UpdateStrategy.READ, feeder, actuatorIdProperty,
locationButtonsPanelFeedEnd, actuatorIdProperty).bind();
}
@SuppressWarnings("serial")
private Action selectTemplateImageAction = new AbstractAction("Select") {
@Override
public void actionPerformed(ActionEvent arg0) {
UiUtils.messageBoxOnException(() -> {
Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead()
.getDefaultCamera();
CameraView cameraView = MainFrame.get().getCameraViews().setSelectedCamera(camera);
cameraView.setSelectionEnabled(true);
// org.openpnp.model.Rectangle r =
// feeder.getVision().getTemplateImageCoordinates();
org.openpnp.model.Rectangle r = null;
if (r == null || r.getWidth() == 0 || r.getHeight() == 0) {
cameraView.setSelection(0, 0, 100, 100);
}
else {
// cameraView.setSelection(r.getLeft(), r.getTop(),
// r.getWidth(), r.getHeight());
}
btnChangeTemplateImage.setAction(confirmSelectTemplateImageAction);
cancelSelectTemplateImageAction.setEnabled(true);
});
}
};
@SuppressWarnings("serial")
private Action confirmSelectTemplateImageAction = new AbstractAction("Confirm") {
@Override
public void actionPerformed(ActionEvent arg0) {
UiUtils.messageBoxOnException(() -> {
Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead()
.getDefaultCamera();
CameraView cameraView = MainFrame.get().getCameraViews().setSelectedCamera(camera);
BufferedImage image = cameraView.captureSelectionImage();
if (image == null) {
MessageBoxes.errorBox(ReferenceDragFeederConfigurationWizard.this,
"No Image Selected",
"Please select an area of the camera image using the mouse.");
}
else {
labelTemplateImage.setIcon(new ImageIcon(image));
}
cameraView.setSelectionEnabled(false);
btnChangeTemplateImage.setAction(selectTemplateImageAction);
cancelSelectTemplateImageAction.setEnabled(false);
});
}
};
@SuppressWarnings("serial")
private Action cancelSelectTemplateImageAction = new AbstractAction("Cancel") {
@Override
public void actionPerformed(ActionEvent arg0) {
UiUtils.messageBoxOnException(() -> {
Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead()
.getDefaultCamera();
CameraView cameraView = MainFrame.get().getCameraViews().setSelectedCamera(camera);
btnChangeTemplateImage.setAction(selectTemplateImageAction);
cancelSelectTemplateImageAction.setEnabled(false);
cameraView.setSelectionEnabled(false);
});
}
};
@SuppressWarnings("serial")
private Action selectAoiAction = new AbstractAction("Select") {
@Override
public void actionPerformed(ActionEvent arg0) {
UiUtils.messageBoxOnException(() -> {
Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead()
.getDefaultCamera();
CameraView cameraView = MainFrame.get().getCameraViews().setSelectedCamera(camera);
btnChangeAoi.setAction(confirmSelectAoiAction);
cancelSelectAoiAction.setEnabled(true);
cameraView.setSelectionEnabled(true);
org.openpnp.model.Rectangle r = feeder.getVision().getAreaOfInterest();
if (r == null || r.getWidth() == 0 || r.getHeight() == 0) {
cameraView.setSelection(0, 0, 100, 100);
}
else {
cameraView.setSelection(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
});
}
};
@SuppressWarnings("serial")
private Action confirmSelectAoiAction = new AbstractAction("Confirm") {
@Override
public void actionPerformed(ActionEvent arg0) {
UiUtils.messageBoxOnException(() -> {
Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead()
.getDefaultCamera();
CameraView cameraView = MainFrame.get().getCameraViews().setSelectedCamera(camera);
btnChangeAoi.setAction(selectAoiAction);
cancelSelectAoiAction.setEnabled(false);
cameraView.setSelectionEnabled(false);
final Rectangle rect = cameraView.getSelection();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textFieldAoiX.setText(Integer.toString(rect.x));
textFieldAoiY.setText(Integer.toString(rect.y));
textFieldAoiWidth.setText(Integer.toString(rect.width));
textFieldAoiHeight.setText(Integer.toString(rect.height));
}
});
});
}
};
@SuppressWarnings("serial")
private Action cancelSelectAoiAction = new AbstractAction("Cancel") {
@Override
public void actionPerformed(ActionEvent arg0) {
UiUtils.messageBoxOnException(() -> {
Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead()
.getDefaultCamera();
CameraView cameraView = MainFrame.get().getCameraViews().setSelectedCamera(camera);
btnChangeAoi.setAction(selectAoiAction);
cancelSelectAoiAction.setEnabled(false);
btnChangeAoi.setAction(selectAoiAction);
cancelSelectAoiAction.setEnabled(false);
cameraView.setSelectionEnabled(false);
});
}
};
}