package org.openpnp.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.DefaultCellEditor; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JMenu; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToolBar; import javax.swing.ListSelectionModel; import javax.swing.border.LineBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import org.openpnp.gui.components.AutoSelectTextTable; import org.openpnp.gui.components.ClassSelectionDialog; import org.openpnp.gui.support.ActionGroup; import org.openpnp.gui.support.Helpers; import org.openpnp.gui.support.Icons; import org.openpnp.gui.support.MessageBoxes; import org.openpnp.gui.tablemodel.PadsTableModel; import org.openpnp.model.Board; import org.openpnp.model.Board.Side; import org.openpnp.model.BoardLocation; import org.openpnp.model.BoardPad; import org.openpnp.model.BoardPad.Type; import org.openpnp.model.Configuration; import org.openpnp.model.Location; import org.openpnp.model.Pad; import org.openpnp.spi.Camera; import org.openpnp.spi.PasteDispenser; import org.openpnp.util.MovableUtils; import org.openpnp.util.UiUtils; import org.openpnp.util.Utils2D; public class JobPastePanel extends JPanel { private JTable table; private PadsTableModel tableModel; private ActionGroup boardLocationSelectionActionGroup; private ActionGroup singleSelectionActionGroup; private ActionGroup multiSelectionActionGroup; private ActionGroup captureAndPositionActionGroup; private BoardLocation boardLocation; private static Color typeColorIgnore = new Color(252, 255, 157); private static Color typeColorPaste = new Color(157, 255, 168); public JobPastePanel(JobPanel jobPanel) { Configuration configuration = Configuration.get(); boardLocationSelectionActionGroup = new ActionGroup(newAction); boardLocationSelectionActionGroup.setEnabled(false); singleSelectionActionGroup = new ActionGroup(removeAction, setTypeAction); singleSelectionActionGroup.setEnabled(false); multiSelectionActionGroup = new ActionGroup(removeAction, setTypeAction); multiSelectionActionGroup.setEnabled(false); captureAndPositionActionGroup = new ActionGroup(moveCameraToPadLocation, moveToolToPadLocation); captureAndPositionActionGroup.setEnabled(false); JComboBox<Side> sidesComboBox = new JComboBox(Side.values()); JComboBox<Type> typesComboBox = new JComboBox(Type.values()); setLayout(new BorderLayout(0, 0)); JToolBar toolBar = new JToolBar(); add(toolBar, BorderLayout.NORTH); toolBar.setFloatable(false); JButton btnNewPad = new JButton(newAction); btnNewPad.setHideActionText(true); toolBar.add(btnNewPad); JButton btnRemovePad = new JButton(removeAction); btnRemovePad.setHideActionText(true); toolBar.add(btnRemovePad); toolBar.addSeparator(); JButton btnPositionCameraPositionLocation = new JButton(moveCameraToPadLocation); btnPositionCameraPositionLocation.setHideActionText(true); toolBar.add(btnPositionCameraPositionLocation); JButton btnPositionToolPositionLocation = new JButton(moveToolToPadLocation); btnPositionToolPositionLocation.setHideActionText(true); toolBar.add(btnPositionToolPositionLocation); toolBar.addSeparator(); tableModel = new PadsTableModel(configuration); table = new AutoSelectTextTable(tableModel); table.setAutoCreateRowSorter(true); table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); table.setDefaultEditor(Side.class, new DefaultCellEditor(sidesComboBox)); table.setDefaultRenderer(Type.class, new TypeRenderer()); table.setDefaultEditor(Type.class, new DefaultCellEditor(typesComboBox)); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } if (getSelections().size() > 1) { // multi select singleSelectionActionGroup.setEnabled(false); captureAndPositionActionGroup.setEnabled(false); multiSelectionActionGroup.setEnabled(true); } else { // single select, or no select multiSelectionActionGroup.setEnabled(false); singleSelectionActionGroup.setEnabled(getSelection() != null); captureAndPositionActionGroup.setEnabled(getSelection() != null && getSelection().getSide() == boardLocation.getSide()); } } }); table.addKeyListener(new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == ' ') { BoardPad pad = getSelection(); pad.setType(pad.getType() == Type.Paste ? Type.Ignore : Type.Paste); tableModel.fireTableRowsUpdated(table.getSelectedRow(), table.getSelectedRow()); } else { super.keyTyped(e); } } }); JPopupMenu popupMenu = new JPopupMenu(); JMenu setTypeMenu = new JMenu(setTypeAction); for (BoardPad.Type type : BoardPad.Type.values()) { setTypeMenu.add(new SetTypeAction(type)); } popupMenu.add(setTypeMenu); JMenu setSideMenu = new JMenu(setSideAction); for (Board.Side side : Board.Side.values()) { setSideMenu.add(new SetSideAction(side)); } popupMenu.add(setSideMenu); table.setComponentPopupMenu(popupMenu); JScrollPane scrollPane = new JScrollPane(table); add(scrollPane, BorderLayout.CENTER); } public void setBoardLocation(BoardLocation boardLocation) { this.boardLocation = boardLocation; if (boardLocation == null) { tableModel.setBoard(null); boardLocationSelectionActionGroup.setEnabled(false); } else { tableModel.setBoard(boardLocation.getBoard()); boardLocationSelectionActionGroup.setEnabled(true); } } public BoardPad getSelection() { List<BoardPad> selectedPads = getSelections(); if (selectedPads.isEmpty()) { return null; } return selectedPads.get(0); } public List<BoardPad> getSelections() { ArrayList<BoardPad> rows = new ArrayList<>(); if (boardLocation == null) { return rows; } int[] selectedRows = table.getSelectedRows(); for (int selectedRow : selectedRows) { selectedRow = table.convertRowIndexToModel(selectedRow); rows.add(boardLocation.getBoard().getSolderPastePads().get(selectedRow)); } return rows; } public final Action newAction = new AbstractAction() { { putValue(SMALL_ICON, Icons.add); putValue(NAME, "New Pad"); putValue(SHORT_DESCRIPTION, "Create a new pad and add it to the board."); } @Override public void actionPerformed(ActionEvent arg0) { List<Class<? extends Pad>> padClasses = new ArrayList<>(); padClasses.add(Pad.RoundRectangle.class); padClasses.add(Pad.Circle.class); padClasses.add(Pad.Ellipse.class); // See note on Pad.Line // padClasses.add(Pad.Line.class); ClassSelectionDialog<Pad> dialog = new ClassSelectionDialog<>( JOptionPane.getFrameForComponent(JobPastePanel.this), "Select Pad...", "Please select a pad type from the list below.", padClasses); dialog.setVisible(true); Class<? extends Pad> padClass = dialog.getSelectedClass(); if (padClass == null) { return; } try { Pad pad = padClass.newInstance(); BoardPad boardPad = new BoardPad(); boardPad.setLocation(new Location(Configuration.get().getSystemUnits())); boardPad.setPad(pad); boardLocation.getBoard().addSolderPastePad(boardPad); tableModel.fireTableDataChanged(); Helpers.selectLastTableRow(table); } catch (Exception e) { MessageBoxes.errorBox(JOptionPane.getFrameForComponent(JobPastePanel.this), "Pad Error", e); } } }; public final Action removeAction = new AbstractAction() { { putValue(SMALL_ICON, Icons.delete); putValue(NAME, "Remove Pad"); putValue(SHORT_DESCRIPTION, "Remove the currently selected pad."); } @Override public void actionPerformed(ActionEvent arg0) { for (BoardPad pad : getSelections()) { boardLocation.getBoard().removeSolderPastePad(pad); } tableModel.fireTableDataChanged(); } }; public final Action moveCameraToPadLocation = new AbstractAction() { { putValue(SMALL_ICON, Icons.centerCamera); putValue(NAME, "Move Camera To Pad Location"); putValue(SHORT_DESCRIPTION, "Position the camera at the pad's location."); } @Override public void actionPerformed(ActionEvent arg0) { UiUtils.submitUiMachineTask(() -> { Location location = Utils2D.calculateBoardPlacementLocation(boardLocation, getSelection().getLocation()); Camera camera = MainFrame.get().getMachineControls().getSelectedTool().getHead() .getDefaultCamera(); MovableUtils.moveToLocationAtSafeZ(camera, location); }); } }; public final Action moveToolToPadLocation = new AbstractAction() { { putValue(SMALL_ICON, Icons.centerTool); putValue(NAME, "Move Tool To Pad Location"); putValue(SHORT_DESCRIPTION, "Position the tool at the pad's location."); } @Override public void actionPerformed(ActionEvent arg0) { Location location = Utils2D.calculateBoardPlacementLocation(boardLocation, getSelection().getLocation()); PasteDispenser dispenser = MainFrame.get().getMachineControls().getSelectedPasteDispenser(); UiUtils.submitUiMachineTask(() -> { MovableUtils.moveToLocationAtSafeZ(dispenser, location); }); } }; public final Action setTypeAction = new AbstractAction() { { putValue(NAME, "Set Type"); putValue(SHORT_DESCRIPTION, "Set pad type(s) to..."); } @Override public void actionPerformed(ActionEvent arg0) {} }; class SetTypeAction extends AbstractAction { final BoardPad.Type type; public SetTypeAction(BoardPad.Type type) { this.type = type; putValue(NAME, type.toString()); putValue(SHORT_DESCRIPTION, "Set pad type(s) to " + type.toString()); } @Override public void actionPerformed(ActionEvent arg0) { for (BoardPad pad : getSelections()) { pad.setType(type); } } }; public final Action setSideAction = new AbstractAction() { { putValue(NAME, "Set Side"); putValue(SHORT_DESCRIPTION, "Set pad side(s) to..."); } @Override public void actionPerformed(ActionEvent arg0) {} }; class SetSideAction extends AbstractAction { final Board.Side side; public SetSideAction(Board.Side side) { this.side = side; putValue(NAME, side.toString()); putValue(SHORT_DESCRIPTION, "Set pad side(s) to " + side.toString()); } @Override public void actionPerformed(ActionEvent arg0) { for (BoardPad pad : getSelections()) { pad.setSide(side); } } }; static class TypeRenderer extends DefaultTableCellRenderer { public void setValue(Object value) { Type type = (Type) value; setText(type.name()); if (type == Type.Paste) { setBorder(new LineBorder(getBackground())); setForeground(Color.black); setBackground(typeColorPaste); } else if (type == Type.Ignore) { setBorder(new LineBorder(getBackground())); setForeground(Color.black); setBackground(typeColorIgnore); } } } }