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.model.generators.ChaosGameDescriptionFactory; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Platform; import javafx.scene.Scene; import javafx.scene.control.ToggleGroup; import javafx.scene.control.RadioButton; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.image.PixelWriter; import javafx.scene.image.WritableImage; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.scene.control.Button; import javafx.util.Duration; import java.io.IOException; import java.util.concurrent.atomic.AtomicReference; public class ChaosGameGUIView { private int currentLine = 0; private PixelWriter pixelWriter; private ImageView imageView; private int width; private int height; private ChaosGame game; private final Timeline timeline; public ChaosGameGUIView(Stage primaryStage) throws IOException { this.timeline = new Timeline(new KeyFrame(Duration.seconds(0.05), event -> this.drawChaosGame())); imageView = new ImageView(); width = 1000; height = 1000; WritableImage writableImage = new WritableImage(width, height); pixelWriter = writableImage.getPixelWriter(); imageView.setImage(writableImage); VBox sideMenu = new VBox(); //TEMPORARY CODE to test Chaos Games in GUI ChaosGameDescriptionFactory factory = new ChaosGameDescriptionFactory(); AtomicReference<ChaosGameDescription> description = new AtomicReference<>(factory.getDescriptions().get(0)); ChaosCanvas canvas = new ChaosCanvas(1000, 1000, description.get().getMinCoords(), description.get().getMaxCoords()); game = new ChaosGame(description.get(), canvas); Button startButton = new Button("Start"); startButton.setOnAction(event -> timeline.play()); Button stopButton = new Button("Stop"); stopButton.setOnAction(event -> timeline.stop()); Button newButton = new Button("New"); newButton.setOnAction(event ->{ WritableImage newWritableImage = new WritableImage(width, height); setPixelWriter(newWritableImage.getPixelWriter()); setImageViewFromImage(newWritableImage); canvas.clearCanvas(); }); Button clearButton = new Button("Clear"); clearButton.setOnAction(event -> { getImageView().setImage(null); setCurrentLine(0); }); // Radio buttons for choosing fractal type ToggleGroup group = new ToggleGroup(); RadioButton sierpinskiRadioButton = new RadioButton("Sierpinski"); sierpinskiRadioButton.setToggleGroup(group); sierpinskiRadioButton.setSelected(true); RadioButton barnsleyRadioButton = new RadioButton("Barnsley"); barnsleyRadioButton.setToggleGroup(group); RadioButton juliaRadioButton = new RadioButton("Julia"); juliaRadioButton.setToggleGroup(group); AtomicReference<ChaosCanvas> canvasRef = new AtomicReference<>(canvas); sierpinskiRadioButton.setOnAction(event -> { timeline.stop(); canvasRef.get().clearCanvas(); WritableImage newWritableImage = new WritableImage(width, height); setPixelWriter(newWritableImage.getPixelWriter()); setImageViewFromImage(newWritableImage); canvas.clearCanvas(); description.set(factory.getDescriptions().get(0)); // Assuming the Sierpinski description is at index 0 canvasRef.set(new ChaosCanvas(1000, 1000, description.get().getMinCoords(), description.get().getMaxCoords())); game = new ChaosGame(description.get(), canvasRef.get()); }); barnsleyRadioButton.setOnAction(event -> { timeline.stop(); canvasRef.get().clearCanvas(); WritableImage newWritableImage = new WritableImage(width, height); setPixelWriter(newWritableImage.getPixelWriter()); setImageViewFromImage(newWritableImage); canvas.clearCanvas(); description.set(factory.getDescriptions().get(1)); // Assuming the Sierpinski description is at index 0 canvasRef.set(new ChaosCanvas(1000, 1000, description.get().getMinCoords(), description.get().getMaxCoords())); game = new ChaosGame(description.get(), canvasRef.get()); }); juliaRadioButton.setOnAction(event -> { timeline.stop(); canvasRef.get().clearCanvas(); WritableImage newWritableImage = new WritableImage(width, height); setPixelWriter(newWritableImage.getPixelWriter()); setImageViewFromImage(newWritableImage); canvas.clearCanvas(); description.set(factory.getDescriptions().get(2)); // Assuming the Sierpinski description is at index 0 canvasRef.set(new ChaosCanvas(1000, 1000, description.get().getMinCoords(), description.get().getMaxCoords())); game = new ChaosGame(description.get(), canvasRef.get()); }); // Quit button Button quitButton = new Button("Quit"); quitButton.setOnAction(event -> Platform.exit()); // Add basic control buttons sideMenu.getChildren().addAll(startButton,stopButton,newButton,clearButton); // Add fractal radio buttons sideMenu.getChildren().addAll(sierpinskiRadioButton, barnsleyRadioButton, juliaRadioButton); // Add quit button sideMenu.getChildren().add(quitButton); BorderPane borderPane = new BorderPane(); borderPane.setCenter(imageView); borderPane.setRight(sideMenu); Scene scene = new Scene(borderPane,1700,1000); primaryStage.setTitle("Fractal Chaos Game"); primaryStage.setScene(scene); primaryStage.show(); } public void drawChaosGame(){ ChaosCanvas canvas = game.getCanvas(); game.runSteps(100000); // Test implementation for drawing fractals int[][] betaArray = canvas.getCanvasArray(); for (int i = 0; i < canvas.getWidth(); i++) { for (int j = 0; j < canvas.getHeight(); j++) { if (betaArray[i][j] == 1) { pixelWriter.setColor(j,i,Color.BLACK); } } } } public int getWidth(){ return this.width; } public int getHeight(){ return this.height; } public ImageView getImageView(){ return this.imageView; } public void setCurrentLine(int currentLine) { this.currentLine = currentLine; } public void setPixelWriter(PixelWriter pixelWriter) { this.pixelWriter = pixelWriter; } public void setImageViewFromImage(Image inputView) { this.imageView.setImage(inputView); } }