main
Alexis Drai 3 years ago
parent fe110224fa
commit a45996d56e

@ -4,14 +4,21 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="39201d7d-d87b-4c10-b0b0-e462b4f0b033" name="Changes" comment=":construction: WIP">
<change beforePath="$PROJECT_DIR$/out/production/EShop/fxml/MainWindow.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/fxml/MainWindow.fxml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/out/production/EShop/model/Garment.class" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/model/Garment.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/out/production/EShop/model/Product.class" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/model/Product.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/out/production/EShop/model/Shop.class" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/model/Shop.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/out/production/EShop/viewmodel/GarmentVM.class" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/viewmodel/GarmentVM.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/out/production/EShop/viewmodel/PerfumeVM.class" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/viewmodel/PerfumeVM.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/out/production/EShop/viewmodel/ProductVM.class" beforeDir="false" afterPath="$PROJECT_DIR$/out/production/EShop/viewmodel/ProductVM.class" afterDir="false" />
<list default="true" id="39201d7d-d87b-4c10-b0b0-e462b4f0b033" name="Changes" comment="🙈 Update gitignore">
<change afterPath="$PROJECT_DIR$/src/data/Loader.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/data/Savable.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/data/Saver.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/resources/fxml/MainWindow.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/resources/fxml/MainWindow.fxml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/data/Loadable.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/data/Loadable.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/data/Stub.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/data/Stub.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/launcher/Launcher.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/launcher/Launcher.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/model/Product.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/model/Product.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/model/Shop.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/model/Shop.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/view/MainWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/view/MainWindow.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/viewmodel/ProductVM.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/viewmodel/ProductVM.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/viewmodel/ShopVM.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/viewmodel/ShopVM.java" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -21,8 +28,9 @@
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Class" />
<option value="FxmlFile" />
<option value="Interface" />
<option value="Class" />
</list>
</option>
</component>
@ -51,16 +59,17 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;project.structure.last.edited&quot;: &quot;Modules&quot;,
&quot;project.structure.proportion&quot;: &quot;0.0&quot;,
&quot;project.structure.side.proportion&quot;: &quot;0.0&quot;
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ASKED_ADD_EXTERNAL_FILES": "true",
"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"
}
}</component>
}]]></component>
<component name="RecentsManager">
<key name="CreateClassDialog.RecentsKey">
<recent name="viewmodel" />
@ -127,7 +136,21 @@
<option name="project" value="LOCAL" />
<updated>1665408691947</updated>
</task>
<option name="localTasksCounter" value="7" />
<task id="LOCAL-00007" summary="🙈 Update gitignore">
<created>1665574402609</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1665574402609</updated>
</task>
<task id="LOCAL-00008" summary="🙈 Update gitignore">
<created>1665574505216</created>
<option name="number" value="00008" />
<option name="presentableId" value="LOCAL-00008" />
<option name="project" value="LOCAL" />
<updated>1665574505216</updated>
</task>
<option name="localTasksCounter" value="9" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -146,6 +169,7 @@
<MESSAGE value=":necktie: Code the model" />
<MESSAGE value=":construction: Set up View and VM" />
<MESSAGE value=":construction: WIP" />
<option name="LAST_COMMIT_MESSAGE" value=":construction: WIP" />
<MESSAGE value=" Update gitignore" />
<option name="LAST_COMMIT_MESSAGE" value=" Update gitignore" />
</component>
</project>

@ -41,6 +41,9 @@
# *.iml
# *.ipr
#iut
*.bin
# CMake
cmake-build-*/

@ -4,8 +4,7 @@
<?import javafx.scene.layout.*?>
<BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="view.MainWindow">
xmlns:fx="http://javafx.com/fxml">
<center>
<VBox>

@ -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;
}

@ -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();
}
}
}

@ -0,0 +1,9 @@
package data;
import model.Shop;
import java.io.IOException;
public interface Savable {
void save(Shop model) throws IOException;
}

@ -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);
}
}
}

@ -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);

@ -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();
}
}

@ -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());
}
}

@ -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<Product> 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<Product> 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);
}
}

@ -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<ProductVM> 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());
}

@ -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());
}
}

@ -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<ProductVM> productsVMObs = FXCollections.observableArrayList();
private final ListProperty<ProductVM> productsVM = new SimpleListProperty<>(productsVMObs);
private final Shop model;
public ObservableList<ProductVM> getProductsVM() {
return FXCollections.unmodifiableObservableList(productsVM.get());
public Shop getModel() {
return model;
}
public ReadOnlyListProperty<ProductVM> productsVMProperty() {
return productsVM;
}
private final ObservableList<ProductVM> productsVMObs = FXCollections.observableArrayList();
private final ListProperty<ProductVM> productsVM = new SimpleListProperty<>(productsVMObs);
public ObservableList<ProductVM> getProductsVM() { return FXCollections.unmodifiableObservableList(productsVM.get()); }
public ReadOnlyListProperty<ProductVM> 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
}
}
}

Loading…
Cancel
Save