Ver Fonte

Merge branch 'feat/more-observed'

* feat/more-observed:
  Remove unneeded subscription where we're displaying an aggregate object anyway
  Fix a handful of update bugs with observers.
  Support updates to durations and summary panels
Sam Jaffe há 5 anos atrás
pai
commit
b19a0ea5c5

+ 1 - 1
pom.xml

@@ -75,7 +75,7 @@
     <dependency>
       <groupId>org.leumasjaffe</groupId>
       <artifactId>observer</artifactId>
-      <version>0.5.0</version>
+      <version>0.5.1</version>
     </dependency>
     <dependency>
       <groupId>org.leumasjaffe</groupId>

+ 2 - 2
src/main/lombok/org/leumasjaffe/recipe/model/CompoundRecipeComponent.java

@@ -1,8 +1,8 @@
 package org.leumasjaffe.recipe.model;
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Map;
+import java.util.TreeMap;
 import java.util.stream.Stream;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@@ -23,7 +23,7 @@ interface CompoundRecipeComponent extends RecipeComponent {
 	
 	@Override
 	default Collection<Ingredient> getIngredients() {
-		final Map<String, Ingredient> map = new HashMap<>();
+		final Map<String, Ingredient> map = new TreeMap<>();
 		getIngredientsAsStream().forEach(value -> {
         	final String key = value.key();
             map.computeIfPresent(key, (k, v) -> value.plus(v));

+ 5 - 2
src/main/lombok/org/leumasjaffe/recipe/model/RecipeCard.java

@@ -7,10 +7,13 @@ import java.util.stream.Stream;
 
 import javax.swing.ImageIcon;
 
+import org.leumasjaffe.observer.Observable;
+
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
-@Data
-public class RecipeCard implements CompoundRecipeComponent {
+@Data @EqualsAndHashCode(callSuper=false)
+public class RecipeCard extends Observable.Instance implements CompoundRecipeComponent {
 	String title;
 	String description;
 	int servings;

+ 13 - 3
src/main/lombok/org/leumasjaffe/recipe/view/AutoGrowPanel.java

@@ -38,9 +38,9 @@ public class AutoGrowPanel extends JPanel {
 					members.get(index).setListPosition(index);
 				}
 				remove((Component) content);
-				getParent().getParent().validate();
+				validateNthParent(4);
 			}
-		}
+		}		
 	}
 	
 	@AllArgsConstructor
@@ -64,7 +64,7 @@ public class AutoGrowPanel extends JPanel {
 			members.add(object);
 			add(object);
 
-			getParent().getParent().validate();
+			validateNthParent(4);
 		}
 		
 	}
@@ -100,4 +100,14 @@ public class AutoGrowPanel extends JPanel {
 		return members.get(members.size() - 1);
 	}
 	
+	private void validateNthParent(int i) {
+		Component current = getParent();
+		Component next = current;
+		while (i --> 0 && next != null) {
+			current = next;
+			next = current.getParent();
+		}
+		current.validate();
+	}
+	
 }

+ 20 - 5
src/main/lombok/org/leumasjaffe/recipe/view/CollatedDurationPanel.java

@@ -6,23 +6,38 @@ import javax.swing.SwingConstants;
 
 import org.jdesktop.swingx.HorizontalLayout;
 import org.leumasjaffe.recipe.model.CollatedDuration;
