Skip to content
Snippets Groups Projects
Commit 933527ac authored by Håvard Daleng's avatar Håvard Daleng
Browse files

Added documentation to new modification popup classes.

parent 7c33efc8
No related branches found
No related tags found
No related merge requests found
......@@ -181,16 +181,19 @@ public class ChaosGame {
/**
* If the point is out of bounds, iterate until it is within bounds.
* If the
*
* @param point the starting point.
* @return the resulting valid point within bounds.
*/
public Vector2D findValidPoint(Vector2D point) {
if (!this.canvas.isPointInCanvasRange(point)) {
while (!this.canvas.isPointInCanvasRange(point)) {
int i = 0;
while (!this.canvas.isPointInCanvasRange(point) && i < 100) {
int j = this.random.nextInt(this.numOfTransforms);
System.out.println("Before transform: " + point.getX0() + " " + point.getX1()); // Test
point = this.description.getTransforms().get(j).transform(currentPoint);
i++;
}
}
return point;
......
......@@ -105,8 +105,6 @@ public class GuiButtonController {
initializeModifyGameButtonHandler();
initializeDescriptionComboBox();
initializeSaveImageButtons();
}
private void initializeModifyGameButtonHandler() {
......
......@@ -13,122 +13,230 @@ import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
/**
* Abstract class for popups.
*/
public abstract class AbstractPopup {
protected Stage popupModifyStage;
protected VBox layout;
protected Scene scene;
protected TextField nameTextField;
protected TextField minXTextField;
protected TextField minYTextField;
protected TextField maxXTextField;
protected TextField maxYTextField;
protected Button updateButton;
protected VBox bottomLayout;
public AbstractPopup(VBox layout) {
this.popupModifyStage = new Stage();
this.popupModifyStage.initModality(Modality.APPLICATION_MODAL);
this.popupModifyStage.setAlwaysOnTop(true);
this.layout = layout;
this.scene = new Scene(layout);
this.popupModifyStage.setScene(scene);
initializeCommonElements();
}
private void initializeCommonElements() {
nameTextField = new TextField();
HBox nameBox = new HBox(new Label("Name: "), nameTextField);
minXTextField = createNumericTextField();
minYTextField = createNumericTextField();
maxXTextField = createNumericTextField();
maxYTextField = createNumericTextField();
updateButton = new Button("Update");
minXTextField.setPrefWidth(50);
minYTextField.setPrefWidth(50);
maxXTextField.setPrefWidth(50);
maxYTextField.setPrefWidth(50);
GridPane minCoordsGrid = new GridPane();
minCoordsGrid.setHgap(10);
minCoordsGrid.add(new Label("Min Coordinates: "), 0, 0);
minCoordsGrid.add(minXTextField, 1, 0);
minCoordsGrid.add(minYTextField, 2, 0);
GridPane maxCoordsGrid = new GridPane();
maxCoordsGrid.setHgap(10);
maxCoordsGrid.add(new Label("Max Coordinates: "), 0, 0);
maxCoordsGrid.add(maxXTextField, 1, 0);
maxCoordsGrid.add(maxYTextField, 2, 0);
bottomLayout = new VBox(10, minCoordsGrid, maxCoordsGrid, updateButton);
bottomLayout.setAlignment(Pos.CENTER); // Center align the children
bottomLayout.setPadding(new Insets(10));
VBox.setVgrow(bottomLayout, Priority.ALWAYS);
layout.getChildren().add(0, nameBox);
/**
* The stage for the popup.
*/
protected Stage popupModifyStage;
/**
* The layout of the popup.
*/
protected VBox layout;
/**
* The scene of the popup.
*/
protected Scene scene;
/**
* The text field for the name.
*/
protected TextField nameTextField;
/**
* The text field for the minimum x value.
*/
protected TextField minXTextField;
/**
* The text field for the minimum y value.
*/
protected TextField minYTextField;
/**
* The text field for the maximum x value.
*/
protected TextField maxXTextField;
/**
* The text field for the maximum y value.
*/
protected TextField maxYTextField;
/**
* The update button.
*/
protected Button updateButton;
/**
* The layout for the bottom part of the popup.
*/
protected VBox bottomLayout;
/**
* Constructor for AbstractPopup.
*
* @param layout the layout of the popup.
*/
public AbstractPopup(VBox layout) {
this.popupModifyStage = new Stage();
this.popupModifyStage.initModality(Modality.APPLICATION_MODAL);
this.popupModifyStage.setAlwaysOnTop(true);
this.layout = layout;
this.scene = new Scene(layout);
this.popupModifyStage.setScene(scene);
initializeCommonElements();
}
/**
* Initialize the common elements of the popup.
*/
private void initializeCommonElements() {
nameTextField = new TextField();
HBox nameBox = new HBox(new Label("Name: "), nameTextField);
minXTextField = createNumericTextField();
minYTextField = createNumericTextField();
maxXTextField = createNumericTextField();
maxYTextField = createNumericTextField();
updateButton = new Button("Update");
minXTextField.setPrefWidth(50);
minYTextField.setPrefWidth(50);
maxXTextField.setPrefWidth(50);
maxYTextField.setPrefWidth(50);
GridPane minCoordsGrid = new GridPane();
minCoordsGrid.setHgap(10);
minCoordsGrid.add(new Label("Min Coordinates: "), 0, 0);
minCoordsGrid.add(minXTextField, 1, 0);
minCoordsGrid.add(minYTextField, 2, 0);
GridPane maxCoordsGrid = new GridPane();
maxCoordsGrid.setHgap(10);
maxCoordsGrid.add(new Label("Max Coordinates: "), 0, 0);
maxCoordsGrid.add(maxXTextField, 1, 0);
maxCoordsGrid.add(maxYTextField, 2, 0);
bottomLayout = new VBox(10, minCoordsGrid, maxCoordsGrid, updateButton);
bottomLayout.setAlignment(Pos.CENTER); // Center align the children
bottomLayout.setPadding(new Insets(10));
VBox.setVgrow(bottomLayout, Priority.ALWAYS);
layout.getChildren().add(0, nameBox);
}
protected TextField createNumericTextField() {
TextField textField = new TextField();
textField.textProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue.matches("-?\\d*(\\.\\d*)?")) {
textField.setText(oldValue);
}
});
return textField;
}
public static VBox initializeLayout() {
VBox layout = new VBox();
layout.setPadding(new Insets(10));
layout.setSpacing(10);
return layout;
}
public VBox getLayout() {
return layout;
}
public void setLayout(VBox layout) {
this.layout = layout;
this.scene.setRoot(layout);
}
public void display() {
popupModifyStage.show();
}
public Stage getPopupModifyStage() {
return popupModifyStage;
}
public TextField getNameTextField() {
return nameTextField;
}
public TextField getMinXTextField() {
return minXTextField;
}
public TextField getMinYTextField() {
return minYTextField;
}
public TextField getMaxXTextField() {
return maxXTextField;
}
public TextField getMaxYTextField() {
return maxYTextField;
}
public Button getUpdateButton() {
return updateButton;
}
/**
* Create a numeric text field.
*
* @return the numeric text field.
*/
protected TextField createNumericTextField() {
TextField textField = new TextField();
textField.textProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue.matches("-?\\d*(\\.\\d*)?")) { // TODO: replace with Formatter
textField.setText(oldValue);
}
});
return textField;
}
/**
* Initialize the layout of the popup.
*
* @return the layout of the popup.
*/
public static VBox initializeLayout() {
VBox layout = new VBox();
layout.setPadding(new Insets(10));
layout.setSpacing(10);
return layout;
}
/**
* Get the layout of the popup.
*
* @return the layout of the popup.
*/
public VBox getLayout() {
return layout;
}
/**
* Set the layout of the popup.
*
* @param layout the layout to set.
*/
public void setLayout(VBox layout) {
this.layout = layout;
this.scene.setRoot(layout);
}
/**
* Display the popup.
*/
public void display() {
popupModifyStage.show();
}
/**
* Get the stage of the popup.
*
* @return the stage of the popup.
*/
public Stage getPopupModifyStage() {
return popupModifyStage;
}
/**
* Get the text field for the name.
*
* @return the text field for the name.
*/
public TextField getNameTextField() {
return nameTextField;
}
/**
* Get the text field for the minimum x value.
*
* @return the text field for the minimum x value.
*/
public TextField getMinXTextField() {
return minXTextField;
}
/**
* Get the text field for the minimum y value.
*
* @return the text field for the minimum y value.
*/
public TextField getMinYTextField() {
return minYTextField;
}
/**
* Get the text field for the maximum x value.
*
* @return the text field for the maximum x value.
*/
public TextField getMaxXTextField() {
return maxXTextField;
}
/**
* Get the text field for the maximum y value.
*
* @return the text field for the maximum y value.
*/
public TextField getMaxYTextField() {
return maxYTextField;
}
/**
* Get the update button.
*
* @return the update button.
*/
public Button getUpdateButton() {
return updateButton;
}
}
......@@ -10,97 +10,127 @@ import edu.ntnu.stud.chaosgame.model.data.Vector2D;
import edu.ntnu.stud.chaosgame.model.transformations.AffineTransform2D;
import edu.ntnu.stud.chaosgame.model.game.ChaosGameDescription;
/**
* Popup for modifying the Affine2D transformations.
*/
public class Affine2DPopup extends AbstractPopup {
private TextField[][] matrixTextFields;
private TextField[] vectorTextFields;
public Affine2DPopup(ChaosGameDescription gameDescription) {
super(AbstractPopup.initializeLayout());
// Initialize the TextFields for matrices and vectors based on the number of transforms
int transformCount = Math.min(gameDescription.getTransforms().size(), 4); // Ensure maximum of 4 transformations
matrixTextFields = new TextField[transformCount][4];
vectorTextFields = new TextField[transformCount * 2];
for (int i = 0; i < transformCount; i++) {
for (int j = 0; j < 4; j++) {
matrixTextFields[i][j] = createNumericTextField();
matrixTextFields[i][j].setPrefWidth(50);
}
vectorTextFields[2 * i] = createNumericTextField();
vectorTextFields[2 * i].setPrefWidth(50);
vectorTextFields[2 * i + 1] = createNumericTextField();
vectorTextFields[2 * i + 1].setPrefWidth(50);
}
// Add labels and text fields to GridPane
VBox matrixVBox = new VBox(10);
for (int i = 0; i < transformCount; i++) {
GridPane matrixGridPane = new GridPane();
matrixGridPane.setHgap(10);
matrixGridPane.setVgap(10);
matrixGridPane.setPadding(new Insets(10));
matrixGridPane.add(new Label("Matrix " + (i + 1) + " Row 1: "), 0, 0);
matrixGridPane.add(matrixTextFields[i][0], 1, 0);
matrixGridPane.add(matrixTextFields[i][1], 2, 0);
matrixGridPane.add(new Label("Matrix " + (i + 1) + " Row 2: "), 0, 1);
matrixGridPane.add(matrixTextFields[i][2], 1, 1);
matrixGridPane.add(matrixTextFields[i][3], 2, 1);
matrixGridPane.add(new Label("Vector " + (i + 1) + ": "), 0, 2);
matrixGridPane.add(vectorTextFields[2 * i], 1, 2);
matrixGridPane.add(vectorTextFields[2 * i + 1], 2, 2);
matrixVBox.getChildren().add(matrixGridPane);
}
// Add the GridPanes to the layout
layout.getChildren().addAll(matrixVBox);
// Add bottomLayout to the end
layout.getChildren().add(bottomLayout);
// Set the title for the popup window
popupModifyStage.setTitle("Affine2D Modification");
// Display the current values from ChaosGameDescription
displayCurrentValues(gameDescription);
// Display the popup
display();
}
private void displayCurrentValues(ChaosGameDescription gameDescription) {
if (gameDescription != null) {
nameTextField.setText(gameDescription.getName());
minXTextField.setText(String.valueOf(gameDescription.getMinCoords().getX0()));
minYTextField.setText(String.valueOf(gameDescription.getMinCoords().getX1()));
maxXTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX0()));
maxYTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX1()));
int transformCount = Math.min(gameDescription.getTransforms().size(), 4);
for (int i = 0; i < transformCount; i++) {
AffineTransform2D transform = (AffineTransform2D) gameDescription.getTransforms().get(i);
Matrix2x2 matrix = transform.getMatrix();
Vector2D vector = transform.getVector();
matrixTextFields[i][0].setText(String.valueOf(matrix.getA00()));
matrixTextFields[i][1].setText(String.valueOf(matrix.getA01()));
matrixTextFields[i][2].setText(String.valueOf(matrix.getA10()));
matrixTextFields[i][3].setText(String.valueOf(matrix.getA11()));
vectorTextFields[2 * i].setText(String.valueOf(vector.getX0()));
vectorTextFields[2 * i + 1].setText(String.valueOf(vector.getX1()));
}
}
}
// Getters for the text fields
public TextField[][] getMatrixTextFields() {
return matrixTextFields;
/**
* The text fields for the matrix, represented as a 2D array.
*/
private TextField[][] matrixTextFields;
/**
* The text fields for the vector, represented as a 1D array.
*/
private TextField[] vectorTextFields;
/**
* Constructor for the Affine2DPopup.
*
* @param gameDescription the chaos game description to be modified.
*/
public Affine2DPopup(ChaosGameDescription gameDescription) {
super(AbstractPopup.initializeLayout());
// Initialize the TextFields for matrices and vectors based on the number of transforms
int transformCount = Math.min(gameDescription.getTransforms().size(), 4); // Ensure maximum of 4 transformations
matrixTextFields = new TextField[transformCount][4];
vectorTextFields = new TextField[transformCount * 2];
for (int i = 0; i < transformCount; i++) {
for (int j = 0; j < 4; j++) {
matrixTextFields[i][j] = createNumericTextField();
matrixTextFields[i][j].setPrefWidth(50);
}
vectorTextFields[2 * i] = createNumericTextField();
vectorTextFields[2 * i].setPrefWidth(50);
vectorTextFields[2 * i + 1] = createNumericTextField();
vectorTextFields[2 * i + 1].setPrefWidth(50);
}
public TextField[] getVectorTextFields() {
return vectorTextFields;
// Add labels and text fields to GridPane
VBox matrixVBox = new VBox(10);
for (int i = 0; i < transformCount; i++) {
GridPane matrixGridPane = new GridPane();
matrixGridPane.setHgap(10);
matrixGridPane.setVgap(10);
matrixGridPane.setPadding(new Insets(10));
matrixGridPane.add(new Label("Matrix " + (i + 1) + " Row 1: "), 0, 0);
matrixGridPane.add(matrixTextFields[i][0], 1, 0);
matrixGridPane.add(matrixTextFields[i][1], 2, 0);
matrixGridPane.add(new Label("Matrix " + (i + 1) + " Row 2: "), 0, 1);
matrixGridPane.add(matrixTextFields[i][2], 1, 1);
matrixGridPane.add(matrixTextFields[i][3], 2, 1);
matrixGridPane.add(new Label("Vector " + (i + 1) + ": "), 0, 2);
matrixGridPane.add(vectorTextFields[2 * i], 1, 2);
matrixGridPane.add(vectorTextFields[2 * i + 1], 2, 2);
matrixVBox.getChildren().add(matrixGridPane);
}
// Add the GridPanes to the layout
layout.getChildren().addAll(matrixVBox);
// Add bottomLayout to the end
layout.getChildren().add(bottomLayout);
// Set the title for the popup window
popupModifyStage.setTitle("Affine2D Modification");
// Display the current values from ChaosGameDescription
displayCurrentValues(gameDescription);
// Display the popup
display();
}
/**
* Display the current values from the ChaosGameDescription in the text fields.
*
* @param gameDescription the ChaosGameDescription to display values from.
*/
private void displayCurrentValues(ChaosGameDescription gameDescription) {
if (gameDescription != null) {
nameTextField.setText(gameDescription.getName());
minXTextField.setText(String.valueOf(gameDescription.getMinCoords().getX0()));
minYTextField.setText(String.valueOf(gameDescription.getMinCoords().getX1()));
maxXTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX0()));
maxYTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX1()));
int transformCount = Math.min(gameDescription.getTransforms().size(), 4);
for (int i = 0; i < transformCount; i++) {
AffineTransform2D transform = (AffineTransform2D) gameDescription.getTransforms().get(i);
Matrix2x2 matrix = transform.getMatrix();
Vector2D vector = transform.getVector();
matrixTextFields[i][0].setText(String.valueOf(matrix.getA00()));
matrixTextFields[i][1].setText(String.valueOf(matrix.getA01()));
matrixTextFields[i][2].setText(String.valueOf(matrix.getA10()));
matrixTextFields[i][3].setText(String.valueOf(matrix.getA11()));
vectorTextFields[2 * i].setText(String.valueOf(vector.getX0()));
vectorTextFields[2 * i + 1].setText(String.valueOf(vector.getX1()));
}
}
}
/**
* Get the matrix text fields.
*
* @return the matrix text fields.
*/
public TextField[][] getMatrixTextFields() {
return matrixTextFields;
}
/**
* Get the vector text fields.
*
* @return the vector text fields.
*/
public TextField[] getVectorTextFields() {
return vectorTextFields;
}
}
......@@ -8,68 +8,98 @@ import edu.ntnu.stud.chaosgame.model.data.Complex;
import edu.ntnu.stud.chaosgame.model.game.ChaosGameDescription;
import edu.ntnu.stud.chaosgame.model.transformations.JuliaTransform;
/**
* Popup for modifying the Julia set.
*/
public class JuliaPopup extends AbstractPopup {
private TextField realPartTextField;
private TextField imagPartTextField;
public JuliaPopup(ChaosGameDescription gameDescription) {
super(AbstractPopup.initializeLayout());
// Initialize the TextFields
realPartTextField = createNumericTextField();
imagPartTextField = createNumericTextField();
// Add labels and text fields to a GridPane for better formatting
GridPane complexNumberGridPane = new GridPane();
complexNumberGridPane.setHgap(10);
complexNumberGridPane.setVgap(10);
complexNumberGridPane.setPadding(new Insets(10));
complexNumberGridPane.add(new Label("Real Part: "), 0, 0);
complexNumberGridPane.add(realPartTextField, 1, 0);
complexNumberGridPane.add(new Label("Imaginary Part: "), 0, 1);
complexNumberGridPane.add(imagPartTextField, 1, 1);
// Add the GridPane to the layout
layout.getChildren().add(complexNumberGridPane);
// Add bottomLayout to the end
layout.getChildren().add(bottomLayout);
// Set the title for the popup window
popupModifyStage.setTitle("Julia Set Modification");
// Display the current values from ChaosGameDescription
displayCurrentValues(gameDescription);
// Display the popup
display();
}
private void displayCurrentValues(ChaosGameDescription gameDescription) {
if (gameDescription != null) {
nameTextField.setText(gameDescription.getName());
minXTextField.setText(String.valueOf(gameDescription.getMinCoords().getX0()));
minYTextField.setText(String.valueOf(gameDescription.getMinCoords().getX1()));
maxXTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX0()));
maxYTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX1()));
JuliaTransform transform = (JuliaTransform) gameDescription.getTransforms().get(0);
Complex complexNumber = transform.getC1();
realPartTextField.setText(String.valueOf(complexNumber.getX0()));
imagPartTextField.setText(String.valueOf(complexNumber.getX1()));
}
}
// Getters for the text fields
public TextField getRealPartTextField() {
return realPartTextField;
}
public TextField getImagPartTextField() {
return imagPartTextField;
/**
* The text field for the real part of the complex number.
*/
private final TextField realPartTextField;
/**
* The text field for the imaginary part of the complex number.
*/
private final TextField imagPartTextField;
/**
* Constructor for the JuliaPopup.
*
* @param gameDescription the chaos game description to be modified.
*/
public JuliaPopup(ChaosGameDescription gameDescription) {
super(AbstractPopup.initializeLayout());
// Initialize the TextFields
realPartTextField = createNumericTextField();
imagPartTextField = createNumericTextField();
// Add labels and text fields to a GridPane for better formatting
GridPane complexNumberGridPane = new GridPane();
complexNumberGridPane.setHgap(10);
complexNumberGridPane.setVgap(10);
complexNumberGridPane.setPadding(new Insets(10));
complexNumberGridPane.add(new Label("Real Part: "), 0, 0);
complexNumberGridPane.add(realPartTextField, 1, 0);
complexNumberGridPane.add(new Label("Imaginary Part: "), 0, 1);
complexNumberGridPane.add(imagPartTextField, 1, 1);
// Add the GridPane to the layout
layout.getChildren().add(complexNumberGridPane);
// Add bottomLayout to the end
layout.getChildren().add(bottomLayout);
// Set the title for the popup window
popupModifyStage.setTitle("Julia Set Modification");
// Display the current values from ChaosGameDescription
displayCurrentValues(gameDescription);
// Display the popup
display();
}
/**
* Display the current values from the ChaosGameDescription.
*
* @param gameDescription the chaos game description to be modified.
*/
private void displayCurrentValues(ChaosGameDescription gameDescription) {
if (gameDescription != null) {
nameTextField.setText(gameDescription.getName());
minXTextField.setText(String.valueOf(gameDescription.getMinCoords().getX0()));
minYTextField.setText(String.valueOf(gameDescription.getMinCoords().getX1()));
maxXTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX0()));
maxYTextField.setText(String.valueOf(gameDescription.getMaxCoords().getX1()));
JuliaTransform transform = (JuliaTransform) gameDescription.getTransforms().get(0);
Complex complexNumber = transform.getC1();
realPartTextField.setText(String.valueOf(complexNumber.getX0()));
imagPartTextField.setText(String.valueOf(complexNumber.getX1()));
}
}
/**
* Get the real part text field.
*
* @return the real part text field.
*/
public TextField getRealPartTextField() {
return realPartTextField;
}
/**
* Get the imaginary part text field.
*
* @return the imaginary part text field.
*/
public TextField getImagPartTextField() {
return imagPartTextField;
}
}
Affine2D
Heighway-Dragon
-1.0, -1.0
1.5, 1.5
0.6, -0.5, 0.5, 0.5, 0.0, 0.0
-0.5, -0.5, 0.6, -0.6, 1.0, 0.0
......@@ -2,4 +2,4 @@ Julia
Julia2
-1.6, -1.0
1.6, 1.0
-0.4, 0.8
-0.8, 0.8
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment