diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index eb1faea..a198cd9 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,14 +4,21 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -21,8 +28,9 @@
@@ -51,16 +59,17 @@
- {
- "keyToString": {
- "RunOnceActivity.OpenProjectViewOnStart": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "SHARE_PROJECT_CONFIGURATION_FILES": "true",
- "project.structure.last.edited": "Modules",
- "project.structure.proportion": "0.0",
- "project.structure.side.proportion": "0.0"
+
+}]]>
@@ -127,7 +136,21 @@
1665408691947
-
+
+ 1665574402609
+
+
+
+ 1665574402609
+
+
+ 1665574505216
+
+
+
+ 1665574505216
+
+
@@ -146,6 +169,7 @@
-
+
+
\ No newline at end of file
diff --git a/gitignore b/gitignore
index 3e04d18..a9f9b48 100644
--- a/gitignore
+++ b/gitignore
@@ -41,6 +41,9 @@
# *.iml
# *.ipr
+#iut
+*.bin
+
# CMake
cmake-build-*/
diff --git a/resources/fxml/MainWindow.fxml b/resources/fxml/MainWindow.fxml
index fe7459b..ee3a3aa 100644
--- a/resources/fxml/MainWindow.fxml
+++ b/resources/fxml/MainWindow.fxml
@@ -4,8 +4,7 @@
+ xmlns:fx="http://javafx.com/fxml">
diff --git a/src/data/Loadable.java b/src/data/Loadable.java
index 8dbe83a..83256e3 100644
--- a/src/data/Loadable.java
+++ b/src/data/Loadable.java
@@ -2,6 +2,8 @@ package data;
import model.Shop;
-interface Loadable {
- Shop load();
+import java.io.IOException;
+
+public interface Loadable {
+ Shop load() throws IOException, ClassNotFoundException;
}
diff --git a/src/data/Loader.java b/src/data/Loader.java
new file mode 100644
index 0000000..2e69e45
--- /dev/null
+++ b/src/data/Loader.java
@@ -0,0 +1,17 @@
+package data;
+
+import model.Shop;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+public class Loader implements Loadable {
+ @Override
+ public Shop load() throws IOException, ClassNotFoundException {
+ try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("save.bin"))) {
+ System.out.println("...loading!...");
+ return (Shop) ois.readObject();
+ }
+ }
+}
diff --git a/src/data/Savable.java b/src/data/Savable.java
new file mode 100644
index 0000000..7134aa0
--- /dev/null
+++ b/src/data/Savable.java
@@ -0,0 +1,9 @@
+package data;
+
+import model.Shop;
+
+import java.io.IOException;
+
+public interface Savable {
+ void save(Shop model) throws IOException;
+}
diff --git a/src/data/Saver.java b/src/data/Saver.java
new file mode 100644
index 0000000..a6c0dab
--- /dev/null
+++ b/src/data/Saver.java
@@ -0,0 +1,18 @@
+package data;
+
+import model.Shop;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+
+
+public class Saver implements Savable {
+ @Override
+ public void save(Shop model) throws IOException {
+ try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("save.bin"))) {
+ System.out.println("...saving!...");
+ oos.writeObject(model);
+ }
+ }
+}
diff --git a/src/data/Stub.java b/src/data/Stub.java
index b8441f6..81fcb82 100644
--- a/src/data/Stub.java
+++ b/src/data/Stub.java
@@ -3,10 +3,12 @@ package data;
import model.*;
import util.Size;
+import java.io.IOException;
+
public class Stub implements Loadable {
@Override
- public Shop load() {
+ public Shop load() throws IOException, ClassNotFoundException {
Shop shop = new Shop();
Garment p1 = new Garment("shirt", 15.9);
diff --git a/src/launcher/Launcher.java b/src/launcher/Launcher.java
index 234f3d3..25c69a3 100644
--- a/src/launcher/Launcher.java
+++ b/src/launcher/Launcher.java
@@ -4,16 +4,38 @@ import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
+import javafx.scene.control.Alert;
+import javafx.scene.control.ButtonType;
import javafx.stage.Stage;
+import view.MainWindow;
+import viewmodel.ShopVM;
+import java.io.IOException;
import java.util.Objects;
public class Launcher extends Application {
+
+ private final ShopVM viewmodel = new ShopVM();
+
@Override
public void start(Stage primaryStage) throws Exception {
- Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/MainWindow.fxml")));
+ FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MainWindow.fxml"));
+
+ loader.setController(new MainWindow(viewmodel));
+
+ Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
+
+ @Override
+ public void stop() throws Exception {
+ try {
+ viewmodel.save();
+ } catch (IOException ex) {
+ new Alert(Alert.AlertType.ERROR, "was not able to save", ButtonType.OK).setHeaderText(null);
+ }
+ super.stop();
+ }
}
diff --git a/src/model/Product.java b/src/model/Product.java
index f2335ad..bc4efd1 100644
--- a/src/model/Product.java
+++ b/src/model/Product.java
@@ -1,12 +1,10 @@
package model;
-import org.w3c.dom.css.CSSFontFaceRule;
-
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
-import java.util.UUID;
+import java.io.Serializable;
-public class Product {
+public class Product implements Serializable {
private String name;
@@ -27,11 +25,12 @@ public class Product {
public void setName(String name) {
String oldV = getName();
this.name = name;
- support.firePropertyChange(
+ getSupport().firePropertyChange(
PROP_PRODUCT_NAME,
oldV,
getName()
);
+ System.out.println("set my name to " + name);
}
public double getPrice() {
@@ -41,20 +40,38 @@ public class Product {
public void setPrice(double price) {
Double oldV = getPrice();
this.price = price;
- support.firePropertyChange(
+ getSupport().firePropertyChange(
PROP_PRODUCT_PRICE,
oldV,
getPrice()
);
+ System.out.println("set my price to " + price);
+ }
+
+ private PropertyChangeSupport support;
+
+ public PropertyChangeSupport getSupport() {
+ if(support == null) {
+ support = new PropertyChangeSupport(this);
+ }
+ return support;
}
- private final PropertyChangeSupport support = new PropertyChangeSupport(this);
- public static final String PROP_PRODUCT_NAME = UUID.randomUUID().toString();
- public static final String PROP_PRODUCT_PRICE = UUID.randomUUID().toString();
+ public static final String PROP_PRODUCT_NAME = "model.product.name";
+ public static final String PROP_PRODUCT_PRICE = "model.product.price";
public void addListener(PropertyChangeListener listener) {
- support.addPropertyChangeListener(listener);
+ getSupport().addPropertyChangeListener(listener);
}
+ @Override
+ public int hashCode() {
+ return getName().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Product && ((Product) obj).getName().equals(getName());
+ }
}
diff --git a/src/model/Shop.java b/src/model/Shop.java
index e2ed5c6..9574c6a 100644
--- a/src/model/Shop.java
+++ b/src/model/Shop.java
@@ -4,41 +4,62 @@ import data.Stub;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
-public class Shop {
+public class Shop implements Serializable {
+ public static final String PROP_SHOP_ADD = "model.shop.addProduct";
+ public static final String PROP_SHOP_RMV = "model.shop.removeProduct";
private final List products = new ArrayList<>();
public void addProduct(Product product) {
-
products.add(0, product);
- support.fireIndexedPropertyChange(
- PROP_SHOP,
+ getSupport().fireIndexedPropertyChange(
+ PROP_SHOP_ADD,
0,
products.size() > 1 ? products.get(1) : null,
product
);
+ System.out.println("added " + product.getName() + " ($" + product.getPrice() + ")");
+ }
+
+ public void removeProduct(Product product) {
+
+ System.out.println("removed " + product.getName() + " ($" + product.getPrice() + ")");
+ int index = products.indexOf(product);
+ if (index != -1){
+ products.remove(product);
+ getSupport().fireIndexedPropertyChange(
+ PROP_SHOP_RMV,
+ index,
+ product,
+ products.get(index)
+ );
+ }
+
}
public List getProducts() {
return Collections.unmodifiableList(products);
}
- public void removeProduct(Product product) {
- products.remove(product);
- }
- public static final String PROP_SHOP = UUID.randomUUID().toString();
+ private transient PropertyChangeSupport support;
- private final PropertyChangeSupport support = new PropertyChangeSupport(this);
+ private PropertyChangeSupport getSupport() {
+ if(support == null) {
+ support = new PropertyChangeSupport(this);
+ }
+ return support;
+ }
public void addListener(PropertyChangeListener listener) {
- support.addPropertyChangeListener(listener);
+ getSupport().addPropertyChangeListener(listener);
}
}
diff --git a/src/view/MainWindow.java b/src/view/MainWindow.java
index 0583174..0ea182d 100644
--- a/src/view/MainWindow.java
+++ b/src/view/MainWindow.java
@@ -1,8 +1,5 @@
package view;
-import com.sun.scenario.effect.impl.sw.java.JSWBlend_SRC_OUTPeer;
-import javafx.beans.property.Property;
-import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
@@ -31,7 +28,15 @@ public class MainWindow {
@FXML
private ListView productsVMLV;
- private ShopVM shopVM;
+ private final ShopVM viewmodel;
+
+ public MainWindow(ShopVM viewmodel) {
+ this.viewmodel = viewmodel;
+ }
+
+ public MainWindow() {
+ this(new ShopVM());
+ }
@FXML
private void clickAddGarment() {
@@ -51,29 +56,28 @@ public class MainWindow {
ProductCreationWindow controller = initProductCreationWindow(creationWindowStage);
- String name = controller.getProductVMName();
- String priceString = controller.getProductVMPrice();
-
try {
- if (name != null && priceString != null) {
- addProductVMToShop(name, priceString, code);
+ if (controller.getProductVMName() != null
+ && controller.getProductVMPrice() != null) {
+ addProductVMToShop(
+ controller.getProductVMName(),
+ controller.getProductVMPrice(),
+ code);
}
} catch (NumberFormatException ex) {
new Alert(Alert.AlertType.ERROR,
"could not parse PRICE as a number, please try again",
ButtonType.OK)
- .setHeaderText("yikes");
+ .setHeaderText(null);
}
}
private void addProductVMToShop(String name, String priceString, int code) {
-
if (code == GARMENT) {
- shopVM.addGarmentVM(new GarmentVM(name, Double.valueOf(priceString)));
+ viewmodel.addGarmentVM(new GarmentVM(name, Double.valueOf(priceString)));
}
if (code == PERFUME) {
- shopVM.addPerfumeVM(new PerfumeVM(name, Double.valueOf(priceString)));
-
+ viewmodel.addPerfumeVM(new PerfumeVM(name, Double.valueOf(priceString)));
}
}
@@ -90,23 +94,19 @@ public class MainWindow {
new Alert(Alert.AlertType.ERROR,
"error while opening product creation window",
ButtonType.OK)
- .setHeaderText("woopsie");
+ .setHeaderText(null);
}
-
return controller;
}
-
@FXML
private void clickRemoveProduct() {
- shopVM.removeProduct(productsVMLV.getSelectionModel().getSelectedItem());
+ viewmodel.removeProduct(productsVMLV.getSelectionModel().getSelectedItem());
}
@FXML
private void initialize() {
- shopVM = new ShopVM();
-// shopVM.getProductsVM().forEach(System.out::println);
- productsVMLV.itemsProperty().bind(shopVM.productsVMProperty());
+ productsVMLV.itemsProperty().bind(viewmodel.productsVMProperty());
addListenerProductsVMLV();
productsVMLV.setCellFactory(__ -> new ProductCell());
}
diff --git a/src/viewmodel/ProductVM.java b/src/viewmodel/ProductVM.java
index 7447643..d76b55b 100644
--- a/src/viewmodel/ProductVM.java
+++ b/src/viewmodel/ProductVM.java
@@ -3,37 +3,85 @@ package viewmodel;
import javafx.beans.property.*;
import model.Product;
-public class ProductVM {
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import static model.Product.PROP_PRODUCT_NAME;
+import static model.Product.PROP_PRODUCT_PRICE;
+
+public class ProductVM implements PropertyChangeListener {
+
+ private final Product model;
+
+ public Product getModel() {
+ return model;
+ }
- Product model;
private final StringProperty name = new SimpleStringProperty();
public ProductVM(String name, Double price) {
model = new Product();
+ //loads
setName(name == null ? model.getName() : name);
setPrice(price == null ? model.getPrice() : price);
+ //subscribes
+ model.addListener(this);
+
+ // promises to update model
nameProperty().addListener((__, ___, newV) -> model.setName(newV));
priceProperty().addListener((__, ___, newV) -> model.setPrice((Double) newV));
}
- public ProductVM() {
- this(null, null);
+ public ProductVM(Object o) {
+ this(o != null ? ((Product) o).getName() : null,
+ o != null ? ((Product) o).getPrice() : null);
+ }
+
+ public String getName() {
+ return name.get();
}
- public String getName() {return name.get();}
public void setName(String name) {this.name.set(name);}
- public StringProperty nameProperty() {return name;}
+
+ public StringProperty nameProperty() {
+ return name;
+ }
private final DoubleProperty price = new SimpleDoubleProperty();
- public double getPrice() {return price.get();}
- public DoubleProperty priceProperty() {return price;}
+
+ public double getPrice() {
+ return price.get();
+ }
+
+ public DoubleProperty priceProperty() {
+ return price;
+ }
+
public void setPrice(double price) {this.price.set(price);}
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals(PROP_PRODUCT_NAME)) {
+ setName((String) evt.getNewValue());
+ }
+ if (evt.getPropertyName().equals(PROP_PRODUCT_PRICE)) {
+ setPrice((Double) evt.getNewValue());
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return getName().hashCode();
+ }
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof ProductVM && ((ProductVM) obj).getName().equals(getName());
+ }
}
diff --git a/src/viewmodel/ShopVM.java b/src/viewmodel/ShopVM.java
index 45b79f0..842826c 100644
--- a/src/viewmodel/ShopVM.java
+++ b/src/viewmodel/ShopVM.java
@@ -1,5 +1,7 @@
package viewmodel;
+import data.Loader;
+import data.Saver;
import data.Stub;
import javafx.beans.property.ListProperty;
import javafx.beans.property.ReadOnlyListProperty;
@@ -11,44 +13,80 @@ import model.Shop;
import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import java.io.IOException;
public class ShopVM implements PropertyChangeListener {
- private final ObservableList productsVMObs = FXCollections.observableArrayList();
- private final ListProperty productsVM = new SimpleListProperty<>(productsVMObs);
+ private final Shop model;
- public ObservableList getProductsVM() {
- return FXCollections.unmodifiableObservableList(productsVM.get());
+ public Shop getModel() {
+ return model;
}
- public ReadOnlyListProperty productsVMProperty() {
- return productsVM;
- }
+ private final ObservableList productsVMObs = FXCollections.observableArrayList();
+ private final ListProperty productsVM = new SimpleListProperty<>(productsVMObs);
+ public ObservableList getProductsVM() { return FXCollections.unmodifiableObservableList(productsVM.get()); }
+ public ReadOnlyListProperty productsVMProperty() { return productsVM; }
public ShopVM() {
- Shop model = new Stub().load();
+ Shop tmpModel;
+
+ try {
+ System.out.println("trying real load");
+ tmpModel = new Loader().load();
+ } catch (IOException | ClassNotFoundException e) {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ try {
+ System.out.println("trying stub load");
+ tmpModel = new Stub().load();
+ } catch (IOException | ClassNotFoundException ex) {
+ System.out.println("giving up load and creating new");
+ tmpModel= new Shop();
+ }
+ }
+
+ //loads
+ model = tmpModel;
model.getProducts().forEach(p -> productsVMObs.add(new ProductVM(p.getName(), p.getPrice())));
+
+ //subscribes
+ model.addListener(this);
+
+ //will update with its methods
}
public void removeProduct(ProductVM productVM) {
productsVMObs.remove(productVM);
+ getModel().removeProduct(productVM.getModel());
}
public void addGarmentVM(GarmentVM garmentVM) {
-
+ productsVMObs.add(garmentVM);
+ getModel().addProduct(garmentVM.getModel());
}
public void addPerfumeVM(PerfumeVM perfumeVM) {
+ productsVMObs.add(perfumeVM);
+ getModel().addProduct(perfumeVM.getModel());
+ }
+
+ public void save() throws IOException {
+ Saver saver = new Saver();
+ saver.save(getModel());
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
- if (evt.getPropertyName().equals(Shop.PROP_SHOP)) {
- ProductVM pvm = ((ProductVM) evt.getNewValue());
+ if (evt.getPropertyName().equals(Shop.PROP_SHOP_ADD)) {
+ ProductVM pvm = new ProductVM(evt.getNewValue());
productsVMObs.add(
- ((IndexedPropertyChangeEvent) evt).getIndex()
- , new ProductVM(pvm.getName(), pvm.getPrice())
+ ((IndexedPropertyChangeEvent) evt).getIndex(),
+ pvm
);
}
+ if (evt.getPropertyName().equals(Shop.PROP_SHOP_RMV)) {
+ productsVMObs.remove(new ProductVM(evt.getOldValue())); // redefined equals an toHash
+ }
}
}