Parcourir la source

Merge branch 'feat/view/fillFromModel'

* feat/view/fillFromModel:
  Add summary of Product ingredients, fix display by removing preferredSize settings.
  Fix amount parsing for COUNT.
  Properly visualize rests.
  Don't track coverage for lombok generated methods.
  Add preparation and instructions into the view.
  Update Jackson to the latest stable version.
  Fix NPE in amount unit switch.
  Add ingredient data into the IngredientPanel.
Sam Jaffe il y a 5 ans
Parent
commit
d32cc4e2eb

+ 1 - 0
lombok.config

@@ -0,0 +1 @@
+lombok.addLombokGeneratedAnnotation = true

+ 2 - 2
pom.xml

@@ -68,13 +68,13 @@
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
-      <version>1.16.8</version>
+      <version>1.18.16</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
-      <version>2.7.3</version>
+      <version>2.12.0</version>
     </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.datatype</groupId>

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

@@ -47,16 +47,22 @@ public class Amount {
 	@JsonCreator
 	public Amount(final String serial) {
 		final String[] tokens = serial.split(" ", 2);
+		unit = Unit.COUNT;
 		value = Double.parseDouble(tokens[0]);
+		if (tokens.length == 1) {
+			return;
+		}
 		final Optional<Volume> rv = Stream.of(Volume.values())
 				.filter(v -> v.displayName.equals(tokens[1])).findFirst();
 		if (rv.isPresent()) {
+			unit = Unit.VOLUME;
 			vol = rv.get();
 			return;
 		}
 		final Optional<Weight> rw = Stream.of(Weight.values())
 				.filter(w -> w.displayName.equals(tokens[1])).findFirst();
 		if (rw.isPresent()) {
+			unit = Unit.WEIGHT;
 			wgt = rw.get();
 			return;
 		}
@@ -73,14 +79,14 @@ public class Amount {
 		return build.toString();
 	}
 	
-	private String unitName() {
+	public String unitName() {
 		switch (unit) {
 		case WEIGHT:
 			return wgt.displayName;
 		case VOLUME:
 			return vol.displayName;
 		default:
-			return "";
+			return "ct";
 		}
 	}
 

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

@@ -2,11 +2,12 @@ package org.leumasjaffe.recipe.model;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
-@Data @AllArgsConstructor
+@Data @AllArgsConstructor @NoArgsConstructor
 public class Ingredient {
 	String name;
-	String preparation;
+	String preparation = "";
 	Amount amount;
 	
 	Ingredient plus(final Ingredient rhs) {

+ 3 - 3
src/main/lombok/org/leumasjaffe/recipe/model/Preparation.java

@@ -1,12 +1,12 @@
 package org.leumasjaffe.recipe.model;
 
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
 
 import lombok.Data;
 
 @Data
 public class Preparation implements RecipeComponent {
-	Set<Ingredient> ingredients = new HashSet<>();
+	List<Ingredient> ingredients = new ArrayList<>();
 	Duration duration;
 }

+ 9 - 1
src/main/lombok/org/leumasjaffe/recipe/model/Rest.java

@@ -1,11 +1,19 @@
 package org.leumasjaffe.recipe.model;
 
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.Getter;
+import lombok.experimental.FieldDefaults;
 
 @Data
 public class Rest {
+	@AllArgsConstructor @Getter @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 	public enum Where {
-		FREEZER, REFRIGERATOR, ROOM_TEMPERATURE, WARM_PLACE
+		FREEZER("in the freezer"), REFRIGERATOR("in the refrigerator"),
+		ROOM_TEMPERATURE("at room temperature"), WARM_PLACE("in a warm place");
+		
+		String humanReadable;
 	}
 	
 	Where where;

+ 3 - 3
src/main/lombok/org/leumasjaffe/recipe/model/Step.java

@@ -1,13 +1,13 @@
 package org.leumasjaffe.recipe.model;
 
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
 
 import lombok.Data;
 
 @Data
 public class Step implements RecipeComponent {
-	Set<Ingredient> ingredients = new HashSet<>();
+	List<Ingredient> ingredients = new ArrayList<>();
 	Duration duration;
 	String instruction;
 }

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

@@ -3,6 +3,7 @@ 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;
 
@@ -48,10 +49,10 @@ public class AutoGrowPanel extends JPanel {
 	 * @wbp.parser.constructor
 	 */
 	public AutoGrowPanel(Supplier<DocumentListenable> prod) {
-		this(i -> prod.get());
+		this(i -> prod.get(), 1);
 	}
 	
-	public AutoGrowPanel(IntFunction<DocumentListenable> prod) {
+	public AutoGrowPanel(IntFunction<DocumentListenable> prod, int create) {
 		this.prod = prod;
 		
 		this.grow = new AnyActionDocumentListener() {
@@ -64,7 +65,14 @@ public class AutoGrowPanel extends JPanel {
 		};
 
 		setLayout(new VerticalLayout(5));
-		extend();
+		while (create-- > 0) {
+			extend();
+		}
+	}
+
+	public <T> AutoGrowPanel(Function<T, DocumentListenable> function, List<T> ingredients) {
+		this(i -> function.apply(ingredients.get(i)), ingredients.size());
+		
 	}
 
 	private void extend() {

+ 21 - 6
src/main/lombok/org/leumasjaffe/recipe/view/IngredientPanel.java

@@ -11,6 +11,8 @@ import java.util.Locale;
 import javax.swing.event.DocumentListener;
 import javax.swing.text.NumberFormatter;
 
+import org.leumasjaffe.recipe.model.Ingredient;
+
 import javax.swing.JFormattedTextField;
 import java.awt.Font;
 import javax.swing.JLabel;
@@ -19,12 +21,13 @@ import javax.swing.JLabel;
 public class IngredientPanel extends JPanel implements AutoGrowPanel.DocumentListenable {
 	private JTextField txtName;
 	private JTextField txtUnit;
+	private JTextField txtPreparation;
 	
-	public IngredientPanel() {
+	public IngredientPanel(final Ingredient ingredient) {
 		GridBagLayout gridBagLayout = new GridBagLayout();
-		gridBagLayout.columnWidths = new int[]{0, 100, 40, 40, 0};
+		gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0};
 		gridBagLayout.rowHeights = new int[]{0, 0};
-		gridBagLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE};
+		gridBagLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
 		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
 		setLayout(gridBagLayout);
 		
@@ -36,7 +39,7 @@ public class IngredientPanel extends JPanel implements AutoGrowPanel.DocumentLis
 		gbc_label.gridy = 0;
 		add(label, gbc_label);
 		
-		txtName = new JTextField();
+		txtName = new JTextField(ingredient.getName());
 		txtName.setFont(new Font("Source Code Pro", Font.PLAIN, 10));
 		GridBagConstraints gbc_txtName = new GridBagConstraints();
 		gbc_txtName.fill = GridBagConstraints.HORIZONTAL;
@@ -50,6 +53,7 @@ public class IngredientPanel extends JPanel implements AutoGrowPanel.DocumentLis
 		fmtDone.setMinimum(0.0);
 		fmtDone.setCommitsOnValidEdit(true);
 		JFormattedTextField txtAmount = new JFormattedTextField(fmtDone);
+		txtAmount.setValue(ingredient.getAmount().getValue());
 		txtAmount.setFont(new Font("Source Code Pro", Font.PLAIN, 10));
 		GridBagConstraints gbc_txtAmount = new GridBagConstraints();
 		gbc_txtAmount.fill = GridBagConstraints.HORIZONTAL;
@@ -59,15 +63,26 @@ public class IngredientPanel extends JPanel implements AutoGrowPanel.DocumentLis
 		add(txtAmount, gbc_txtAmount);
 		txtAmount.setColumns(4);
 		
-		txtUnit = new JTextField();
+		txtUnit = new JTextField(ingredient.getAmount().unitName());
 		txtUnit.setFont(new Font("Source Code Pro", Font.PLAIN, 10));
 		GridBagConstraints gbc_txtUnit = new GridBagConstraints();
+		gbc_txtUnit.insets = new Insets(0, 0, 0, 5);
 		gbc_txtUnit.anchor = GridBagConstraints.ABOVE_BASELINE;
 		gbc_txtUnit.fill = GridBagConstraints.HORIZONTAL;
 		gbc_txtUnit.gridx = 3;
 		gbc_txtUnit.gridy = 0;
 		add(txtUnit, gbc_txtUnit);
-		txtUnit.setColumns(10);
+		txtUnit.setColumns(6);
+		
+		txtPreparation = new JTextField(ingredient.getPreparation());
+		txtPreparation.setFont(new Font("Source Code Pro", Font.PLAIN, 10));
+		GridBagConstraints gbc_txtPreparation = new GridBagConstraints();
+		gbc_txtPreparation.anchor = GridBagConstraints.ABOVE_BASELINE;
+		gbc_txtPreparation.fill = GridBagConstraints.HORIZONTAL;
+		gbc_txtPreparation.gridx = 4;
+		gbc_txtPreparation.gridy = 0;
+		add(txtPreparation, gbc_txtPreparation);
+		txtPreparation.setColumns(10);
 	}
 
 	@Override

+ 3 - 14
src/main/lombok/org/leumasjaffe/recipe/view/PreparationPanel.java

@@ -14,7 +14,6 @@ import javax.swing.JLabel;
 import javax.swing.JTextPane;
 import java.awt.Component;
 import javax.swing.Box;
-import java.awt.Dimension;
 
 @SuppressWarnings("serial")
 public class PreparationPanel extends JPanel implements AutoGrowPanel.DocumentListenable {
@@ -30,7 +29,6 @@ public class PreparationPanel extends JPanel implements AutoGrowPanel.DocumentLi
 		setLayout(gridBagLayout);
 		
 		JPanel panelLeft = new JPanel();
-		panelLeft.setPreferredSize(new Dimension(200, 50));
 		GridBagConstraints gbc_panelLeft = new GridBagConstraints();
 		gbc_panelLeft.insets = new Insets(0, 0, 0, 5);
 		gbc_panelLeft.fill = GridBagConstraints.BOTH;
@@ -44,7 +42,7 @@ public class PreparationPanel extends JPanel implements AutoGrowPanel.DocumentLi
 		gbl_panelLeft.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
 		panelLeft.setLayout(gbl_panelLeft);
 		
-		lblIndex = new JLabel("");
+		lblIndex = new JLabel("Prep");
 		GridBagConstraints gbc_lblIndex = new GridBagConstraints();
 		gbc_lblIndex.fill = GridBagConstraints.HORIZONTAL;
 		gbc_lblIndex.insets = new Insets(0, 0, 5, 5);
@@ -59,14 +57,14 @@ public class PreparationPanel extends JPanel implements AutoGrowPanel.DocumentLi
 		gbc_horizontalGlue.gridy = 0;
 		panelLeft.add(horizontalGlue, gbc_horizontalGlue);
 		
-		JLabel lblDuration = new JLabel("Duration");
+		JLabel lblDuration = new JLabel("Requires: " + step.getDuration().toString());
 		GridBagConstraints gbc_lblDuration = new GridBagConstraints();
 		gbc_lblDuration.insets = new Insets(0, 0, 5, 0);
 		gbc_lblDuration.gridx = 2;
 		gbc_lblDuration.gridy = 0;
 		panelLeft.add(lblDuration, gbc_lblDuration);
 		
-		AutoGrowPanel panelIngredients = new AutoGrowPanel(IngredientPanel::new);
+		AutoGrowPanel panelIngredients = new AutoGrowPanel(IngredientPanel::new, step.getIngredients());
 		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
 		gbc_panelIngredients.gridwidth = 3;
 		gbc_panelIngredients.insets = new Insets(0, 0, 0, 5);
@@ -74,15 +72,6 @@ public class PreparationPanel extends JPanel implements AutoGrowPanel.DocumentLi
 		gbc_panelIngredients.gridx = 0;
 		gbc_panelIngredients.gridy = 1;
 		panelLeft.add(panelIngredients, gbc_panelIngredients);
-		
-		txtpnInstructions = new JTextPane();
-		txtpnInstructions.setPreferredSize(new Dimension(200, 30));
-		txtpnInstructions.setText("Instructions");
-		GridBagConstraints gbc_txtpnInstructions = new GridBagConstraints();
-		gbc_txtpnInstructions.fill = GridBagConstraints.BOTH;
-		gbc_txtpnInstructions.gridx = 1;
-		gbc_txtpnInstructions.gridy = 0;
-		add(txtpnInstructions, gbc_txtpnInstructions);
 	}
 
 	@Override

+ 39 - 0
src/main/lombok/org/leumasjaffe/recipe/view/ProductSummaryPanel.java

@@ -0,0 +1,39 @@
+package org.leumasjaffe.recipe.view;
+
+import javax.swing.JPanel;
+
+import org.leumasjaffe.recipe.model.Product;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+
+import javax.swing.JLabel;
+import java.awt.GridBagConstraints;
+
+@SuppressWarnings("serial")
+public class ProductSummaryPanel extends JPanel {
+	public ProductSummaryPanel(final Product product) {
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0};
+		gridBagLayout.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JLabel lblProductName = new JLabel(product.getName());
+		GridBagConstraints gbc_lblProductName = new GridBagConstraints();
+		gbc_lblProductName.gridx = 0;
+		gbc_lblProductName.gridy = 0;
+		add(lblProductName, gbc_lblProductName);
+		
+		AutoGrowPanel panelIngredients = new AutoGrowPanel(IngredientPanel::new,
+				new ArrayList<>(product.getIngredients()));
+		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
+		gbc_panelIngredients.gridwidth = 2;
+		gbc_panelIngredients.insets = new Insets(0, 0, 0, 5);
+		gbc_panelIngredients.fill = GridBagConstraints.BOTH;
+		gbc_panelIngredients.gridx = 0;
+		gbc_panelIngredients.gridy = 1;
+		add(panelIngredients, gbc_panelIngredients);
+	}
+}

+ 1 - 0
src/main/lombok/org/leumasjaffe/recipe/view/RecipeFrame.java

@@ -28,6 +28,7 @@ public class RecipeFrame extends JFrame {
 		try {
 			Recipe recipe = mapper.readValue(new File("src/test/resources/example.json"), Recipe.class);
 			for (Product comp : recipe.getProducts()) {
+				summaryPanel.addProduct(comp);
 				tabbedPane.addTab(comp.getName(), new ProductPanel(comp));
 			}
 		} catch (IOException e) {

+ 1 - 1
src/main/lombok/org/leumasjaffe/recipe/view/RestPanel.java

@@ -26,7 +26,7 @@ public class RestPanel extends JPanel {
 		gbc_lblRest.gridy = 0;
 		add(lblRest, gbc_lblRest);
 		
-		JLabel lblLocation = new JLabel(rest.getWhere().toString());
+		JLabel lblLocation = new JLabel(rest.getWhere().getHumanReadable());
 		GridBagConstraints gbc_lblLocation = new GridBagConstraints();
 		gbc_lblLocation.insets = new Insets(0, 0, 0, 5);
 		gbc_lblLocation.gridx = 1;

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

@@ -30,7 +30,6 @@ public class StepPanel extends JPanel implements AutoGrowPanel.DocumentListenabl
 		setLayout(gridBagLayout);
 		
 		JPanel panelLeft = new JPanel();
-		panelLeft.setPreferredSize(new Dimension(200, 50));
 		GridBagConstraints gbc_panelLeft = new GridBagConstraints();
 		gbc_panelLeft.insets = new Insets(0, 0, 0, 5);
 		gbc_panelLeft.fill = GridBagConstraints.BOTH;
@@ -59,14 +58,14 @@ public class StepPanel extends JPanel implements AutoGrowPanel.DocumentListenabl
 		gbc_horizontalGlue.gridy = 0;
 		panelLeft.add(horizontalGlue, gbc_horizontalGlue);
 		
-		JLabel lblDuration = new JLabel("Duration");
+		JLabel lblDuration = new JLabel("Requires: " + step.getDuration().toString());
 		GridBagConstraints gbc_lblDuration = new GridBagConstraints();
 		gbc_lblDuration.insets = new Insets(0, 0, 5, 0);
 		gbc_lblDuration.gridx = 2;
 		gbc_lblDuration.gridy = 0;
 		panelLeft.add(lblDuration, gbc_lblDuration);
 		
-		AutoGrowPanel panelIngredients = new AutoGrowPanel(IngredientPanel::new);
+		AutoGrowPanel panelIngredients = new AutoGrowPanel(IngredientPanel::new, step.getIngredients());
 		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
 		gbc_panelIngredients.gridwidth = 3;
 		gbc_panelIngredients.insets = new Insets(0, 0, 0, 5);
@@ -77,7 +76,7 @@ public class StepPanel extends JPanel implements AutoGrowPanel.DocumentListenabl
 		
 		txtpnInstructions = new JTextPane();
 		txtpnInstructions.setPreferredSize(new Dimension(200, 30));
-		txtpnInstructions.setText("Instructions");
+		txtpnInstructions.setText(step.getInstruction());
 		GridBagConstraints gbc_txtpnInstructions = new GridBagConstraints();
 		gbc_txtpnInstructions.fill = GridBagConstraints.BOTH;
 		gbc_txtpnInstructions.gridx = 1;

+ 14 - 4
src/main/lombok/org/leumasjaffe/recipe/view/SummaryPanel.java

@@ -7,14 +7,20 @@ import java.awt.Insets;
 
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.JSeparator;
 import javax.swing.JTextField;
 import javax.swing.JTextPane;
 
 import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.recipe.model.Product;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
 
 @SuppressWarnings("serial")
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class SummaryPanel extends JPanel {
-	JTextField txtTitle;
+	JPanel panelIngredients;
 	
 	public SummaryPanel() {
 		GridBagLayout gridBagLayout = new GridBagLayout();
@@ -39,7 +45,7 @@ public class SummaryPanel extends JPanel {
 		gbl_panelHeader.rowWeights = new double[]{0.0, Double.MIN_VALUE};
 		panelHeader.setLayout(gbl_panelHeader);
 		
-		txtTitle = new JTextField();
+		JTextField txtTitle = new JTextField();
 		txtTitle.setText("Title");
 		GridBagConstraints gbc_txtTitle = new GridBagConstraints();
 		gbc_txtTitle.insets = new Insets(0, 0, 0, 5);
@@ -55,8 +61,7 @@ public class SummaryPanel extends JPanel {
 		gbc_lblDuration.gridy = 0;
 		panelHeader.add(lblDuration, gbc_lblDuration);
 		
-		JPanel panelIngredients = new JPanel();
-		panelIngredients.setPreferredSize(new Dimension(200, 100));
+		panelIngredients = new JPanel();
 		GridBagConstraints gbc_panelIngredients = new GridBagConstraints();
 		gbc_panelIngredients.gridheight = 2;
 		gbc_panelIngredients.insets = new Insets(0, 0, 0, 5);
@@ -83,4 +88,9 @@ public class SummaryPanel extends JPanel {
 		gbc_txtpnDescription.gridy = 2;
 		add(txtpnDescription, gbc_txtpnDescription);
 	}
+
+	void addProduct(final Product comp) {
+		panelIngredients.add(new ProductSummaryPanel(comp));
+		panelIngredients.add(new JSeparator());
+	}
 }

+ 57 - 3
src/test/resources/example.json

@@ -13,16 +13,70 @@
             "ingredients": [
               {
                 "name": "onion",
-                "preparation": "",
+                "preparation": "chopped",
                 "amount": "100 g"
-              }
+              },
+              {
+                "name": "onion",
+                "amount": "1"
+              },
+              {
+              	"name": "oil",
+              	"amount": "1 Tbsp"
+            	},
+              {
+              	"name": "oil",
+              	"amount": "1 Tbsp"
+            	}
             ],
             "duration": {
               "displayAs": "MINUTES",
-              "isApproximate": true,
+              "approximate": true,
               "minSeconds": 300,
               "maxSeconds": 600
             }
+          },
+          "cooking": [
+          	{
+          		"ingredients": [
+          			{
+          				"name": "oil",
+          				"amount": "1 Tbsp"
+          			}
+          		],
+	            "duration": {
+	              "displayAs": "SECONDS",
+	              "approximate": true,
+	              "minSeconds": 30,
+	              "maxSeconds": 60
+	            },
+          		"instruction": "Heat oil over high heat"
+          	},
+          	{
+          		"ingredients": [
+          			{
+          				"name": "onion",
+          				"preparation": "chopped",
+          				"amount": "100 g"
+          			}
+          		],
+	            "duration": {
+	              "displayAs": "MINUTES",
+	              "approximate": true,
+	              "minSeconds": 300,
+	              "maxSeconds": 900
+	            },
+          		"instruction": "Sauté the onions until soft and translucent, stirring to prevent burning"
+          	}
+          ],
+          "rest": {
+          	"where": "ROOM_TEMPERATURE",
+            "duration": {
+              "displayAs": "SECONDS",
+              "approximate": false,
+              "minSeconds": 30,
+              "maxSeconds": 30
+            }
           }
         }
       ]