+import org.leumasjaffe.recipe.model.Duration;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
 
 @SuppressWarnings("serial")
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class CollatedDurationPanel extends JPanel {
+	DurationPanel panelPrepTime;
+	DurationPanel panelCookingTime;
+	DurationPanel panelTotalTime;
 	
-	public CollatedDurationPanel(CollatedDuration duration) {
+	public CollatedDurationPanel(final CollatedDuration duration) {
 		setLayout(new HorizontalLayout(5));
 		
-		DurationPanel panelPrepTime = new DurationPanel("Prep", duration.getPrepTime().round(5));
+		panelPrepTime = new DurationPanel("Prep", Duration.ZERO);
 		add(panelPrepTime);
 		add(new JSeparator(SwingConstants.VERTICAL));
 		
-		DurationPanel panelCookingTime = new DurationPanel("Cooking", duration.getCookingTime().round(5));
+		panelCookingTime = new DurationPanel("Cooking", Duration.ZERO);
 		add(panelCookingTime);
 		add(new JSeparator(SwingConstants.VERTICAL));
 		
-		DurationPanel panelTotalTime = new DurationPanel("Total", duration.getTotalTime().round(5));
+		panelTotalTime = new DurationPanel("Total", Duration.ZERO);
 		add(panelTotalTime);
+		
+		setModel(duration);
+	}
+	
+	public void setModel(final CollatedDuration duration) {
+		panelPrepTime.setModel(duration.getPrepTime().round(5));
+		panelCookingTime.setModel(duration.getCookingTime().round(5));
+		panelTotalTime.setModel(duration.getTotalTime().round(5));
 	}
-
 }

+ 18 - 11
src/main/lombok/org/leumasjaffe/recipe/view/DurationPanel.java

@@ -11,6 +11,7 @@ import org.leumasjaffe.recipe.model.Duration;
 
 @SuppressWarnings("serial")
 public class DurationPanel extends JPanel {
+	private JLabel lblTime;
 	public DurationPanel(String name, Duration duration) {
 		GridBagLayout gridBagLayout = new GridBagLayout();
 		gridBagLayout.columnWidths = new int[]{0, 0, 0};
@@ -19,17 +20,23 @@ public class DurationPanel extends JPanel {
 		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
 		setLayout(gridBagLayout);
 		
-		JLabel lblPrep = new JLabel(name + ": ");
-		GridBagConstraints gbc_lblPrep = new GridBagConstraints();
-		gbc_lblPrep.insets = new Insets(0, 0, 0, 5);
-		gbc_lblPrep.gridx = 0;
-		gbc_lblPrep.gridy = 0;
-		add(lblPrep, gbc_lblPrep);
+		JLabel lblName = new JLabel(name + ": ");
+		GridBagConstraints gbc_lblName = new GridBagConstraints();
+		gbc_lblName.insets = new Insets(0, 0, 0, 5);
+		gbc_lblName.gridx = 0;
+		gbc_lblName.gridy = 0;
+		add(lblName, gbc_lblName);
 		
-		JLabel lblPrepTime = new JLabel(duration.toString());
-		GridBagConstraints gbc_lblPrepTime = new GridBagConstraints();
-		gbc_lblPrepTime.gridx = 1;
-		gbc_lblPrepTime.gridy = 0;
-		add(lblPrepTime, gbc_lblPrepTime);
+		lblTime = new JLabel();
+		GridBagConstraints gbc_lblTime = new GridBagConstraints();
+		gbc_lblTime.gridx = 1;
+		gbc_lblTime.gridy = 0;
+		add(lblTime, gbc_lblTime);
+		
+		setModel(duration);
+	}
+
+	public void setModel(final Duration duration) {
+		lblTime.setText(duration.toString());
 	}
 }

+ 12 - 0
src/main/lombok/org/leumasjaffe/recipe/view/RecipeCardPanel.java

@@ -3,6 +3,9 @@ package org.leumasjaffe.recipe.view;
 import javax.swing.JSplitPane;
 
 import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.observer.ForwardingObservableListener;
+import org.leumasjaffe.observer.ObservableListener;
+import org.leumasjaffe.recipe.model.Element;
 import org.leumasjaffe.recipe.model.RecipeCard;
 import org.leumasjaffe.recipe.view.summary.SummaryPanel;
 
@@ -14,13 +17,22 @@ import javax.swing.JPanel;
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE)
 public class RecipeCardPanel extends JSplitPane {
+	ObservableListener<RecipeCardPanel, RecipeCard> updateUI;
+	ForwardingObservableListener<RecipeCard> listener;
 	
 	public RecipeCardPanel(final RecipeCard card) {
 		final JPanel rightPanel = new JPanel();
 		rightPanel.setLayout(new VerticalLayout(5));
 		setRightComponent(rightPanel);
 		setLeftComponent(new SummaryPanel(card));
+		
 		card.getComponents().map(ElementPanel::new).forEach(rightPanel::add);
+		
+		listener = new ForwardingObservableListener<>();
+		listener.setObserved(card, card.getElements().toArray(new Element[0]));
+		
+		updateUI = new ObservableListener<>(this, (c, t) -> validate());
+		updateUI.setObserved(card);
 	}
 
 }

+ 8 - 3
src/main/lombok/org/leumasjaffe/recipe/view/StepPanel.java

@@ -78,8 +78,13 @@ public class StepPanel extends JPanel implements AutoGrowPanel.DocumentListenabl
 		
 		final List<Ingredient> ingredients = step.getIngredients();
 		panelIngredients = new AutoGrowPanel(IngredientPanel::new,
-				Ingredient::new, ingredients::add, i -> {
-					ingredients.remove((int) i);
+				Ingredient::new, ing -> {
+					ingredients.add(ing);
+					listener.setObserved(step, ingredients);
+					ObserverDispatch.notifySubscribers(step);
+				}, i -> {
+					ingredients.remove(i);
+					listener.setObserved(step, ingredients);
 					ObserverDispatch.notifySubscribers(step);
 				}, ingredients.toArray(new Ingredient[0]));
 		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
@@ -100,7 +105,7 @@ public class StepPanel extends JPanel implements AutoGrowPanel.DocumentListenabl
 		add(txtpnInstructions, gbc_txtpnInstructions);
 		
 		setListPosition(zeroIndex);
-		listener.setObserved(step, step.getIngredients());
+		listener.setObserved(step, ingredients);
 	}
 
 	@Override

+ 0 - 15
src/main/lombok/org/leumasjaffe/recipe/view/summary/IngredientPanel.java

@@ -10,8 +10,6 @@ import java.util.Locale;
 
 import javax.swing.text.NumberFormatter;
 
-import org.leumasjaffe.observer.ObservableListener;
-import org.leumasjaffe.observer.ObserverDispatch;
 import org.leumasjaffe.recipe.model.Ingredient;
 
 import lombok.AccessLevel;
@@ -25,7 +23,6 @@ import javax.swing.JLabel;
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class IngredientPanel extends JPanel {
-	ObservableListener<IngredientPanel, Ingredient> listener;
 	@Getter(AccessLevel.PACKAGE) JTextField txtName;
 	@Getter(AccessLevel.PACKAGE) JFormattedTextField txtAmount;
 	@Getter(AccessLevel.PACKAGE) JTextField txtUnit;
@@ -82,18 +79,6 @@ public class IngredientPanel extends JPanel {
 		gbc_txtUnit.gridy = 0;
 		add(txtUnit, gbc_txtUnit);
 		txtUnit.setColumns(6);
-		
-		listener = new ObservableListener<>(this, (c, t) -> {
-			if (txtName.getText().equals(t.getName())) return;
-			txtName.setText(t.getName());
-		});
-		listener.setObserved(ingredient);
-	}
-	
-	@Override
-	public void removeNotify() {
-		super.removeNotify();
-		ObserverDispatch.unsubscribeAll(listener);
 	}
 
 }

+ 24 - 7
src/main/lombok/org/leumasjaffe/recipe/view/summary/SummaryPanel.java

@@ -10,6 +10,8 @@ import javax.swing.JTextArea;
 import javax.swing.JTextField;
 
 import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.observer.ObservableListener;
+import org.leumasjaffe.recipe.model.CollatedDuration;
 import org.leumasjaffe.recipe.model.Element;
 import org.leumasjaffe.recipe.model.RecipeCard;
 import org.leumasjaffe.recipe.view.CollatedDurationPanel;
@@ -22,6 +24,8 @@ import java.awt.Font;
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class SummaryPanel extends JPanel {
+	ObservableListener<CollatedDurationPanel, RecipeCard> durationListener;
+	ObservableListener<JPanel, RecipeCard> childListener;
 	
 	public SummaryPanel(final RecipeCard card) {
 		GridBagLayout gridBagLayout = new GridBagLayout();
@@ -56,13 +60,12 @@ public class SummaryPanel extends JPanel {
 		panelHeader.add(txtTitle, gbc_txtTitle);
 		txtTitle.setColumns(10);
 		
-		CollatedDurationPanel panelDuration =
-				new CollatedDurationPanel(card.getCollatedDuration());
+		CollatedDurationPanel panelDuration = new CollatedDurationPanel(CollatedDuration.ZERO);
 		GridBagConstraints gbc_panelDuration = new GridBagConstraints();
 		gbc_panelDuration.gridx = 0;
 		gbc_panelDuration.gridy = 1;
-		panelHeader.add(panelDuration, gbc_panelDuration);
 		
+		panelHeader.add(panelDuration, gbc_panelDuration);
 		JPanel panelIngredients = new JPanel();
 		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
 		gbc_panelIngredients.insets = new Insets(0, 0, 5, 5);
@@ -105,10 +108,24 @@ public class SummaryPanel extends JPanel {
 		gbc_txaDesription.gridy = 1;
 		panel.add(txaDesription, gbc_txaDesription);
 		
-		for (final Element element : card.getElements()) {
-			panelIngredients.add(new ElementPanel(element));
-			panelIngredients.add(new JSeparator());
-		}
+		durationListener = new ObservableListener<>(panelDuration,
+				(c, v) -> c.setModel(v.getCollatedDuration()));
+		
+		childListener = new ObservableListener<>(panelIngredients, (c, v) -> {
+			if (c.getComponents().length == v.getElements().size()) {
+				return;
+			}
+			c.removeAll();
+			for (final Element element : v.getElements()) {
+				JPanel wrapper = new JPanel(new VerticalLayout());
+				wrapper.add(new ElementPanel(element));
+				wrapper.add(new JSeparator());
+				c.add(wrapper);
+			}
+		});
+		
+		durationListener.setObserved(card);
+		childListener.setObserved(card);
 	}
 	
 }

+ 2 - 3
src/test/java/org/leumasjaffe/recipe/view/summary/IngredientPanelTest.java

@@ -35,12 +35,11 @@ class IngredientPanelTest extends SwingTestCase {
 	}
 
 	@Test
-	void testIsSubscribedToUpdates() {
+	void testIsNotSubscribedToUpdates() {
 		stuff.setName("Bacon");
 		assertEquals("Onions", panel.getTxtName().getText());
 		ObserverDispatch.notifySubscribers(stuff);
-		assertEquals("Bacon", panel.getTxtName().getText());
-		// TODO: I need to add hook-ups for the rest of the fields, too
+		assertNotEquals("Bacon", panel.getTxtName().getText());
 	}
 
 }