Skip to content
Snippets Groups Projects
Commit a6c166f4 authored by Edvard Granheim Harbo's avatar Edvard Granheim Harbo
Browse files

Added filehandling and saving fractals

parent a188177c
No related branches found
No related tags found
2 merge requests!54Final release,!37Added filehandling and saving fractals
Showing
with 225 additions and 78 deletions
...@@ -7,6 +7,7 @@ import edu.ntnu.idatt2003.mappevurderingprog2.models.Transform2D; ...@@ -7,6 +7,7 @@ import edu.ntnu.idatt2003.mappevurderingprog2.models.Transform2D;
import edu.ntnu.idatt2003.mappevurderingprog2.models.Vector2D; import edu.ntnu.idatt2003.mappevurderingprog2.models.Vector2D;
import edu.ntnu.idatt2003.mappevurderingprog2.models.chaos.ChaosGame; import edu.ntnu.idatt2003.mappevurderingprog2.models.chaos.ChaosGame;
import edu.ntnu.idatt2003.mappevurderingprog2.models.chaos.ChaosGameDescription; import edu.ntnu.idatt2003.mappevurderingprog2.models.chaos.ChaosGameDescription;
import edu.ntnu.idatt2003.mappevurderingprog2.models.chaos.ChaosGameFileHandler;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -80,4 +81,21 @@ public class GameController { ...@@ -80,4 +81,21 @@ public class GameController {
if (transforms.isEmpty()) return false; if (transforms.isEmpty()) return false;
return transforms.get(0) instanceof JuliaTransform; return transforms.get(0) instanceof JuliaTransform;
} }
public void saveFractalToFile(String name) throws Exception {
ChaosGameFileHandler.writeTransformationsToFile(ChaosGame.getInstance().getDescription(), name);
}
public void readFractalFromFile(String name) throws Exception {
ChaosGameDescription description = ChaosGameFileHandler.readTransformationsFromFile(name);
ChaosGame.getInstance().setDescription(description);
}
public boolean doesFileExist(String name) {
return ChaosGameFileHandler.checkFileExists(name);
}
public List<String> listTransformationFileNames() {
return ChaosGameFileHandler.listTransformationFileNames();
}
} }
\ No newline at end of file
...@@ -15,8 +15,8 @@ import java.util.Locale; ...@@ -15,8 +15,8 @@ import java.util.Locale;
import java.util.Scanner; import java.util.Scanner;
public class ChaosGameFileHandler { public class ChaosGameFileHandler {
public static ChaosGameDescription readTransformationsFromFile(String path) throws FileNotFoundException { public static ChaosGameDescription readTransformationsFromFile(String name) throws FileNotFoundException {
File file = new File(path); File file = new File("src/main/resources/transformations/" + name);
Scanner scanner = new Scanner(file).useLocale(Locale.ENGLISH); Scanner scanner = new Scanner(file).useLocale(Locale.ENGLISH);
String transformType = scanner.nextLine().trim(); String transformType = scanner.nextLine().trim();
...@@ -43,8 +43,8 @@ public class ChaosGameFileHandler { ...@@ -43,8 +43,8 @@ public class ChaosGameFileHandler {
return ChaosGameDescription.createWithTransforms(transforms, minCoords, maxCoords); return ChaosGameDescription.createWithTransforms(transforms, minCoords, maxCoords);
} }
public static void writeTransformationsToFile(ChaosGameDescription description, String path) throws Exception{ public static void writeTransformationsToFile(ChaosGameDescription description, String name) throws Exception{
try (FileWriter writer = new FileWriter(new File(path))) { try (FileWriter writer = new FileWriter("src/main/resources/transformations/" + name)) {
if (description.getTransforms().isEmpty()) return; if (description.getTransforms().isEmpty()) return;
Transform2D firstTransform = description.getTransforms().get(0); Transform2D firstTransform = description.getTransforms().get(0);
...@@ -69,6 +69,29 @@ public class ChaosGameFileHandler { ...@@ -69,6 +69,29 @@ public class ChaosGameFileHandler {
} }
} }
public static List<String> listTransformationFileNames() {
List<String> fileNames = new ArrayList<>();
File directory = new File("src/main/resources/transformations/");
if (directory.exists() && directory.isDirectory()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
fileNames.add(file.getName());
}
}
}
}
return fileNames;
}
public static boolean checkFileExists(String name) {
File file = new File("src/main/resources/transformations/" + name);
return file.exists();
}
private static String formatVector2D(Vector2D vector) { private static String formatVector2D(Vector2D vector) {
return String.format(Locale.ENGLISH, "%s, %s", vector.getX0(), vector.getX1()); return String.format(Locale.ENGLISH, "%s, %s", vector.getX0(), vector.getX1());
} }
......
...@@ -92,8 +92,38 @@ public class AffineDialog { ...@@ -92,8 +92,38 @@ public class AffineDialog {
HBox editBox = new HBox(10); HBox editBox = new HBox(10);
editBox.setAlignment(Pos.CENTER_LEFT); editBox.setAlignment(Pos.CENTER_LEFT);
Button editButton = new Button(isEditMode ? "Edit Fractal" : "Create Fractal"); Button editButton = new Button(isEditMode ? "Edit Fractal" : "Display Fractal");
editButton.setOnAction(event -> { editButton.setOnAction(event -> {
displayFractal(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, transformationFields);
});
HBox buttonBox = new HBox(10);
buttonBox.setAlignment(Pos.CENTER_RIGHT);
Button addBtn = new Button("Add Transformation");
addBtn.setOnAction(event -> {
addEmptyTransformationFields(grid, rowIndex.get(), transformationFields);
rowIndex.incrementAndGet();
});
Button removeBtn = new Button("Remove Transformation");
removeBtn.setOnAction(event -> {
if (!transformationFields.isEmpty()) {
Node[] lastFields = transformationFields.remove(transformationFields.size() - 1);
grid.getChildren().removeAll(lastFields);
rowIndex.decrementAndGet();
}
});
editBox.getChildren().addAll(editButton);
buttonBox.getChildren().addAll(addBtn, removeBtn);
dialogVBox.getChildren().addAll(scrollPane, editBox, buttonBox);
dialog.getDialogPane().setContent(dialogVBox);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
}
private void displayFractal(TextField stepsField, TextField minCoordsFieldX, TextField minCoordsFieldY, TextField maxCoordsFieldX, TextField maxCoordsFieldY, List<Node[]> transformationFields) {
if (stepsField.getText().isEmpty() || minCoordsFieldX.getText().isEmpty() || if (stepsField.getText().isEmpty() || minCoordsFieldX.getText().isEmpty() ||
minCoordsFieldY.getText().isEmpty() || maxCoordsFieldX.getText().isEmpty() || minCoordsFieldY.getText().isEmpty() || maxCoordsFieldX.getText().isEmpty() ||
maxCoordsFieldY.getText().isEmpty()) { maxCoordsFieldY.getText().isEmpty()) {
...@@ -143,32 +173,6 @@ public class AffineDialog { ...@@ -143,32 +173,6 @@ public class AffineDialog {
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
UserFeedback.showErrorPopup("Input Error", "Please enter valid numbers for all fields."); UserFeedback.showErrorPopup("Input Error", "Please enter valid numbers for all fields.");
} }
});
HBox buttonBox = new HBox(10);
buttonBox.setAlignment(Pos.CENTER_RIGHT);
Button addBtn = new Button("Add Transformation");
addBtn.setOnAction(event -> {
addEmptyTransformationFields(grid, rowIndex.get(), transformationFields);
rowIndex.incrementAndGet();
});
Button removeBtn = new Button("Remove Transformation");
removeBtn.setOnAction(event -> {
if (!transformationFields.isEmpty()) {
Node[] lastFields = transformationFields.remove(transformationFields.size() - 1);
grid.getChildren().removeAll(lastFields);
rowIndex.decrementAndGet();
}
});
editBox.getChildren().addAll(editButton);
buttonBox.getChildren().addAll(addBtn, removeBtn);
dialogVBox.getChildren().addAll(scrollPane, editBox, buttonBox);
dialog.getDialogPane().setContent(dialogVBox);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
} }
private void addTransformationFields(GridPane grid, AffineTransform2D transform, int rowIndex, List<Node[]> fieldList) { private void addTransformationFields(GridPane grid, AffineTransform2D transform, int rowIndex, List<Node[]> fieldList) {
......
...@@ -4,6 +4,7 @@ import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController; ...@@ -4,6 +4,7 @@ import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController;
import edu.ntnu.idatt2003.mappevurderingprog2.views.View; import edu.ntnu.idatt2003.mappevurderingprog2.views.View;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.geometry.Pos; import javafx.geometry.Pos;
...@@ -25,7 +26,11 @@ public class CreateFractalMenu extends VBox { ...@@ -25,7 +26,11 @@ public class CreateFractalMenu extends VBox {
juliaDialog.showDialog(); juliaDialog.showDialog();
}); });
getChildren().addAll(headline, affineButton, juliaButton); HBox buttonBox = new HBox(affineButton, juliaButton);
buttonBox.setAlignment(Pos.CENTER);
buttonBox.setSpacing(10);
getChildren().addAll(headline, buttonBox);
setAlignment(Pos.TOP_CENTER); setAlignment(Pos.TOP_CENTER);
setSpacing(10); setSpacing(10);
} }
......
...@@ -2,16 +2,19 @@ package edu.ntnu.idatt2003.mappevurderingprog2.views.Components; ...@@ -2,16 +2,19 @@ package edu.ntnu.idatt2003.mappevurderingprog2.views.Components;
import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController; import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController;
import edu.ntnu.idatt2003.mappevurderingprog2.views.View; import edu.ntnu.idatt2003.mappevurderingprog2.views.View;
import java.util.Optional;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.geometry.Pos; import javafx.geometry.Pos;
public class EditFractalMenu extends VBox { public class CurrentFractalMenu extends VBox {
private GameController gameController; private GameController gameController;
public EditFractalMenu(View view, GameController gameController) { public CurrentFractalMenu(View view, GameController gameController) {
this.gameController = gameController; this.gameController = gameController;
Label editLabel = new Label("Edit current fractal"); Label editLabel = new Label("Current fractal");
editLabel.setStyle("-fx-font-size: 16px; -fx-font-weight: bold;"); editLabel.setStyle("-fx-font-size: 16px; -fx-font-weight: bold;");
Button editButton = new Button("Edit"); Button editButton = new Button("Edit");
...@@ -27,7 +30,37 @@ public class EditFractalMenu extends VBox { ...@@ -27,7 +30,37 @@ public class EditFractalMenu extends VBox {
} }
}); });
getChildren().addAll(editLabel, editButton); Button saveButton = new Button("Save");
saveButton.setOnAction(event -> {
if (gameController.isChaosGameEmpty()) {
UserFeedback.showErrorPopup("Error", "There is no fractal to save");
} else {
TextInputDialog dialog = new TextInputDialog();
dialog.setTitle("Save fractal");
dialog.setHeaderText("Enter a name for the fractal");
dialog.setContentText("Name:");
Optional<String> result = dialog.showAndWait();
result.ifPresent(name -> {
if (gameController.doesFileExist(name)) {
UserFeedback.showErrorPopup("Error", "A fractal with that name already exists");
} else {
try {
gameController.saveFractalToFile(name);
UserFeedback.showConfirmationPopup("Success", "Fractal saved successfully");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
});
HBox buttonBox = new HBox(editButton, saveButton);
buttonBox.setAlignment(Pos.CENTER);
buttonBox.setSpacing(10);
getChildren().addAll(editLabel, buttonBox);
setAlignment(Pos.TOP_CENTER); setAlignment(Pos.TOP_CENTER);
setSpacing(10); setSpacing(10);
} }
......
...@@ -2,9 +2,15 @@ package edu.ntnu.idatt2003.mappevurderingprog2.views.Components; ...@@ -2,9 +2,15 @@ package edu.ntnu.idatt2003.mappevurderingprog2.views.Components;
import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController; import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController;
import edu.ntnu.idatt2003.mappevurderingprog2.views.View; import edu.ntnu.idatt2003.mappevurderingprog2.views.View;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
public class ExistingFractalsMenu extends VBox { public class ExistingFractalsMenu extends VBox {
...@@ -15,8 +21,48 @@ public class ExistingFractalsMenu extends VBox { ...@@ -15,8 +21,48 @@ public class ExistingFractalsMenu extends VBox {
BarnsleyFernButton barnsleyButton = new BarnsleyFernButton(view, view.getMainCanvas(), gameController); BarnsleyFernButton barnsleyButton = new BarnsleyFernButton(view, view.getMainCanvas(), gameController);
JuliaTransformationButton juliaButton = new JuliaTransformationButton(view, view.getMainCanvas(), gameController); JuliaTransformationButton juliaButton = new JuliaTransformationButton(view, view.getMainCanvas(), gameController);
getChildren().addAll(headline, sierpinskiButton, barnsleyButton, juliaButton); Button savedFractalsButton = new Button("Saved Fractals");
savedFractalsButton.setOnAction(event -> showSavedFractalsDialog(gameController));
getChildren().addAll(headline, sierpinskiButton, barnsleyButton, juliaButton, savedFractalsButton);
setAlignment(Pos.TOP_CENTER); setAlignment(Pos.TOP_CENTER);
setSpacing(10); setSpacing(10);
} }
private void showSavedFractalsDialog(GameController gameController) {
if (gameController.listTransformationFileNames().isEmpty()) {
UserFeedback.showErrorPopup("Error", "There are no saved fractals");
return;
}
Dialog<String> dialog = new Dialog<>();
dialog.setTitle("Select a Fractal");
dialog.setHeaderText("Choose a fractal to display:");
ButtonType loadButtonType = new ButtonType("Display", ButtonBar.ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loadButtonType, ButtonType.CANCEL);
ListView<String> listView = new ListView<>();
List<String> savedFractals = gameController.listTransformationFileNames();
listView.setItems(FXCollections.observableArrayList(savedFractals));
listView.setPrefHeight(180);
dialog.getDialogPane().setContent(listView);
dialog.setResultConverter(dialogButton -> {
if (dialogButton == loadButtonType && !listView.getSelectionModel().isEmpty()) {
return listView.getSelectionModel().getSelectedItem();
}
return null;
});
dialog.showAndWait().ifPresent(fractalName -> {
try {
gameController.readFractalFromFile(fractalName);
gameController.setChaosGameSteps(1000000);
gameController.setChaosCanvasSize(200, 200);
gameController.runTransformation();
} catch (Exception e) {
UserFeedback.showErrorPopup("Error", "Failed to load fractal: " + e.getMessage());
}
});
}
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ package edu.ntnu.idatt2003.mappevurderingprog2.views.Components; ...@@ -3,6 +3,7 @@ package edu.ntnu.idatt2003.mappevurderingprog2.views.Components;
import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController; import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController;
import edu.ntnu.idatt2003.mappevurderingprog2.models.Complex; import edu.ntnu.idatt2003.mappevurderingprog2.models.Complex;
import edu.ntnu.idatt2003.mappevurderingprog2.models.Vector2D; import edu.ntnu.idatt2003.mappevurderingprog2.models.Vector2D;
import edu.ntnu.idatt2003.mappevurderingprog2.models.chaos.ChaosGameFileHandler;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.ButtonType; import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog; import javafx.scene.control.Dialog;
...@@ -57,15 +58,15 @@ public class JuliaDialog { ...@@ -57,15 +58,15 @@ public class JuliaDialog {
grid.add(new Label("Imaginary Part:"), 0, 4); grid.add(new Label("Imaginary Part:"), 0, 4);
grid.add(imagField, 1, 4); grid.add(imagField, 1, 4);
Button editButton = new Button(isEditMode ? "Edit Fractal" : "Create Fractal"); Button editButton = new Button("Display Fractal");
editButton.setOnAction(event -> handleAction(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, realField, imagField)); editButton.setOnAction(event -> displayFractal(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, realField, imagField));
grid.add(editButton, 1, 5); grid.add(editButton, 1, 5);
dialog.getDialogPane().setContent(grid); dialog.getDialogPane().setContent(grid);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CLOSE); dialog.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
} }
private void handleAction(TextField stepsField, TextField minCoordsFieldX, TextField minCoordsFieldY, TextField maxCoordsFieldX, TextField maxCoordsFieldY, TextField realField, TextField imagField) { private void displayFractal(TextField stepsField, TextField minCoordsFieldX, TextField minCoordsFieldY, TextField maxCoordsFieldX, TextField maxCoordsFieldY, TextField realField, TextField imagField) {
if (stepsField.getText().isEmpty() || minCoordsFieldX.getText().isEmpty() || if (stepsField.getText().isEmpty() || minCoordsFieldX.getText().isEmpty() ||
minCoordsFieldY.getText().isEmpty() || maxCoordsFieldX.getText().isEmpty() || minCoordsFieldY.getText().isEmpty() || maxCoordsFieldX.getText().isEmpty() ||
maxCoordsFieldY.getText().isEmpty() || realField.getText().isEmpty() || maxCoordsFieldY.getText().isEmpty() || realField.getText().isEmpty() ||
......
...@@ -10,13 +10,13 @@ import javafx.scene.layout.VBox; ...@@ -10,13 +10,13 @@ import javafx.scene.layout.VBox;
public class Menu extends VBox { public class Menu extends VBox {
private ExistingFractalsMenu existingFractalsMenu; private ExistingFractalsMenu existingFractalsMenu;
private CreateFractalMenu createFractalMenu; private CreateFractalMenu createFractalMenu;
private EditFractalMenu editFractalMenu; private CurrentFractalMenu editFractalMenu;
private ExtraUserOptions extraUserOptions; private ExtraUserOptions extraUserOptions;
public Menu(View view, GameController gameController) { public Menu(View view, GameController gameController) {
existingFractalsMenu = new ExistingFractalsMenu(view, gameController); existingFractalsMenu = new ExistingFractalsMenu(view, gameController);
createFractalMenu = new CreateFractalMenu(view, gameController); createFractalMenu = new CreateFractalMenu(view, gameController);
editFractalMenu = new EditFractalMenu(view, gameController); editFractalMenu = new CurrentFractalMenu(view, gameController);
extraUserOptions = new ExtraUserOptions(view.getMainCanvas()); extraUserOptions = new ExtraUserOptions(view.getMainCanvas());
initializeMenu(); initializeMenu();
} }
......
Affine2D
0.0, 0.0
1.0, 1.0
0.000000, 0.000000, 0.000000, 0.160000, 0.0, 0.0
0.850000, 0.040000, -0.040000, 0.850000, 0.0, 1.6
0.200000, -0.260000, 0.230000, 0.220000, 0.0, 1.6
-0.150000, 0.280000, 0.260000, 0.240000, 0.0, 0.44
\ No newline at end of file
Julia
-1.6, -1.0
1.6, 1.0
-0.74543, 0.11301, -1
Affine2D
0.0, 0.0
1.0, 1.0
0.500000, 0.000000, 0.000000, 0.500000, 0.0, 0.0
0.500000, 0.000000, 0.000000, 0.500000, 0.5, 0.0
0.500000, 0.000000, 0.000000, 0.500000, 0.25, 0.5
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment