diff --git a/src/main/java/edu/ntnu/stud/chaosgame/controller/game/GuiButtonController.java b/src/main/java/edu/ntnu/stud/chaosgame/controller/game/GuiButtonController.java new file mode 100644 index 0000000000000000000000000000000000000000..df327c576675055242e3463782b6ea2bc42da0e6 --- /dev/null +++ b/src/main/java/edu/ntnu/stud/chaosgame/controller/game/GuiButtonController.java @@ -0,0 +1,92 @@ +package edu.ntnu.stud.chaosgame.controller.game; + +import edu.ntnu.stud.chaosgame.model.generators.ChaosGameDescriptionFactory; +import edu.ntnu.stud.chaosgame.view.ChaosCanvasToImageConverter; +import edu.ntnu.stud.chaosgame.view.ChaosGameGui; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.WritableImage; +import javafx.util.Duration; + +import java.util.Objects; + +public class GuiButtonController { + public ChaosGame game; + private ChaosGameGui gui; + private Timeline timeline; + private ChaosCanvas chaosCanvas; + private ChaosGameDescriptionFactory factory; + + + public GuiButtonController(ChaosGame game, ChaosGameGui gui) { + this.game = game; + this.gui = gui; + this.timeline = new Timeline(new KeyFrame(Duration.seconds(0.05), event -> this.drawChaosGame())); + this.timeline.setCycleCount(Timeline.INDEFINITE); + this.factory = new ChaosGameDescriptionFactory(); + this.chaosCanvas = new ChaosCanvas(1000, 1000, this.factory.getDescriptions().get(0).getMinCoords(), + this.factory.getDescriptions().get(0).getMaxCoords()); + } + + public void runGameSteps(int steps) { + game.runSteps(steps); + } + + public void drawChaosGame(){ + // Run the number of steps specified in text field, else 1000. + game.runSteps(!Objects.equals(gui.getStepCountTextField().getText(), "") ? + Integer.parseInt(gui.getStepCountTextField().getText()) : 1000); + + // Convert the canvas to either an image with coloured pixels based on intensity, or just black and white. + ChaosCanvasToImageConverter converter = new ChaosCanvasToImageConverter(chaosCanvas, + gui.getColorCheckBox().isSelected()); + WritableImage image = converter.getImage(); + gui.getCanvas().getGraphicsContext2D().drawImage(image, 0, 0); + gui.getImageView().setImage(image); + } + public void startGame() { + timeline.play(); + } + + public void stopGame() { + timeline.stop(); + } + public void clearImageView() { + GraphicsContext gc = gui.getCanvas().getGraphicsContext2D(); + gc.clearRect(0, 0, gui.getCanvas().getWidth(), gui.getCanvas().getHeight()); + gui.getImageView().setImage(null); + } + + + /** + * Update the description of the chaos game. + * TODO: this method may need to be changed depending on how we implement the UI. Rename to update? + * + * @param index the index of the new description in the list of factory descriptions. + * + */ + public void updateDescription(int index) { + // Stop the timeline + timeline.stop(); + + // Clear the ChaosCanvas + chaosCanvas.clearCanvas(); + gui.getCanvas().getGraphicsContext2D().clearRect(0, 0, gui.getCanvas().getGraphicsContext2D(). + getCanvas().getWidth(), gui.getCanvas().getGraphicsContext2D().getCanvas().getHeight()); + clearImageView(); + chaosCanvas.clearCanvas(); + + // Get the new description and create a new ChaosCanvas + ChaosGameDescription description = factory.getDescriptions().get(index); + chaosCanvas = new ChaosCanvas(1000, 1000, description.getMinCoords(), + description.getMaxCoords()); + + // Update the ChaosCanvas in the GUI + gui.updateCanvas(chaosCanvas); + + // Create a new ChaosGame with the updated description and ChaosCanvas + game = new ChaosGame(description, chaosCanvas); + game.setUseColor(gui.getColorCheckBox().isSelected()); + } +} \ No newline at end of file diff --git a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameGui.java b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameGui.java index baea5bfd55c60d9ef4debd535693bfe61392abfe..10984715373d809ba2c6aebe8dec00734b470d9a 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameGui.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameGui.java @@ -3,6 +3,7 @@ package edu.ntnu.stud.chaosgame.view; import edu.ntnu.stud.chaosgame.controller.game.ChaosCanvas; import edu.ntnu.stud.chaosgame.controller.game.ChaosGame; import edu.ntnu.stud.chaosgame.controller.game.ChaosGameDescription; +import edu.ntnu.stud.chaosgame.controller.game.GuiButtonController; import edu.ntnu.stud.chaosgame.controller.utility.Formatter; import edu.ntnu.stud.chaosgame.model.data.Vector2D; import edu.ntnu.stud.chaosgame.model.generators.ChaosGameDescriptionFactory; @@ -115,31 +116,33 @@ public class ChaosGameGui implements ChaosGameObserver { private CheckBox colorCheckBox; + private GuiButtonController controller; - public ChaosGameGui(Stage primaryStage) throws IOException { - this.initializeComponents(); +public ChaosGameGui(Stage primaryStage) throws IOException { + + + this.controller = new GuiButtonController(game, this); // Initialize controller here + this.initializeComponents(); + this.initializeGameComponents(); primaryStage.setTitle("Fractal Chaos Game"); primaryStage.setScene(scene); primaryStage.setOnShown(event -> this.imageView.requestFocus()); primaryStage.show(); - - } - +} /** * Initialize the components of the GUI. */ private void initializeComponents() { // Timeline - this.timeline = new Timeline(new KeyFrame(Duration.seconds(0.05), event -> this.drawChaosGame())); + //this.timeline = new Timeline(new KeyFrame(Duration.seconds(0.05), event -> controller.drawChaosGame())); this.initializeImageView(); // Side menu - //TEMPORARY CODE to test Chaos Games in GUI - this.initializeGameComponents(); + this.initializeMainButtons(); this.initializeFractalButtons(); @@ -153,9 +156,9 @@ public class ChaosGameGui implements ChaosGameObserver { */ private void initializeMainButtons() { this.startButton = new Button("Start"); - startButton.setOnAction(event -> timeline.play()); + startButton.setOnAction(event -> controller.startGame()); this.stopButton = new Button("Stop"); - stopButton.setOnAction(event -> timeline.stop()); + stopButton.setOnAction(event -> controller.stopGame()); this.newButton = new Button("New"); @@ -188,8 +191,8 @@ public class ChaosGameGui implements ChaosGameObserver { this.chaosCanvas = new ChaosCanvas(100, 100, this.description.getMinCoords(), this.description.getMaxCoords()); game = new ChaosGame(this.description, chaosCanvas); - } - + //controller.startGame(); // Start the game after it's created +} /** * Initialize components related to the image view and zoom function. */ @@ -208,7 +211,7 @@ public class ChaosGameGui implements ChaosGameObserver { /** * Color the entire image view white. */ - private void clearImageView() { + public void clearImageView() { GraphicsContext gc = canvas.getGraphicsContext2D(); gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); imageView.setImage(null); @@ -223,7 +226,7 @@ public class ChaosGameGui implements ChaosGameObserver { ToggleGroup group = new ToggleGroup(); this.sierpinskiRadioButton = new RadioButton("Sierpinski"); sierpinskiRadioButton.setToggleGroup(group); - sierpinskiRadioButton.setSelected(true); + //sierpinskiRadioButton.setSelected(true); this.barnsleyRadioButton = new RadioButton("Barnsley"); barnsleyRadioButton.setToggleGroup(group); this.juliaRadioButton = new RadioButton("Julia"); @@ -234,21 +237,21 @@ public class ChaosGameGui implements ChaosGameObserver { // Set action for Sierpinski radio button. sierpinskiRadioButton.setOnAction(event -> { - this.updateDescription(0); + controller.updateDescription(0); }); // Set action for Barnsley radio button. barnsleyRadioButton.setOnAction(event -> { - this.updateDescription(1); + controller.updateDescription(1); }); // Set action for Julia radio button. juliaRadioButton.setOnAction(event -> { - this.updateDescription(2); + controller.updateDescription(2); }); improvedBarnsleyButton.setOnAction(event -> { - this.updateDescription(3); + controller.updateDescription(3); }); // Load fractal file button @@ -382,7 +385,7 @@ public class ChaosGameGui implements ChaosGameObserver { */ private void initializeColorButtonHandler() { this.colorCheckBox.setOnAction(event -> { - game.setUseColor(colorCheckBox.isSelected()); + controller.game.setUseColor(colorCheckBox.isSelected()); this.clearImageView(); this.chaosCanvas.clearCanvas(); }); @@ -397,18 +400,6 @@ public class ChaosGameGui implements ChaosGameObserver { return this.chaosCanvas; } - public void drawChaosGame(){ - // Run the number of steps specified in text field, else 1000. - game.runSteps(!Objects.equals(this.stepCountTextField.getText(), "") ? - Integer.parseInt(this.stepCountTextField.getText()) : 1000); - - // Convert the canvas to either an image with coloured pixels based on intensity, or just black and white. - ChaosCanvasToImageConverter converter = new ChaosCanvasToImageConverter(this.chaosCanvas, - this.colorCheckBox.isSelected()); - WritableImage image = converter.getImage(); - this.canvas.getGraphicsContext2D().drawImage(image, 0, 0); - this.imageView.setImage(image); - } public int getWidth(){ return this.width; @@ -428,30 +419,8 @@ public class ChaosGameGui implements ChaosGameObserver { this.imageView.setImage(inputView); } - /** - * Update the description of the chaos game. - * TODO: this method may need to be changed depending on how we implement the UI. Rename to update? - * - * @param index the index of the new description in the list of factory descriptions. - * - */ - @Override - public void updateDescription(int index) { - timeline.stop(); - this.chaosCanvas.clearCanvas(); - this.canvas.getGraphicsContext2D().clearRect(0, 0, this.canvas.getGraphicsContext2D(). - getCanvas().getWidth(), this.canvas.getGraphicsContext2D().getCanvas().getHeight()); - this.clearImageView(); - this.chaosCanvas.clearCanvas(); - this.description = this.factory.getDescriptions().get(index); // Assuming the Sierpinski description is at index 0 - this.chaosCanvas = new ChaosCanvas(1000, 1000, this.description.getMinCoords(), - this.description.getMaxCoords()); - this.updateCanvas(this.chaosCanvas); - game = new ChaosGame(this.description, this.chaosCanvas); - game.setUseColor(this.colorCheckBox.isSelected()); - //this.game.setDescription(description); - } + /** * Update the canvas and set a new zoom factor for the image view based on the ratio @@ -477,7 +446,7 @@ public class ChaosGameGui implements ChaosGameObserver { this.clearImageView(); this.chaosCanvas.clearCanvas(); this.chaosCanvas.updateCoords(centreX, centreY, zoomLevel); - this.game.setCurrentPoint(new Vector2D(centreX, centreY)); + controller.game.setCurrentPoint(new Vector2D(centreX, centreY)); } /** @@ -488,8 +457,24 @@ public class ChaosGameGui implements ChaosGameObserver { */ @Override public void update(ChaosGame game) { - //drawChaosGame(); + controller.drawChaosGame(); + } + public TextField getStepCountTextField() { + return this.stepCountTextField; + } + + public CheckBox getColorCheckBox() { + return this.colorCheckBox; + } + + + + public Canvas getCanvas() { + return this.canvas; } + + + } diff --git a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameObserver.java b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameObserver.java index 5eb1f0888f1a289801c797e4f626a307b1857adc..90e8a3f1d3426a69aa7657b4dd01a0b1fd57ccd8 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameObserver.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameObserver.java @@ -10,13 +10,6 @@ import edu.ntnu.stud.chaosgame.controller.game.ChaosGameDescription; */ public interface ChaosGameObserver { - /** - * Perform update of the ChaosGameDescription. - * - * @param index the description's index in a list of descriptions. - */ - //void updateDescription(ChaosGameDescription description); - void updateDescription(int index); /** * Update the ChaosCanvas.