package org.leumasjaffe.recipe.view; import java.awt.Component; import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; import javax.swing.JPanel; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.jdesktop.swingx.VerticalLayout; import org.leumasjaffe.event.AnyActionDocumentListener; import lombok.AllArgsConstructor; @SuppressWarnings("serial") public class AutoGrowPanel extends JPanel { public static interface DocumentListenable { void addDocumentListener(DocumentListener dl); void removeDocumentListener(DocumentListener dl); default void setListPosition(int zeroIndex) {} } @AllArgsConstructor private class DeleteOnEmpty implements AnyActionDocumentListener { DocumentListenable content; @Override public void update(DocumentEvent e) { if (e.getDocument().getLength() == 0) { content.removeDocumentListener(this); int index = members.indexOf(content); members.remove(index); for (final int size = members.size(); index < size; ++index) { members.get(index).setListPosition(index); } remove((Component) content); getParent().getParent().validate(); } } } IntFunction prod; AnyActionDocumentListener grow; List members = new ArrayList<>(); /** * @wbp.parser.constructor */ public AutoGrowPanel(Supplier prod) { this(i -> prod.get(), 1); } public AutoGrowPanel(IntFunction prod, int create) { this.prod = prod; this.grow = new AnyActionDocumentListener() { @Override public void update(DocumentEvent e) { getBack().removeDocumentListener(this); getBack().addDocumentListener(new DeleteOnEmpty(getBack())); extend(); getParent().getParent().validate(); } }; setLayout(new VerticalLayout(5)); while (create-- > 0) { extend(); } } public AutoGrowPanel(Function function, List ingredients) { this(i -> function.apply(ingredients.get(i)), ingredients.size()); } private void extend() { members.add(prod.apply(members.size())); add((Component) getBack()); getBack().addDocumentListener(grow); } private DocumentListenable getBack() { return members.get(members.size() - 1); } }