/* * 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.wizards; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.border.TitledBorder; import javax.swing.table.AbstractTableModel; import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy; import org.openpnp.ConfigurationListener; import org.openpnp.gui.MainFrame; import org.openpnp.gui.components.AutoSelectTextTable; import org.openpnp.gui.components.ComponentDecorators; import org.openpnp.gui.components.LocationButtonsPanel; import org.openpnp.gui.support.AbstractConfigurationWizard; import org.openpnp.gui.support.IntegerConverter; import org.openpnp.gui.support.LengthConverter; import org.openpnp.gui.support.MutableLocationProxy; import org.openpnp.machine.reference.ReferenceNozzleTip; import org.openpnp.model.Configuration; import org.openpnp.util.UiUtils; import org.openpnp.vision.pipeline.CvPipeline; import org.openpnp.vision.pipeline.ui.CvPipelineEditor; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.FormSpecs; import com.jgoodies.forms.layout.RowSpec; public class ReferenceNozzleTipConfigurationWizard extends AbstractConfigurationWizard { private final ReferenceNozzleTip nozzleTip; private JPanel panelChanger; private JLabel lblX_1; private JLabel lblY_1; private JLabel lblZ_1; private LocationButtonsPanel changerStartLocationButtonsPanel; private JLabel lblStartLocation; private JTextField textFieldChangerStartX; private JTextField textFieldChangerStartY; private JTextField textFieldChangerStartZ; private JLabel lblMiddleLocation; private JTextField textFieldChangerMidX; private JTextField textFieldChangerMidY; private JTextField textFieldChangerMidZ; private JLabel lblEndLocation; private JTextField textFieldChangerEndX; private JTextField textFieldChangerEndY; private JTextField textFieldChangerEndZ; private LocationButtonsPanel changerMidLocationButtonsPanel; private LocationButtonsPanel changerEndLocationButtonsPanel; private JPanel panelPackageCompat; private JCheckBox chckbxAllowIncompatiblePackages; private JScrollPane scrollPane; private JTable table; private PackagesTableModel tableModel; private Set<org.openpnp.model.Package> compatiblePackages = new HashSet<>(); private JPanel panelCalibration; private JButton btnEditPipeline; private JButton btnCalibrate; private JButton btnReset; private JLabel lblEnabled; private JCheckBox calibrationEnabledCheckbox; private JLabel lblMiddleLocation_1; private JTextField textFieldMidX2; private JTextField textFieldMidY2; private JTextField textFieldMidZ2; private LocationButtonsPanel changerMidButtons2; private JPanel panelVacuumSensing; private JLabel lblPartOnNozzle; private JLabel lblPartOffNozzle; private JTextField vacuumLevelPartOn; private JTextField vacuumLevelPartOff; public ReferenceNozzleTipConfigurationWizard(ReferenceNozzleTip nozzleTip) { this.nozzleTip = nozzleTip; panelPackageCompat = new JPanel(); panelPackageCompat.setBorder(new TitledBorder(null, "Package Compatibility", TitledBorder.LEADING, TitledBorder.TOP, null, null)); contentPanel.add(panelPackageCompat); panelPackageCompat.setLayout(new FormLayout( new ColumnSpec[] {FormSpecs.RELATED_GAP_COLSPEC, ColumnSpec.decode("default:grow"),}, new RowSpec[] {FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.RELATED_GAP_ROWSPEC, RowSpec.decode("max(100dlu;min)"),})); chckbxAllowIncompatiblePackages = new JCheckBox("Allow Incompatible Packages?"); panelPackageCompat.add(chckbxAllowIncompatiblePackages, "2, 2"); scrollPane = new JScrollPane(); panelPackageCompat.add(scrollPane, "2, 4, fill, default"); table = new AutoSelectTextTable(tableModel = new PackagesTableModel()); scrollPane.setViewportView(table); panelChanger = new JPanel(); panelChanger.setBorder(new TitledBorder(null, "Nozzle Tip Changer", TitledBorder.LEADING, TitledBorder.TOP, null, null)); contentPanel.add(panelChanger); panelChanger.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, FormSpecs.DEFAULT_COLSPEC,}, 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, FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,})); lblX_1 = new JLabel("X"); panelChanger.add(lblX_1, "4, 2"); lblY_1 = new JLabel("Y"); panelChanger.add(lblY_1, "6, 2"); lblZ_1 = new JLabel("Z"); panelChanger.add(lblZ_1, "8, 2"); lblStartLocation = new JLabel("First Location"); panelChanger.add(lblStartLocation, "2, 4, right, default"); textFieldChangerStartX = new JTextField(); panelChanger.add(textFieldChangerStartX, "4, 4, fill, default"); textFieldChangerStartX.setColumns(5); textFieldChangerStartY = new JTextField(); panelChanger.add(textFieldChangerStartY, "6, 4, fill, default"); textFieldChangerStartY.setColumns(5); textFieldChangerStartZ = new JTextField(); panelChanger.add(textFieldChangerStartZ, "8, 4, fill, default"); textFieldChangerStartZ.setColumns(5); changerStartLocationButtonsPanel = new LocationButtonsPanel(textFieldChangerStartX, textFieldChangerStartY, textFieldChangerStartZ, (JTextField) null); changerStartLocationButtonsPanel.setShowPositionToolNoSafeZ(true); panelChanger.add(changerStartLocationButtonsPanel, "10, 4, fill, default"); lblMiddleLocation = new JLabel("Second Location"); panelChanger.add(lblMiddleLocation, "2, 6, right, default"); textFieldChangerMidX = new JTextField(); panelChanger.add(textFieldChangerMidX, "4, 6, fill, default"); textFieldChangerMidX.setColumns(5); textFieldChangerMidY = new JTextField(); panelChanger.add(textFieldChangerMidY, "6, 6, fill, default"); textFieldChangerMidY.setColumns(5); textFieldChangerMidZ = new JTextField(); panelChanger.add(textFieldChangerMidZ, "8, 6, fill, default"); textFieldChangerMidZ.setColumns(5); changerMidLocationButtonsPanel = new LocationButtonsPanel(textFieldChangerMidX, textFieldChangerMidY, textFieldChangerMidZ, (JTextField) null); changerMidLocationButtonsPanel.setShowPositionToolNoSafeZ(true); panelChanger.add(changerMidLocationButtonsPanel, "10, 6, fill, default"); lblMiddleLocation_1 = new JLabel("Third Location"); panelChanger.add(lblMiddleLocation_1, "2, 8, right, default"); textFieldMidX2 = new JTextField(); textFieldMidX2.setColumns(5); panelChanger.add(textFieldMidX2, "4, 8, fill, default"); textFieldMidY2 = new JTextField(); textFieldMidY2.setColumns(5); panelChanger.add(textFieldMidY2, "6, 8, fill, default"); textFieldMidZ2 = new JTextField(); textFieldMidZ2.setColumns(5); panelChanger.add(textFieldMidZ2, "8, 8, fill, default"); changerMidButtons2 = new LocationButtonsPanel(textFieldMidX2, textFieldMidY2, textFieldMidZ2, (JTextField) null); changerMidButtons2.setShowPositionToolNoSafeZ(true); panelChanger.add(changerMidButtons2, "10, 8, fill, default"); lblEndLocation = new JLabel("Last Location"); panelChanger.add(lblEndLocation, "2, 10, right, default"); textFieldChangerEndX = new JTextField(); panelChanger.add(textFieldChangerEndX, "4, 10, fill, default"); textFieldChangerEndX.setColumns(5); textFieldChangerEndY = new JTextField(); panelChanger.add(textFieldChangerEndY, "6, 10, fill, default"); textFieldChangerEndY.setColumns(5); textFieldChangerEndZ = new JTextField(); panelChanger.add(textFieldChangerEndZ, "8, 10, fill, default"); textFieldChangerEndZ.setColumns(5); changerEndLocationButtonsPanel = new LocationButtonsPanel(textFieldChangerEndX, textFieldChangerEndY, textFieldChangerEndZ, (JTextField) null); changerEndLocationButtonsPanel.setShowPositionToolNoSafeZ(true); panelChanger.add(changerEndLocationButtonsPanel, "10, 10, fill, default"); panelVacuumSensing = new JPanel(); panelVacuumSensing.setBorder(new TitledBorder(null, "Vacuum Sensing", TitledBorder.LEADING, TitledBorder.TOP, null, null)); contentPanel.add(panelVacuumSensing); panelVacuumSensing.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,})); lblPartOnNozzle = new JLabel("Part On Nozzle Vacuum Value"); panelVacuumSensing.add(lblPartOnNozzle, "2, 2, right, default"); vacuumLevelPartOn = new JTextField(); panelVacuumSensing.add(vacuumLevelPartOn, "4, 2"); vacuumLevelPartOn.setColumns(10); lblPartOffNozzle = new JLabel("Part Off Nozzle Vacuum Value"); panelVacuumSensing.add(lblPartOffNozzle, "2, 4, right, default"); vacuumLevelPartOff = new JTextField(); panelVacuumSensing.add(vacuumLevelPartOff, "4, 4"); vacuumLevelPartOff.setColumns(10); panelCalibration = new JPanel(); panelCalibration.setBorder(new TitledBorder(null, "Calibration", TitledBorder.LEADING, TitledBorder.TOP, null, null)); // TODO: Removing panel until this feature is actually working. // See: https://github.com/openpnp/openpnp/issues/235 // contentPanel.add(panelCalibration); panelCalibration.setLayout(new FormLayout( new ColumnSpec[] {FormSpecs.RELATED_GAP_COLSPEC, FormSpecs.DEFAULT_COLSPEC, FormSpecs.DEFAULT_COLSPEC,}, new RowSpec[] {FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, RowSpec.decode("23px"), FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC, FormSpecs.RELATED_GAP_ROWSPEC, FormSpecs.DEFAULT_ROWSPEC,})); lblEnabled = new JLabel("Enabled?"); panelCalibration.add(lblEnabled, "2, 2, right, default"); calibrationEnabledCheckbox = new JCheckBox(""); panelCalibration.add(calibrationEnabledCheckbox, "3, 2, left, default"); btnCalibrate = new JButton("Calibrate"); btnCalibrate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { calibrate(); } }); panelCalibration.add(btnCalibrate, "3, 3"); btnReset = new JButton("Reset"); btnReset.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { nozzleTip.getCalibration().reset(); } }); panelCalibration.add(btnReset, "3, 5"); btnEditPipeline = new JButton("Edit Pipeline"); btnEditPipeline.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { UiUtils.messageBoxOnException(() -> { editCalibrationPipeline(); }); } }); panelCalibration.add(btnEditPipeline, "3, 7, left, top"); } private void editCalibrationPipeline() throws Exception { CvPipeline pipeline = nozzleTip.getCalibration().getPipeline(); CvPipelineEditor editor = new CvPipelineEditor(pipeline); JDialog dialog = new JDialog(MainFrame.get(), "Calibration Pipeline"); dialog.getContentPane().setLayout(new BorderLayout()); dialog.getContentPane().add(editor); dialog.setSize(1024, 768); dialog.setVisible(true); } private void calibrate() { UiUtils.submitUiMachineTask(() -> { nozzleTip.getCalibration().calibrate(nozzleTip); }); } @Override public void createBindings() { LengthConverter lengthConverter = new LengthConverter(); IntegerConverter intConverter = new IntegerConverter(); addWrappedBinding(nozzleTip, "allowIncompatiblePackages", chckbxAllowIncompatiblePackages, "selected"); MutableLocationProxy changerStartLocation = new MutableLocationProxy(); bind(UpdateStrategy.READ_WRITE, nozzleTip, "changerStartLocation", changerStartLocation, "location"); addWrappedBinding(changerStartLocation, "lengthX", textFieldChangerStartX, "text", lengthConverter); addWrappedBinding(changerStartLocation, "lengthY", textFieldChangerStartY, "text", lengthConverter); addWrappedBinding(changerStartLocation, "lengthZ", textFieldChangerStartZ, "text", lengthConverter); MutableLocationProxy changerMidLocation = new MutableLocationProxy(); bind(UpdateStrategy.READ_WRITE, nozzleTip, "changerMidLocation", changerMidLocation, "location"); addWrappedBinding(changerMidLocation, "lengthX", textFieldChangerMidX, "text", lengthConverter); addWrappedBinding(changerMidLocation, "lengthY", textFieldChangerMidY, "text", lengthConverter); addWrappedBinding(changerMidLocation, "lengthZ", textFieldChangerMidZ, "text", lengthConverter); MutableLocationProxy changerMidLocation2 = new MutableLocationProxy(); bind(UpdateStrategy.READ_WRITE, nozzleTip, "changerMidLocation2", changerMidLocation2, "location"); addWrappedBinding(changerMidLocation2, "lengthX", textFieldMidX2, "text", lengthConverter); addWrappedBinding(changerMidLocation2, "lengthY", textFieldMidY2, "text", lengthConverter); addWrappedBinding(changerMidLocation2, "lengthZ", textFieldMidZ2, "text", lengthConverter); MutableLocationProxy changerEndLocation = new MutableLocationProxy(); bind(UpdateStrategy.READ_WRITE, nozzleTip, "changerEndLocation", changerEndLocation, "location"); addWrappedBinding(changerEndLocation, "lengthX", textFieldChangerEndX, "text", lengthConverter); addWrappedBinding(changerEndLocation, "lengthY", textFieldChangerEndY, "text", lengthConverter); addWrappedBinding(changerEndLocation, "lengthZ", textFieldChangerEndZ, "text", lengthConverter); addWrappedBinding(nozzleTip.getCalibration(), "enabled", calibrationEnabledCheckbox, "selected"); addWrappedBinding(nozzleTip, "vacuumLevelPartOn", vacuumLevelPartOn, "text", intConverter); addWrappedBinding(nozzleTip, "vacuumLevelPartOff", vacuumLevelPartOff, "text", intConverter); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerStartX); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerStartY); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerStartZ); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerMidX); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerMidY); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerMidZ); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldMidX2); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldMidY2); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldMidZ2); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerEndX); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerEndY); ComponentDecorators.decorateWithAutoSelectAndLengthConversion(textFieldChangerEndZ); ComponentDecorators.decorateWithAutoSelect(vacuumLevelPartOn); ComponentDecorators.decorateWithAutoSelect(vacuumLevelPartOff); } @Override protected void loadFromModel() { compatiblePackages.clear(); compatiblePackages.addAll(nozzleTip.getCompatiblePackages()); tableModel.refresh(); super.loadFromModel(); } @Override protected void saveToModel() { nozzleTip.setCompatiblePackages(compatiblePackages); super.saveToModel(); } public class PackagesTableModel extends AbstractTableModel { private String[] columnNames = new String[] {"Package Id", "Compatible?"}; private List<org.openpnp.model.Package> packages; public PackagesTableModel() { Configuration.get().addListener(new ConfigurationListener.Adapter() { public void configurationComplete(Configuration configuration) throws Exception { refresh(); } }); } public void refresh() { packages = new ArrayList<>(Configuration.get().getPackages()); fireTableDataChanged(); } @Override public String getColumnName(int column) { return columnNames[column]; } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return (packages == null) ? 0 : packages.size(); } public org.openpnp.model.Package getPackage(int index) { return packages.get(index); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex == 1; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { try { org.openpnp.model.Package pkg = packages.get(rowIndex); if (columnIndex == 1) { if ((Boolean) aValue) { compatiblePackages.add(pkg); } else { compatiblePackages.remove(pkg); } notifyChange(); } } catch (Exception e) { // TODO: dialog, bad input } } @Override public Class<?> getColumnClass(int columnIndex) { if (columnIndex == 1) { return Boolean.class; } return super.getColumnClass(columnIndex); } public Object getValueAt(int row, int col) { switch (col) { case 0: return packages.get(row).getId(); case 1: return compatiblePackages.contains(packages.get(row)); default: return null; } } } }