package org.leumasjaffe.recipe.view; import javax.swing.JPanel; import javax.swing.event.DocumentListener; import org.leumasjaffe.observer.ForwardingObservableListener; import org.leumasjaffe.observer.ObservableController; import org.leumasjaffe.observer.ObservableListener; import org.leumasjaffe.observer.ObserverDispatch; import org.leumasjaffe.recipe.controller.TextBinding; import org.leumasjaffe.recipe.model.Ingredient; import org.leumasjaffe.recipe.model.Step; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.FieldDefaults; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.event.FocusListener; import javax.swing.JLabel; import javax.swing.JTextPane; import java.awt.Component; import javax.swing.Box; import javax.swing.JFormattedTextField; import java.awt.Dimension; @SuppressWarnings("serial") @FieldDefaults(level=AccessLevel.PRIVATE) public class StepPanel extends JPanel implements AutoGrowPanel.ChildComponent { ForwardingObservableListener listener = new ForwardingObservableListener<>(); TextBinding instructionBinding; ObservableListener durationController; JLabel lblIndex; @Getter(AccessLevel.PACKAGE) JTextPane txtpnInstructions; AutoGrowPanel panelIngredients; public StepPanel() { GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[]{0, 0, 0}; gridBagLayout.rowHeights = new int[]{0, 0}; gridBagLayout.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE}; gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE}; setLayout(gridBagLayout); JPanel panelLeft = new JPanel(); GridBagConstraints gbc_panelLeft = new GridBagConstraints(); gbc_panelLeft.insets = new Insets(0, 0, 0, 5); gbc_panelLeft.fill = GridBagConstraints.BOTH; gbc_panelLeft.gridx = 0; gbc_panelLeft.gridy = 0; add(panelLeft, gbc_panelLeft); GridBagLayout gbl_panelLeft = new GridBagLayout(); gbl_panelLeft.columnWidths = new int[]{0, 0, 0, 0}; gbl_panelLeft.rowHeights = new int[]{0, 0, 0}; gbl_panelLeft.columnWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE}; gbl_panelLeft.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE}; panelLeft.setLayout(gbl_panelLeft); lblIndex = new JLabel(""); GridBagConstraints gbc_lblIndex = new GridBagConstraints(); gbc_lblIndex.fill = GridBagConstraints.HORIZONTAL; gbc_lblIndex.insets = new Insets(0, 0, 0, 5); gbc_lblIndex.gridx = 0; gbc_lblIndex.gridy = 0; panelLeft.add(lblIndex, gbc_lblIndex); Component horizontalGlue = Box.createHorizontalGlue(); GridBagConstraints gbc_horizontalGlue = new GridBagConstraints(); gbc_horizontalGlue.insets = new Insets(0, 0, 0, 5); gbc_horizontalGlue.gridx = 1; gbc_horizontalGlue.gridy = 0; panelLeft.add(horizontalGlue, gbc_horizontalGlue); DurationPanel panelDuration = new DurationPanel("Requires"); GridBagConstraints gbc_panelDuration = new GridBagConstraints(); gbc_panelDuration.gridx = 2; gbc_panelDuration.gridy = 0; panelLeft.add(panelDuration, gbc_panelDuration); panelIngredients = new AutoGrowPanel<>(Ingredient::new, IngredientPanel::new); GridBagConstraints gbc_panelIngredients = new GridBagConstraints(); gbc_panelIngredients.gridwidth = 3; gbc_panelIngredients.insets = new Insets(0, 0, 0, 5); gbc_panelIngredients.fill = GridBagConstraints.BOTH; gbc_panelIngredients.gridx = 0; gbc_panelIngredients.gridy = 1; panelLeft.add(panelIngredients, gbc_panelIngredients); txtpnInstructions = new JTextPane(); txtpnInstructions.setPreferredSize(new Dimension(200, 30)); GridBagConstraints gbc_txtpnInstructions = new GridBagConstraints(); gbc_txtpnInstructions.fill = GridBagConstraints.BOTH; gbc_txtpnInstructions.gridx = 1; gbc_txtpnInstructions.gridy = 0; add(txtpnInstructions, gbc_txtpnInstructions); instructionBinding = new TextBinding<>(txtpnInstructions, Step::getInstruction, Step::setInstruction); durationController = ObservableController.from(panelDuration.txtTime, Step::getDuration, Step::setDuration); setListPosition(0); } public StepPanel(final Step step) { this(); setModel(step); } void setModel(final Step step) { panelIngredients.setModel(step.getIngredients(), added -> { listener.setObserved(step, step.getIngredients()); if (!added) { ObserverDispatch.notifySubscribers(step); } }); listener.setObserved(step, step.getIngredients()); instructionBinding.setModel(step); durationController.setObserved(step); } @Override public void removeNotify() { super.removeNotify(); ObserverDispatch.unsubscribeAll(listener); ObserverDispatch.unsubscribeAll(instructionBinding); ObserverDispatch.unsubscribeAll(durationController); } @Override public void setListPosition(int zeroIndex) { this.lblIndex.setText("Step " + Integer.toString(zeroIndex + 1)); repaint(); } @Override public void addGrowListener(DocumentListener dl) { this.txtpnInstructions.getDocument().addDocumentListener(dl); } @Override public void removeGrowListener(DocumentListener dl) { this.txtpnInstructions.getDocument().removeDocumentListener(dl); } @Override public void addShrinkListener(FocusListener fl) { this.txtpnInstructions.addFocusListener(fl); } @Override public void removeShrinkListener(FocusListener fl) { this.txtpnInstructions.removeFocusListener(fl); } }