diff --git a/res/stages/data-view-stage.fxml b/res/stages/data-view-stage.fxml index 4eaff3a517f37cf2129ee0f95c841f2182c4ff82..0c9adc6f66b2ec31f0b2d41509fd91e5ef02643f 100644 --- a/res/stages/data-view-stage.fxml +++ b/res/stages/data-view-stage.fxml @@ -6,37 +6,56 @@ <?import javafx.scene.control.*?> <?import javafx.scene.image.*?> <?import javafx.scene.layout.*?> +<?import javafx.scene.text.*?> <?import javafx.stage.*?> -<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> +<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.DataStageController"> <scene> <Scene> - <AnchorPane prefHeight="363.0" prefWidth="692.0"> + <AnchorPane prefHeight="487.0" prefWidth="692.0"> <children> - <VBox prefHeight="363.0" prefWidth="691.0"> + <VBox prefHeight="488.0" prefWidth="691.0"> <children> - <HBox prefHeight="356.0" prefWidth="691.0"> + <HBox alignment="TOP_CENTER" prefHeight="356.0" prefWidth="691.0" spacing="5.0"> <children> - <Region prefHeight="338.0" prefWidth="65.0" /> - <ScatterChart prefHeight="342.0" prefWidth="609.0"> - <xAxis> - <CategoryAxis fx:id="absAxeView" prefHeight="21.0" prefWidth="498.0" side="BOTTOM" /> - </xAxis> - <yAxis> - <NumberAxis fx:id="ordAxeView" side="LEFT" /> - </yAxis> - </ScatterChart> - <Button fx:id="settingsView" mnemonicParsing="false"> - <graphic> - <ImageView fitHeight="100.0" fitWidth="30.0" pickOnBounds="true" preserveRatio="true"> - <image> - <Image url="@gear.png" /> - </image></ImageView> - </graphic> + <AnchorPane prefHeight="200.0" prefWidth="200.0"> + <children> + <Region prefHeight="338.0" prefWidth="65.0" /> + <ScatterChart fx:id="scatterChart" prefHeight="342.0" prefWidth="609.0"> + <xAxis> + <NumberAxis fx:id="absAxe" prefHeight="21.0" prefWidth="498.0" side="BOTTOM" /> + </xAxis> + <yAxis> + <NumberAxis fx:id="ordAxe" side="LEFT" /> + </yAxis> + </ScatterChart> + <Label fx:id="AxesSelected" alignment="CENTER" layoutX="175.0" layoutY="152.0" prefHeight="38.0" prefWidth="259.0"> + <font> + <Font size="21.0" /> + </font></Label> + </children> <HBox.margin> - <Insets right="10.0" top="30.0" /> + <Insets left="10.0" /> </HBox.margin> - </Button> + </AnchorPane> + <Button fx:id="settingsView" mnemonicParsing="false" onAction="#openAxesSetting"> + <graphic> + <ImageView fitHeight="100.0" fitWidth="30.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@gear.png" /> + </image> + </ImageView> + </graphic> + <HBox.margin> + <Insets top="40.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + <HBox alignment="CENTER" prefHeight="169.0" prefWidth="691.0" spacing="50.0"> + <children> + <Button fx:id="addData" mnemonicParsing="false" onAction="#openAddData" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" /> + <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> </children> </HBox> </children> diff --git a/res/stages/main-stage.fxml b/res/stages/main-stage.fxml index 21c1941b9e1627e260b3f2c5f765e0bc59535401..d96791c6fc56edec5a2bb01d5b71bdb294fcdaa2 100644 --- a/res/stages/main-stage.fxml +++ b/res/stages/main-stage.fxml @@ -9,7 +9,7 @@ <?import javafx.scene.text.*?> <?import javafx.stage.*?> -<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> +<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> <scene> <Scene> <AnchorPane prefHeight="487.0" prefWidth="692.0"> @@ -52,13 +52,18 @@ </Button> </children> </HBox> - <HBox alignment="CENTER" prefHeight="169.0" prefWidth="691.0" spacing="50.0"> + <VBox alignment="TOP_CENTER" prefHeight="200.0" prefWidth="100.0"> <children> - <Button fx:id="loadData" mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="185.0" text="Charger un jeu de données" /> - <Button fx:id="addData" mnemonicParsing="false" onAction="#openAddData" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" /> - <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> + <HBox alignment="CENTER" prefHeight="85.0" prefWidth="691.0" spacing="50.0"> + <children> + <Button fx:id="loadData" mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="185.0" text="Charger un jeu de données" /> + <Button fx:id="addData" mnemonicParsing="false" onAction="#openAddData" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" /> + <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> + </children> + </HBox> + <Button alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#openDataView" text="Ouvrir une autre vue" /> </children> - </HBox> + </VBox> </children> </VBox> </children></AnchorPane> diff --git a/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java b/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java new file mode 100644 index 0000000000000000000000000000000000000000..8df439c61c0603b6b3c2e600d2545ead503b2661 --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java @@ -0,0 +1,92 @@ +package fr.univlille.sae.classification.controller; + +import fr.univlille.sae.classification.model.ClassificationModel; +import fr.univlille.sae.classification.view.*; +import javafx.fxml.FXML; +import javafx.scene.chart.NumberAxis; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.stage.Stage; + +import java.io.IOException; + + +public class DataStageController { + @FXML + Stage stage; + + @FXML + NumberAxis absAxe; + + @FXML + NumberAxis ordAxe; + + @FXML + Button settings; + + @FXML + Button loadData; + + @FXML + Button addData; + + @FXML + Button classifyData; + + @FXML + ScatterChart scatterChart; + + @FXML + Label AxesSelected; + + Stage loadStage; + private DataStageView dataStageView; + + /** + * Ouvre l'interface de chargement des données. + * @throws IOException + */ + public void openLoadData() throws IOException { + LoadDataView loadDataView = new LoadDataView(ClassificationModel.getClassificationModel(), stage); + loadDataView.show(); + } + + public void openAxesSetting()throws IOException { + AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, dataStageView); + axesSettingsView.show(); + } + + public void setDataStageView (DataStageView dataStageView) { + this.dataStageView = dataStageView; + } + + /** + * Ouvre l'interface d'ajout de donnée. + * @throws IOException + */ + public void openAddData() throws IOException { + AddDataView addDataView = new AddDataView(ClassificationModel.getClassificationModel(), stage, dataStageView); + addDataView.show(); + } + + + + public void classifyDatas() { + ClassificationModel.getClassificationModel().classifierDonnees(); + classifyData.setDisable(true); + } + + + public ScatterChart getScatterChart() { + return this.scatterChart; + } + + public void setAxesSelected(String texte) { + this.AxesSelected.setText(texte); + } + + public Button getClassifyData() { + return this.classifyData; + } +} diff --git a/src/main/java/fr/univlille/sae/classification/controller/DataViewStage.java b/src/main/java/fr/univlille/sae/classification/controller/DataViewStage.java deleted file mode 100644 index fe7a9b0083d0ef2abc3ac4a22eb5be0faae92c5c..0000000000000000000000000000000000000000 --- a/src/main/java/fr/univlille/sae/classification/controller/DataViewStage.java +++ /dev/null @@ -1,22 +0,0 @@ -package fr.univlille.sae.classification.controller; - -import javafx.fxml.FXML; -import javafx.scene.chart.CategoryAxis; -import javafx.scene.chart.NumberAxis; -import javafx.scene.control.Button; -import javafx.stage.Stage; - -public class DataViewStage { - - @FXML - Stage stage; - - @FXML - CategoryAxis absAxe; - - @FXML - NumberAxis ordAxe; - - @FXML - Button settings; -} diff --git a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java index bf9f71772b2d4d293772505e2f4e0b38e2b9f693..bf8ab81524503f95f0e79d146a92a2da1545ab7d 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java @@ -1,10 +1,7 @@ package fr.univlille.sae.classification.controller; import fr.univlille.sae.classification.model.ClassificationModel; -import fr.univlille.sae.classification.view.AxesSettingsView; -import fr.univlille.sae.classification.view.LoadDataView; -import fr.univlille.sae.classification.view.AddDataView; -import fr.univlille.sae.classification.view.MainStageView; +import fr.univlille.sae.classification.view.*; import javafx.fxml.FXML; import javafx.scene.chart.*; @@ -59,6 +56,11 @@ public class MainStageController { loadDataView.show(); } + public void openDataView() throws IOException { + DataStageView dataStageView = new DataStageView(ClassificationModel.getClassificationModel()); + dataStageView.show(); + } + public void openAxesSetting()throws IOException { AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, mainStageView); axesSettingsView.show(); diff --git a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java index f52b777a7d536b07d41032a0b6412eed913807fa..fbc948a225c1120786a06625616c7287715028dd 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java @@ -17,6 +17,7 @@ public class AddDataView { private ClassificationModel model; private Stage owner; private MainStageView mainStageView; + private DataStageView dataStageView; public AddDataView(ClassificationModel model, Stage owner, MainStageView mainStageView) { this.model = model; @@ -24,7 +25,11 @@ public class AddDataView { this.mainStageView = mainStageView; } - + public AddDataView(ClassificationModel model, Stage owner, DataStageView dataStageView) { + this.model = model; + this.owner = owner; + this.dataStageView = dataStageView; + } public void show() throws IOException { diff --git a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java index 48ca4ce0f1b8e3369cc350672cb210b2a0bb39e2..8f959e2fd2358dc7c65f63f0d1849b9b4a183cd9 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java @@ -1,6 +1,7 @@ package fr.univlille.sae.classification.view; import fr.univlille.sae.classification.controller.AxesSettingsController; +import fr.univlille.sae.classification.controller.DataStageController; import fr.univlille.sae.classification.controller.MainStageController; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.LoadableData; @@ -9,6 +10,7 @@ import javafx.scene.control.Alert; import javafx.stage.Modality; import javafx.stage.Stage; +import javax.xml.crypto.Data; import java.io.File; import java.io.IOException; import java.net.URL; @@ -19,6 +21,7 @@ public class AxesSettingsView { private ClassificationModel model; private Stage owner; private MainStageView mainStageView; + private DataStageView dataStageView; public AxesSettingsView(ClassificationModel model, Stage owner, MainStageView mainStageView){ this.model = model; @@ -26,6 +29,12 @@ public class AxesSettingsView { this.mainStageView = mainStageView; } + public AxesSettingsView(ClassificationModel model, Stage owner, DataStageView dataStageView) { + this.model = model; + this.owner = owner; + this.dataStageView = dataStageView; + } + public void show() throws IOException { FXMLLoader loader = new FXMLLoader(); diff --git a/src/main/java/fr/univlille/sae/classification/view/DataStageView.java b/src/main/java/fr/univlille/sae/classification/view/DataStageView.java new file mode 100644 index 0000000000000000000000000000000000000000..3362f0c6fdffe57671224c9d92e1bb2724bb18cc --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/view/DataStageView.java @@ -0,0 +1,159 @@ +package fr.univlille.sae.classification.view; + +import fr.univlille.sae.classification.controller.DataStageController; +import fr.univlille.sae.classification.controller.MainStageController; +import fr.univlille.sae.classification.model.ClassificationModel; +import fr.univlille.sae.classification.model.DataType; +import fr.univlille.sae.classification.model.Iris; +import fr.univlille.sae.classification.model.LoadableData; +import fr.univlille.sae.classification.utils.Observable; +import fr.univlille.sae.classification.utils.Observer; +import javafx.fxml.FXMLLoader; +import javafx.scene.chart.ScatterChart; +import javafx.scene.chart.XYChart; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.shape.Circle; +import javafx.stage.Stage; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +public class DataStageView implements Observer { + + private ClassificationModel model; + private ScatterChart scatterChart; + private DataStageController controller; + + private String actualX; + private String actualY; + private Stage root; + + public DataStageView(ClassificationModel model) { + this.model = model; + model.attach(this); + } + + public void show() throws IOException { + FXMLLoader loader = new FXMLLoader(); + + URL fxmlFileUrl = new File(System.getProperty("user.dir") + File.separator + "res" + File.separator + "stages" + File.separator + "data-view-stage.fxml").toURI().toURL(); + + if (fxmlFileUrl == null) { + System.out.println("Impossible de charger le fichier fxml"); + System.exit(-1); + } + loader.setLocation(fxmlFileUrl); + root = loader.load(); + root.setResizable(false); + root.setTitle("SAE3.3 - Logiciel de classification"); + root.show(); + loader.getController(); + controller = loader.getController(); + controller.setDataStageView(this); + scatterChart = controller.getScatterChart(); + controller.setAxesSelected("Aucun fichier sélectionné"); + } + + @Override + public void update(Observable observable) { + if(scatterChart == null) throw new IllegalStateException(); + if(!(observable instanceof ClassificationModel)) throw new IllegalStateException(); + //on vide le nuage pour s'assurer que celui-ci est bien vide + scatterChart.getData().clear(); + + XYChart.Series series1 = new XYChart.Series(); + series1.setName("Iris"); + + //Jalon 1: on verifie que le type de donnée est bien IRIS + if(model.getType() == DataType.IRIS) { + if(actualX==null && actualY==null){ + controller.setAxesSelected("Aucuns axes sélectionnés"); + } + else{ + controller.setAxesSelected(""); + // On ajoute la serie au nuage + scatterChart.getData().add(series1); + + //On recupere les données du model + List<LoadableData> points = new ArrayList<>(model.getDatas()); + points.addAll(model.getDataToClass()); + // on ajoute chaque point a la serie + for(LoadableData i : points) { + + Iris iris = (Iris)i; + XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>(iris.getDataType(actualX), + iris.getDataType(actualY)); + + dataPoint.setNode(getCircle(iris)); + + series1.getData().add(dataPoint); + + } + } + } + } + + + private Circle getCircle(Iris iris) { + Circle circle = new Circle(5); + circle.setFill(iris.getColor()); + circle.setOnMouseClicked(e -> { + ContextMenu contextMenu = new ContextMenu(); + for(String attributes : iris.getAttributesName()) { + contextMenu.getItems().add(new MenuItem(attributes + " : " + iris.getDataType(attributes))); + } + contextMenu.show(root, e.getScreenX(), e.getScreenY()); + }); + + return circle; + } + + + + @Override + public void update(Observable observable, Object data) { + if(scatterChart == null) throw new IllegalStateException(); + if(!(observable instanceof ClassificationModel)) throw new IllegalStateException(); + if(data instanceof Iris) { + Iris iris = (Iris) data; + if(actualX == null || actualY == null) { + controller.setAxesSelected("Aucuns axes sélectionnés"); + return; + } + XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>( + iris.getDataType(actualX), + iris.getDataType(actualY) + ); + + dataPoint.setNode(getCircle(iris)); + if (!scatterChart.getData().isEmpty()) { + XYChart.Series series = (XYChart.Series) scatterChart.getData().get(0); + series.getData().add(dataPoint); + } + } + } + + public void setActualX(String actualX) { + this.actualX = actualX; + } + + public void setActualY(String actualY) { + this.actualY = actualY; + } + + public String getActualX() { + return actualX; + } + + public String getActualY() { + return actualY; + } + + public DataStageController getController() { + return controller; + } +}