package tools.map.xml.creator; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.Optional; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import com.google.common.collect.Sets; /** * Base class for *Panel classes based on DynamicRow class with which it is interlinked. * Subclasses list row entries after a header line with labels and ends with a button row which * mostly consists only of an Add-button. * Each subclass can override the main "Auto-Fill" button with an own action. * Furthermore, this class contains a boolean variable describing whether the inputed data is consistent. * * @see DynamicRow * */ public abstract class DynamicRowsPanel { protected static Optional<DynamicRowsPanel> me = Optional.empty(); private final JPanel ownPanel; protected JPanel getOwnPanel() { return ownPanel; } private final JPanel stepActionPanel; private final ArrayList<JButton> finalRowButtons = new ArrayList<>(); boolean dataIsConsistent = true; public LinkedHashSet<DynamicRow> rows = Sets.newLinkedHashSet(); protected static void layout(final MapXmlCreator mapXmlCreator) { if (me.isPresent()) { me.get().resetRows(); mapXmlCreator.setAutoFillActionListener(me.get().getAutoFillAction()); } } public boolean dataIsConsistent() { return dataIsConsistent; } void setDataIsConsistent(final boolean dataIsConsistent) { this.dataIsConsistent = dataIsConsistent; } protected DynamicRowsPanel(final JPanel stepActionPanel) { this.stepActionPanel = stepActionPanel; ownPanel = new JPanel(); final Dimension size = stepActionPanel.getSize(); final JScrollPane js = new JScrollPane(ownPanel); js.setBorder(null); stepActionPanel.setLayout(new BorderLayout()); stepActionPanel.add(js, BorderLayout.CENTER); stepActionPanel.setPreferredSize(size); } protected void resetRows() { initialize(); ownPanel.removeAll(); // re-register scollPane on stepActionPanel final Container viewPort = ownPanel.getParent(); final Container scrollPane = viewPort.getParent(); if (scrollPane.getParent() == null) { if (!(stepActionPanel.getLayout() instanceof BorderLayout)) { stepActionPanel.setLayout(new BorderLayout()); } stepActionPanel.add(scrollPane, BorderLayout.CENTER); } layoutComponents(); dataIsConsistent = true; } private void initialize() { finalRowButtons.clear(); rows.clear(); me.get().initializeSpecifics(); } public void removeComponents(final ArrayList<JComponent> componentList) { for (final JComponent component : componentList) { ownPanel.remove(component); } } protected void addButton(final JButton newButton) { finalRowButtons.add(newButton); } protected void setRows(final GridBagLayout gblPanel, final int inputRows) { final int totalRows = inputRows + 3; // header row, button row, remaining space row gblPanel.rowHeights = new int[totalRows]; gblPanel.rowWeights = new double[totalRows]; for (int i = 0; i < totalRows; ++i) { gblPanel.rowHeights[i] = 32; gblPanel.rowWeights[i] = 0.0; } gblPanel.rowHeights[totalRows - 1] = 0; gblPanel.rowWeights[totalRows - 1] = Double.MIN_VALUE; } /** * @return number of rows. */ public int countRows() { return rows.size() + 1; } protected void addRow(final DynamicRow newRow) { removeFinalButtonRow(); final int countPlayers = countRows(); newRow.addToParentComponentWithGbc(ownPanel, countPlayers, MapXmlUIHelper.getGbcDefaultTemplateWith(0, countPlayers)); rows.add(newRow); final int finalButtonGridY = countPlayers + 1; addFinalButtonRow(MapXmlUIHelper.getGbcDefaultTemplateWith(0, finalButtonGridY)); } protected void addFinalButtonRow(final GridBagConstraints gbcTemplate) { int colIndex = 0; for (final JButton button : finalRowButtons) { final GridBagConstraints gbcCurrentButton = (GridBagConstraints) gbcTemplate.clone(); gbcCurrentButton.gridx = colIndex; ++colIndex; ownPanel.add(button, gbcCurrentButton); } } public void removeFinalButtonRow() { for (final JButton button : finalRowButtons) { ownPanel.remove(button); } } public LinkedHashSet<DynamicRow> getRows() { return rows; } protected abstract ActionListener getAutoFillAction(); protected abstract void layoutComponents(); protected abstract void initializeSpecifics(); protected abstract void setColumns(GridBagLayout gblPanel); protected void repaintOwnPanel() { SwingUtilities.invokeLater(() -> { resetRows(); ownPanel.revalidate(); ownPanel.repaint(); ownPanel.requestFocus(); }); } }