Jelajahi Sumber

Add servings to SummaryPanel, use a binding mechanism that doesn't trigger ObserverDispatch unnecessarily.

Sam Jaffe 5 tahun lalu
induk
melakukan
214c58c468

+ 39 - 0
src/main/lombok/org/leumasjaffe/recipe/controller/SpinnerBinding.java

@@ -0,0 +1,39 @@
+package org.leumasjaffe.recipe.controller;
+
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+import javax.swing.JSpinner;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import lombok.experimental.NonFinal;
+
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class SpinnerBinding<T, O> implements ChangeListener {
+	JSpinner component;
+	Function<T, O> get;
+	BiConsumer<T, O> set;
+	@NonFinal T model;
+	
+	public SpinnerBinding(JSpinner component, Function<T, O> get, BiConsumer<T, O> set) {
+		this.component = component;
+		this.get = get;
+		this.set = set;
+		component.addChangeListener(this);
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public void stateChanged(ChangeEvent e) {
+		set.accept(this.model, (O) component.getValue());
+	}
+	
+	public void setModel(T model) {
+		this.model = model;
+		component.setValue(get.apply(model));
+	}
+
+}

+ 39 - 0
src/main/lombok/org/leumasjaffe/recipe/controller/TextBinding.java

@@ -0,0 +1,39 @@
+package org.leumasjaffe.recipe.controller;
+
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.JTextComponent;
+
+import org.leumasjaffe.event.AnyActionDocumentListener;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import lombok.experimental.NonFinal;
+
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class TextBinding<T> implements AnyActionDocumentListener {
+	JTextComponent component;
+	Function<T, String> get;
+	BiConsumer<T, String> set;
+	@NonFinal T model;
+	
+	public TextBinding(JTextComponent component, Function<T, String> get, BiConsumer<T, String> set) {
+		this.component = component;
+		this.get = get;
+		this.set = set;
+		component.getDocument().addDocumentListener(this);
+	}
+	
+	@Override
+	public void update(DocumentEvent e) {
+		set.accept(this.model, component.getText());
+	}
+	
+	public void setModel(T model) {
+		this.model = model;
+		component.setText(get.apply(model));
+	}
+
+}

+ 49 - 10
src/main/lombok/org/leumasjaffe/recipe/view/summary/SummaryPanel.java

@@ -8,12 +8,14 @@ import javax.swing.JPanel;
 import javax.swing.JSeparator;
 import javax.swing.JTextArea;
 import javax.swing.JTextField;
+import javax.swing.SpinnerNumberModel;
 
 import org.jdesktop.swingx.VerticalLayout;
-import org.leumasjaffe.observer.ObservableController;
 import org.leumasjaffe.observer.ObservableListener;
 import org.leumasjaffe.observer.ObserverDispatch;
 import org.leumasjaffe.recipe.controller.ReplaceChildrenController;
+import org.leumasjaffe.recipe.controller.SpinnerBinding;
+import org.leumasjaffe.recipe.controller.TextBinding;
 import org.leumasjaffe.recipe.model.Element;
 import org.leumasjaffe.recipe.model.RecipeCard;
 import org.leumasjaffe.recipe.view.CollatedDurationPanel;
@@ -21,13 +23,16 @@ import org.leumasjaffe.recipe.view.ImagePanel;
 
 import lombok.AccessLevel;
 import lombok.experimental.FieldDefaults;
+import javax.swing.JLabel;
+import javax.swing.JSpinner;
 
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE)
 public class SummaryPanel extends JPanel {
 	ReplaceChildrenController<RecipeCard, Element> controller;
-	ObservableListener<JTextField, RecipeCard> titleListener;
-	ObservableListener<JTextArea, RecipeCard> descriptionListener;
+	TextBinding<RecipeCard> titleBinding;
+	SpinnerBinding<RecipeCard, Integer> servingsBinding;
+	TextBinding<RecipeCard> descriptionBinding;
 	ObservableListener<CollatedDurationPanel, RecipeCard> durationListener;
 	ObservableListener<JPanel, RecipeCard> childListener;
 	
@@ -44,9 +49,9 @@ public class SummaryPanel extends JPanel {
 		
 		GridBagLayout gridBagLayout = new GridBagLayout();
 		gridBagLayout.columnWidths = new int[]{0, 0, 0};
-		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0};
 		gridBagLayout.columnWeights = new double[]{1.0, 0.0, Double.MIN_VALUE};
-		gridBagLayout.rowWeights = new double[]{0.0, 1.0, 1.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, 1.0, 1.0, 1.0, Double.MIN_VALUE};
 		setLayout(gridBagLayout);
 		
 		JPanel panelHeader = new JPanel();
@@ -79,17 +84,47 @@ public class SummaryPanel extends JPanel {
 		gbc_panelDuration.gridy = 1;
 		
 		panelHeader.add(panelDuration, gbc_panelDuration);
+		
+		JPanel panelServings = new JPanel();
+		GridBagConstraints gbc_panelServings = new GridBagConstraints();
+		gbc_panelServings.insets = new Insets(0, 0, 5, 5);
+		gbc_panelServings.fill = GridBagConstraints.BOTH;
+		gbc_panelServings.gridx = 0;
+		gbc_panelServings.gridy = 1;
+		add(panelServings, gbc_panelServings);
+		GridBagLayout gbl_panelServings = new GridBagLayout();
+		gbl_panelServings.columnWidths = new int[]{0, 0, 0};
+		gbl_panelServings.rowHeights = new int[]{0, 0};
+		gbl_panelServings.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
+		gbl_panelServings.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		panelServings.setLayout(gbl_panelServings);
+		
+		JLabel lblServes = new JLabel("Serves");
+		GridBagConstraints gbc_lblServes = new GridBagConstraints();
+		gbc_lblServes.insets = new Insets(0, 0, 5, 0);
+		gbc_lblServes.gridx = 0;
+		gbc_lblServes.gridy = 0;
+		panelServings.add(lblServes, gbc_lblServes);
+		
+		JSpinner spnServings = new JSpinner(new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1));
+		GridBagConstraints gbc_spnServings = new GridBagConstraints();
+		gbc_spnServings.fill = GridBagConstraints.HORIZONTAL;
+		gbc_spnServings.gridx = 1;
+		gbc_spnServings.gridy = 0;
+		panelServings.add(spnServings, gbc_spnServings);
+		
 		JPanel panelIngredients = new JPanel();
 		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
 		gbc_panelIngredients.insets = new Insets(0, 0, 5, 5);
 		gbc_panelIngredients.fill = GridBagConstraints.BOTH;
 		gbc_panelIngredients.gridx = 0;
-		gbc_panelIngredients.gridy = 1;
+		gbc_panelIngredients.gridy = 2;
 		add(panelIngredients, gbc_panelIngredients);
 		panelIngredients.setLayout(new VerticalLayout());
 		
 		JPanel panel = new JPanel();
 		GridBagConstraints gbc_panel = new GridBagConstraints();
+		gbc_panel.gridheight = 2;
 		gbc_panel.insets = new Insets(0, 0, 5, 0);
 		gbc_panel.fill = GridBagConstraints.BOTH;
 		gbc_panel.gridx = 1;
@@ -120,10 +155,13 @@ public class SummaryPanel extends JPanel {
 		gbc_txaDescription.gridy = 1;
 		panel.add(txaDescription, gbc_txaDescription);
 		
-		titleListener = ObservableController.from(txtTitle,
+		titleBinding = new TextBinding<>(txtTitle,
 				RecipeCard::getTitle, RecipeCard::setTitle);
+		
+		servingsBinding = new SpinnerBinding<>(spnServings, 
+				RecipeCard::getServings, RecipeCard::setServings);
 
-		descriptionListener = ObservableController.from(txaDescription,
+		descriptionBinding = new TextBinding<>(txaDescription,
 				RecipeCard::getDescription, RecipeCard::setDescription);
 
 		durationListener = new ObservableListener<>(panelDuration,
@@ -140,8 +178,9 @@ public class SummaryPanel extends JPanel {
 	}
 	
 	public void setModel(final RecipeCard card) {
-		titleListener.setObserved(card);
-		descriptionListener.setObserved(card);
+		titleBinding.setModel(card);
+		servingsBinding.setModel(card);
+		descriptionBinding.setModel(card);
 		durationListener.setObserved(card);
 		childListener.setObserved(card);
 	}