| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package org.leumasjaffe.recipe.view;
- import java.awt.Component;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.function.Consumer;
- 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;
- import lombok.RequiredArgsConstructor;
- @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();
- }
- }
- }
-
- private class GrowAction implements AnyActionDocumentListener {
- @Override
- public void update(DocumentEvent e) {
- final DocumentListenable back = getBack();
- back.removeDocumentListener(this);
- back.addDocumentListener(new DeleteOnEmpty(back));
- extend();
- getBack().addDocumentListener(this);
- getParent().getParent().validate();
- }
- }
-
- @RequiredArgsConstructor
- private class ExtendAction<T, C extends Component & DocumentListenable> implements AnyActionDocumentListener {
- final Function<T, C> factory;
- final Consumer<? super T> previous;
- final Supplier<? extends T> next;
- T current = null;
- @Override
- public void update(DocumentEvent e) {
- if (current != null) {
- previous.accept(current);
- }
-
- final C object = factory.apply(current = next.get());
- final DocumentListenable back = getBack();
-
- back.removeDocumentListener(this);
- back.addDocumentListener(new DeleteOnEmpty(back));
- object.addDocumentListener(this);
-
- members.add(object);
- add(object);
- getParent().getParent().validate();
- }
-
- }
-
- IntFunction<DocumentListenable> prod;
- AnyActionDocumentListener grow;
- List<DocumentListenable> members = new ArrayList<>();
-
- /**
- * @wbp.parser.constructor
- */
- public AutoGrowPanel(Supplier<DocumentListenable> prod) {
- this(i -> prod.get(), 1);
- }
-
- public AutoGrowPanel(IntFunction<DocumentListenable> prod, int create) {
- this.prod = prod;
- this.grow = new GrowAction();
- setLayout(new VerticalLayout(5));
- if (create == 0) return; // TODO
- while (create-- > 1) {
- extend();
- getBack().addDocumentListener(new DeleteOnEmpty(getBack()));
- }
- extend();
- getBack().addDocumentListener(grow);
- }
- public <T> AutoGrowPanel(Function<T, DocumentListenable> function, List<T> list) {
- this(i -> list.size() > i ? function.apply(list.get(i)) : null, list.size());
- }
-
- @SafeVarargs
- public <T, C extends Component & DocumentListenable> AutoGrowPanel(Function<T, C> function,
- Supplier<T> newItem, Consumer<? super T> onData, Consumer<Integer> onDelete, T...ts) {
- setLayout(new VerticalLayout(5));
-
- this.grow = new ExtendAction<T, C>(function, onData, newItem);
-
- for (T value : ts) {
- C listen = function.apply(value);
- members.add(listen);
- add(listen);
- listen.addDocumentListener(new DeleteOnEmpty(listen));
- }
-
- T next = newItem.get();
- C empty = function.apply(next);
- members.add(empty);
- add(empty);
- empty.addDocumentListener(this.grow);
- }
- private void extend() {
- DocumentListenable value = prod.apply(members.size());
- if (value != null) {
- members.add(value);
- add((Component) getBack());
- }
- }
- private DocumentListenable getBack() {
- return members.get(members.size() - 1);
- }
-
- }
|