diff --git a/.idea/google-java-format.xml b/.idea/google-java-format.xml index 2aa056da349dddd834c2c648fc49c936f390dbfc..8b57f4527ab2bb586db85ec1471ea7926cee6c05 100644 --- a/.idea/google-java-format.xml +++ b/.idea/google-java-format.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="GoogleJavaFormatSettings"> - <option name="enabled" value="false" /> + <option name="enabled" value="true" /> </component> </project> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 7ddfc9ed476345b09db3e8fdf464a62bb2ccfa9b..574de4568e21706c1ac832f7025a60df46d8ae69 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -8,5 +8,6 @@ </component> <component name="VcsDirectoryMappings"> <mapping directory="" vcs="Git" /> + <mapping directory="$PROJECT_DIR$/idatt2003" vcs="Git" /> </component> </project> \ No newline at end of file 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 index d1a1b2e93e5ba440e0701de7db53377dd49176c8..95fe31d35a5ca12f4bdbba0d87b50c5ac5621600 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/controller/game/GuiButtonController.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/controller/game/GuiButtonController.java @@ -8,284 +8,213 @@ import edu.ntnu.stud.chaosgame.model.generators.ChaosGameDescriptionFactory; import edu.ntnu.stud.chaosgame.model.transformations.JuliaTransform; import edu.ntnu.stud.chaosgame.view.ChaosCanvasToImageConverter; import edu.ntnu.stud.chaosgame.view.ChaosGameGui; +import edu.ntnu.stud.chaosgame.view.GuiButtonObserver; import edu.ntnu.stud.chaosgame.view.modificationpopups.Affine2DPopup; import edu.ntnu.stud.chaosgame.view.modificationpopups.JuliaPopup; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Platform; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; import javafx.scene.canvas.GraphicsContext; import javafx.scene.control.ComboBox; import javafx.scene.image.PixelReader; import javafx.scene.image.WritableImage; import javafx.scene.paint.Color; -import javafx.stage.Popup; -import javafx.util.Duration; import javafx.stage.FileChooser; +import javafx.util.Duration; import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; /** - * Controller class for the GUI buttons, responsible for handling their functionality. + * Controller class for handling GUI button actions. + * It notifies registered observers when a button is pressed. */ public class GuiButtonController { + private final ChaosGameGui gui; + private final Timeline timeline; + private final PopupButtonController popupButtonController; + private final List<GuiButtonObserver> observers = new ArrayList<>(); + private final ChaosGameFileHandler fileHandler; + private ChaosGame game; + private ChaosGameDescriptionFactory factory; + private ChaosCanvas chaosCanvas; + private final String currentImagePath = System.getProperty("user.home"); + private int stepCounter = 0; /** - * The file handler for the controller. + * Constructs a GuiButtonController with the given game and GUI. + * + * @param game the Chaos Game model. + * @param gui the Chaos Game GUI. */ - private ChaosGameFileHandler fileHandler; + 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()); + this.fileHandler = new ChaosGameFileHandler(); + this.popupButtonController = new PopupButtonController(); - /** - * The chaos game for the controller. - */ - public ChaosGame game; + addObserver(gui); - /** - * The GUI for the controller. - */ - private ChaosGameGui gui; + gui.getStartButton().setOnAction(event -> notifyStartButtonPressed()); + gui.getStopButton().setOnAction(event -> notifyStopButtonPressed()); + gui.getClearButton().setOnAction(event -> notifyClearButtonPressed()); + gui.getQuitButton().setOnAction(event -> notifyQuitButtonPressed()); + gui.getSaveImageButton().setOnAction(event -> notifySaveImageButtonPressed()); + gui.getLoadFractalFromFileButton().setOnAction(event -> notifyLoadFractalFromFileButtonPressed()); + gui.getWriteToFileButton().setOnAction(event -> notifyWriteToFileButtonPressed()); + gui.getModifyGameButton().setOnAction(event -> notifyModifyGameButtonPressed()); - /** - * The timeline for the controller. - */ - private Timeline timeline; + initializeDescriptionComboBox(); + } /** - * The ChaosCanvas for the controller. + * Adds an observer to the list of observers. + * + * @param observer the observer to add. */ - private ChaosCanvas chaosCanvas; + public void addObserver(GuiButtonObserver observer) { + observers.add(observer); + } - /** - * The factory for the ChaosGameDescriptions. - */ - private ChaosGameDescriptionFactory factory; /** - * The controller which assigns functionality to the popup-window + * Notifies all observers that the start button has been pressed. */ - private PopupButtonController popupButtonController; + private void notifyStartButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onStartButtonPressed(); + } + } /** - * Default image save path + * Notifies all observers that the stop button has been pressed. */ - private String currentImagePath = System.getProperty("user.home"); + private void notifyStopButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onStopButtonPressed(); + } + } /** - * The step counter for the controller. + * Notifies all observers that the clear button has been pressed. */ - private int stepCounter = 0; - + private void notifyClearButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onClearButtonPressed(); + } + } - /** - * Basic constructor for the GuiButtonController. - * - * @param game the chaos game. - * @param gui the GUI. + /** + * Notifies all observers that the quit button has been pressed. */ - 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()); - initializeMainButtons(); - this.fileHandler = new ChaosGameFileHandler(); - this.popupButtonController = new PopupButtonController(); - initializeLoadFractalFromFileButtonHandler(); - initializeWriteToFileButtonHandler(); - initializeModifyGameButtonHandler(); - initializeDescriptionComboBox(); - initializeSaveImageButtons(); + private void notifyQuitButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onQuitButtonPressed(); } + } /** - * Initialize the modify game button handler. + * Notifies all observers that the save image button has been pressed. */ - private void initializeModifyGameButtonHandler() { - gui.getModifyGameButton().setOnAction(e -> { - ChaosGameDescription description = game.getDescription(); - if (description.getTransforms().get(0) instanceof JuliaTransform) { - JuliaPopup juliaPopup = new JuliaPopup(description); - juliaPopup.getPopupModifyStage().setUserData(this); - popupButtonController.handleUpdateButton(juliaPopup); - juliaPopup.display(); - } else { - Affine2DPopup affine2DPopup = new Affine2DPopup(description); - affine2DPopup.getPopupModifyStage().setUserData(this); - popupButtonController.handleUpdateButton(affine2DPopup); - affine2DPopup.display(); - } - }); + private void notifySaveImageButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onSaveImageButtonPressed(); + } } /** - * Initialize the description combo box. + * Notifies all observers that the load fractal from file button has been pressed. */ - private void initializeDescriptionComboBox() { - ComboBox<String> descriptionComboBox = gui.getDescriptionComboBox(); - - descriptionComboBox.setOnShowing(event -> updateDescriptionComboBox()); - - descriptionComboBox.getSelectionModel().selectedItemProperty() - .addListener((observable, oldValue, newValue) -> { - for (int i = 0; i < factory.getDescriptions().size(); i++) { - ChaosGameDescription description = factory.getDescriptions().get(i); - if (description.getName().equals(newValue)) { - updateDescription(i); - break; - } - } - - }); + private void notifyLoadFractalFromFileButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onLoadFractalFromFileButtonPressed(); } + } - /* - * Update the description combo box. - */ - public void updateDescriptionComboBox() { - factory = new ChaosGameDescriptionFactory(); - ComboBox<String> descriptionComboBox = gui.getDescriptionComboBox(); - descriptionComboBox.getItems().clear(); - for (ChaosGameDescription description : factory.getDescriptions()) { - descriptionComboBox.getItems().add(description.getName()); - } + /** + * Notifies all observers that the write to file button has been pressed. + */ + private void notifyWriteToFileButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onWriteToFileButtonPressed(); } + } /** - * Initialize the save image buttons. + * Notifies all observers that the modify game button has been pressed. */ - private void initializeSaveImageButtons(){ - gui.getSaveImageButton().setOnAction(event -> saveImage()); + private void notifyModifyGameButtonPressed() { + for (GuiButtonObserver observer : observers) { + observer.onModifyGameButtonPressed(); } + } /** - * Initialize the load fractal from file button handler. + * Starts the game. */ - private void initializeLoadFractalFromFileButtonHandler() { - gui.getLoadFractalFromFileButton().setOnAction(event -> { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Open Fractal File"); - fileChooser.getExtensionFilters().add( - new FileChooser.ExtensionFilter("Text Files", "*.txt")); - File selectedFile = fileChooser.showOpenDialog(gui.getStage()); - if (selectedFile != null) { - Path dest = Paths.get("src/main/resources/descriptions/saved_descriptions/" - + selectedFile.getName()); - try { - Files.copy(selectedFile.toPath(), dest); - // Refresh the list of descriptions - factory = new ChaosGameDescriptionFactory(); - } catch (IOException e) { - PopupManager.displayError("Error", "Could not load the fractal from file."); - } - } - }); + public void startGame() { + timeline.play(); + gui.getStartButton().setText("Start"); } /** - * Initialize the write to file button handler. + * Stops the game. */ - private void initializeWriteToFileButtonHandler() { - gui.getWriteToFileButton().setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - // Create a FileChooser object - FileChooser fileChooser = new FileChooser(); - - // Set the title of the FileChooser dialog - fileChooser.setTitle("Save File"); - - // Set the initial directory of the FileChooser - fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); - - // Set the extension filter - fileChooser.getExtensionFilters().addAll( - new FileChooser.ExtensionFilter("Text Files", "*.txt"), - new FileChooser.ExtensionFilter("All Files", "*.*") - ); - - // Show the save file dialog and get the selected file - File file = fileChooser.showSaveDialog(gui.getStage()); - - if (file != null) { - try { - // Create a ChaosGameDescription object - ChaosGameDescription description = game.getDescription(); - - // Call the writeToFile method - fileHandler.writeToFile(description, file.getPath()); - } catch (IOException e) { - // Handle the exception - PopupManager.displayError("Error", "Could not write the ChaosGameDescription to file."); - } - } - } - }); - 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()); - initializeMainButtons(); + public void stopGame() { + timeline.stop(); + gui.getStartButton().setText("Resume"); } /** - * Draw the chaos game on the canvas. + * Clears the canvas. */ - public void drawChaosGame(){ - int iterationLimit = Integer.parseInt(gui.getIterationLimitTextField().getText()); - - if (stepCounter >= iterationLimit) { - timeline.stop(); - return; - } - // 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()); + public void clearCanvas() { + chaosCanvas.clearCanvas(); + GraphicsContext gc = gui.getCanvas().getGraphicsContext2D(); + gc.clearRect(0, 0, gui.getCanvas().getWidth(), gui.getCanvas().getHeight()); + gui.getImageView().setImage(null); + } - WritableImage image = converter.getImage(); - gui.getCanvas().getGraphicsContext2D().drawImage(image, 0, 0); - gui.getImageView().setImage(image); - stepCounter++; + /** + * Quits the game. + */ + public void quitGame() { + Platform.exit(); } - /** - * Saves a WritableImage to an image file. - */ - public void saveImage() { - // Retrieve the WritableImage from the ImageView - WritableImage image = gui.getImageView().snapshot(null, null); - - // Use a FileChooser to let the user specify the filename - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Save Image"); - fileChooser.setInitialDirectory(new File(currentImagePath)); - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG Files", "*.png")); - File file = fileChooser.showSaveDialog(gui.getStage()); - - if (file != null) { - try { - BufferedImage bufferedImage = toBufferedImage(image); - ImageIO.write(bufferedImage, "png", file); - } catch (IOException e) { - PopupManager.displayError("Save error", "There was an error whilst saving the image."); - } + /** + * Saves the image. + */ + public void saveImage() { + WritableImage image = gui.getImageView().snapshot(null, null); + + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save Image"); + fileChooser.setInitialDirectory(new File(currentImagePath)); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG Files", "*.png")); + File file = fileChooser.showSaveDialog(gui.getStage()); + + if (file != null) { + try { + BufferedImage bufferedImage = toBufferedImage(image); + ImageIO.write(bufferedImage, "png", file); + } catch (IOException e) { + PopupManager.displayError("Save error", "There was an error whilst saving the image."); } } + } /** * Converts a WritableImage to a BufferedImage. @@ -313,81 +242,135 @@ public class GuiButtonController { } /** - * Start the game. + * Loads a fractal from a file. */ - public void startGame() { - timeline.play(); - gui.getStartButton().setText("Start"); + public void loadFractalFromFile() { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open Fractal File"); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text Files", "*.txt")); + File selectedFile = fileChooser.showOpenDialog(gui.getStage()); + if (selectedFile != null) { + Path dest = Paths.get("src/main/resources/descriptions/saved_descriptions/" + selectedFile.getName()); + try { + Files.copy(selectedFile.toPath(), dest); + factory = new ChaosGameDescriptionFactory(); + } catch (IOException e) { + PopupManager.displayError("Error", "Could not load the fractal from file."); + } + } } /** - * Stop the game. + * Writes the fractal to a file. */ - public void stopGame() { - timeline.stop(); - gui.getStartButton().setText("Resume"); + public void writeFractalToFile() { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save File"); + fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); + fileChooser.getExtensionFilters().addAll( + new FileChooser.ExtensionFilter("Text Files", "*.txt"), + new FileChooser.ExtensionFilter("All Files", "*.*") + ); + File file = fileChooser.showSaveDialog(gui.getStage()); + + if (file != null) { + try { + ChaosGameDescription description = game.getDescription(); + fileHandler.writeToFile(description, file.getPath()); + } catch (IOException e) { + PopupManager.displayError("Error", "Could not write the ChaosGameDescription to file."); + } + } } /** - * Clear the image view. + * Modifies the game based on the selected transformation. */ - public void clearCanvas() { - chaosCanvas.clearCanvas(); - GraphicsContext gc = gui.getCanvas().getGraphicsContext2D(); - gc.clearRect(0, 0, gui.getCanvas().getWidth(), gui.getCanvas().getHeight()); - gui.getImageView().setImage(null); + public void modifyGame() { + ChaosGameDescription description = game.getDescription(); + if (description.getTransforms().get(0) instanceof JuliaTransform) { + JuliaPopup juliaPopup = new JuliaPopup(description); + juliaPopup.getPopupModifyStage().setUserData(this); + popupButtonController.handleUpdateButton(juliaPopup); + juliaPopup.display(); + } else { + Affine2DPopup affine2DPopup = new Affine2DPopup(description); + affine2DPopup.getPopupModifyStage().setUserData(this); + popupButtonController.handleUpdateButton(affine2DPopup); + affine2DPopup.display(); + } } + /** + * Initializes the description combo box. + */ + private void initializeDescriptionComboBox() { + ComboBox<String> descriptionComboBox = gui.getDescriptionComboBox(); + descriptionComboBox.setOnShowing(event -> updateDescriptionComboBox()); + + descriptionComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + for (int i = 0; i < factory.getDescriptions().size(); i++) { + ChaosGameDescription description = factory.getDescriptions().get(i); + if (description.getName().equals(newValue)) { + updateDescription(i); + break; + } + } + }); + } /** - * Quit the game. + * Updates the description combo box. */ - public void quitGame() { - Platform.exit(); + public void updateDescriptionComboBox() { + factory = new ChaosGameDescriptionFactory(); + ComboBox<String> descriptionComboBox = gui.getDescriptionComboBox(); + descriptionComboBox.getItems().clear(); + for (ChaosGameDescription description : factory.getDescriptions()) { + descriptionComboBox.getItems().add(description.getName()); + } } /** - * Initialize the main buttons. + * Draws the chaos game on the canvas. */ - private void initializeMainButtons() { - gui.getStartButton().setOnAction(event -> startGame()); - gui.getStopButton().setOnAction(event -> stopGame()); + public void drawChaosGame() { + int iterationLimit = Integer.parseInt(gui.getIterationLimitTextField().getText()); - gui.getClearButton().setOnAction(event -> clearCanvas()); + if (stepCounter >= iterationLimit) { + timeline.stop(); + return; + } + game.runSteps(!Objects.equals(gui.getStepCountTextField().getText(), "") ? + Integer.parseInt(gui.getStepCountTextField().getText()) : 1000); - gui.getQuitButton().setOnAction(event -> quitGame()); - gui.getColorCheckBox().setOnAction(event -> game.setUseColor(gui.getColorCheckBox().isSelected())); + ChaosCanvasToImageConverter converter = new ChaosCanvasToImageConverter(chaosCanvas, + gui.getColorCheckBox().isSelected()); + WritableImage image = converter.getImage(); + gui.getCanvas().getGraphicsContext2D().drawImage(image, 0, 0); + gui.getImageView().setImage(image); + stepCounter++; } /** - * 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? + * Updates the description of the chaos game. * * @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()); + gui.getCanvas().getGraphicsContext2D().clearRect(0, 0, gui.getCanvas().getGraphicsContext2D().getCanvas().getWidth(), gui.getCanvas().getGraphicsContext2D().getCanvas().getHeight()); clearCanvas(); 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()); + 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/ChaosCanvasToImageConverter.java b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosCanvasToImageConverter.java index 95a5e42364a299eea2a517506bc7dffd9ac40665..77dba5f68ced446988bb560a9b1547b86aa1a2c2 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosCanvasToImageConverter.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosCanvasToImageConverter.java @@ -1,8 +1,8 @@ package edu.ntnu.stud.chaosgame.view; +import edu.ntnu.stud.chaosgame.model.game.ChaosCanvas; import javafx.scene.image.PixelWriter; import javafx.scene.image.WritableImage; import javafx.scene.paint.Color; -import edu.ntnu.stud.chaosgame.model.game.ChaosCanvas; /** * This class converts the state of a ChaosCanvas to a WritableImage. 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 712fe29ea5347cfd375c05d8e27395cdfbd2d0bf..c482f6dd187eb0dd614de998ac9fd206fd18c4ed 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameGui.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameGui.java @@ -1,12 +1,12 @@ package edu.ntnu.stud.chaosgame.view; -import edu.ntnu.stud.chaosgame.model.game.ChaosCanvas; import edu.ntnu.stud.chaosgame.controller.game.ChaosGame; -import edu.ntnu.stud.chaosgame.model.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.game.ChaosCanvas; +import edu.ntnu.stud.chaosgame.model.game.ChaosGameDescription; import edu.ntnu.stud.chaosgame.model.generators.ChaosGameDescriptionFactory; +import java.io.IOException; import javafx.animation.Timeline; import javafx.animation.TranslateTransition; import javafx.geometry.Insets; @@ -15,163 +15,100 @@ import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.control.*; -import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.text.Font; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Region; -import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.stage.Window; import javafx.util.Duration; -import java.io.IOException; // todo: look through GUI and get rid of redundancies, clean up code -public class ChaosGameGui implements ChaosGameObserver { - private int currentLine = 0; - - /** - * The primary stage for the GUI. - */ +public class ChaosGameGui implements ChaosGameObserver, GuiButtonObserver { + /** The primary stage for the GUI. */ private final Stage primaryStage; - /** - * The aspect ratio of the GUI. - */ + /** The aspect ratio of the GUI. */ private final double aspectRatio; - /** - * The canvas for this GUI. - */ + private final int currentLine = 0; + + /** The controller for the GUI. */ + private final GuiButtonController controller; + + /** The canvas for this GUI. */ private Canvas canvas; - /** - * The ChaosCanvas for this GUI. - */ + /** The ChaosCanvas for this GUI. */ private ChaosCanvas chaosCanvas; - /** - * The ChaosGameDescription. - */ + /** The ChaosGameDescription. */ private ChaosGameDescription description; - /** - * The ChaosGameDescriptionFactory. - */ + /** The ChaosGameDescriptionFactory. */ private ChaosGameDescriptionFactory factory; - /** - * The ImageView for the GUI. - */ + /** The ImageView for the GUI. */ private ChaosGameImageView imageView; - /** - * The Scene for the GUI. - */ + /** The Scene for the GUI. */ private Scene scene; - /** - * The width of the GUI. - */ + /** The width of the GUI. */ private int width; - /** - * The height of the GUI. - */ + /** The height of the GUI. */ private int height; - /** - * The ChaosGame for this GUI. - */ + /** The ChaosGame for this GUI. */ private ChaosGame game; - /** - * The Timeline for the GUI. - */ + /** The Timeline for the GUI. */ private Timeline timeline; - /** - * The BorderPane for the GUI. - */ + /** The BorderPane for the GUI. */ private BorderPane borderPane; - /** - * The side menu for the GUI. - */ + /** The side menu for the GUI. */ private VBox sideMenu; - /** - * The start, stop, new, clear, quit and show sidebar buttons for the GUI. - */ + /** The start, stop, new, clear, quit and show sidebar buttons for the GUI. */ private Button startButton; - /** - * The stop button for the GUI. - */ + /** The stop button for the GUI. */ private Button stopButton; - - /** - * The button for clearing - */ + /** The button for clearing */ private Button clearButton; - /** - * The quit button for the GUI. - */ + /** The quit button for the GUI. */ private Button quitButton; - /** - * The side menu button for the GUI. - */ + /** The side menu button for the GUI. */ private Button sideMenuButton; - /** - * The load fractal from file and write fractal to file buttons for the GUI. - */ + /** The load fractal from file and write fractal to file buttons for the GUI. */ private Button loadFractalFromFileButton; - /** - * The write fractal to file button for the GUI. - */ + /** The write fractal to file button for the GUI. */ private Button writeFractalToFileButton; - /** - * The button which opens a menu to modify the game - */ + /** The button which opens a menu to modify the game */ private Button modifyGameButton; - /** - * A description ComboBox for choosing different fractal descriptions. - */ + /** A description ComboBox for choosing different fractal descriptions. */ private ComboBox<String> descriptionComboBox; - /** - * The step count text field for the GUI. - */ + /** The step count text field for the GUI. */ private TextField stepCountTextField; - /** - * The iteration limiter text field for the GUI - */ + /** The iteration limiter text field for the GUI */ private TextField iterationLimitTextField; - /** - * The color check box for the GUI. - */ + /** The color check box for the GUI. */ private CheckBox colorCheckBox; - /** - * The controller for the GUI. - */ - private GuiButtonController controller; - - /** - * Button to save an image of the fractal. - */ + /** Button to save an image of the fractal. */ private Button saveImageButton; /** @@ -186,49 +123,53 @@ public class ChaosGameGui implements ChaosGameObserver { this.initializeGameComponents(); this.controller = new GuiButtonController(game, this); // Initialize controller here - primaryStage.setTitle("Fractal Chaos Game"); - primaryStage.setScene(scene); - primaryStage.setOnShown(event -> this.imageView.requestFocus()); - primaryStage.show(); + primaryStage.setTitle("Fractal Chaos Game"); + primaryStage.setScene(scene); + primaryStage.setOnShown(event -> this.imageView.requestFocus()); + primaryStage.show(); // Initialize aspect ratio based on initial dimensions this.aspectRatio = (double) width / height; // Add listeners to handle window size changes - scene.widthProperty().addListener((observable, oldValue, newValue) -> { - resizeCanvas(); - }); - - - scene.heightProperty().addListener((observable, oldValue, newValue) -> { - resizeCanvas(); - }); - - // Bind the width of the sideMenu to the width of the scene - sideMenu.prefWidthProperty().bind(scene.widthProperty().multiply(0.2)); // 20% of the scene width - - // Bind the height of the sideMenu to the height of the scene - sideMenu.prefHeightProperty().bind(scene.heightProperty()); + scene + .widthProperty() + .addListener( + (observable, oldValue, newValue) -> { + resizeCanvas(); + }); + + scene + .heightProperty() + .addListener( + (observable, oldValue, newValue) -> { + resizeCanvas(); + }); + + // Bind the width of the sideMenu to the width of the scene + sideMenu + .prefWidthProperty() + .bind(scene.widthProperty().multiply(0.2)); // 20% of the scene width + + // Bind the height of the sideMenu to the height of the scene + sideMenu.prefHeightProperty().bind(scene.heightProperty()); } - - /** - * Initialize the components of the GUI. - */ + /** Initialize the components of the GUI. */ private void initializeComponents() { // Timeline - //this.timeline = new Timeline(new KeyFrame(Duration.seconds(0.05), event -> controller.drawChaosGame())); + // this.timeline = new Timeline(new KeyFrame(Duration.seconds(0.05), event -> + // controller.drawChaosGame())); this.initializeImageView(); - //this.initializeMainButtons(); + // this.initializeMainButtons(); this.initializeFractalComponents(); this.initializeSideMenu(); - this.scene = new Scene(this.borderPane,1700,1000); + this.scene = new Scene(this.borderPane, 1700, 1000); } -/** - * Creates a TextField of specific size. - */ + + /** Creates a TextField of specific size. */ private TextField createCoordinateTextField(String promptText) { TextField textField = new TextField(); textField.setPrefHeight(5); @@ -237,21 +178,19 @@ public class ChaosGameGui implements ChaosGameObserver { return textField; } - /** - * Initialize the components related to the chaos game itself. - */ + /** Initialize the components related to the chaos game itself. */ private void initializeGameComponents() { // Description this.factory = new ChaosGameDescriptionFactory(); this.description = factory.getDescriptions().get(0); - this.chaosCanvas = new ChaosCanvas(1000, 1000, this.description.getMinCoords(), - this.description.getMaxCoords()); + this.chaosCanvas = + new ChaosCanvas( + 1000, 1000, this.description.getMinCoords(), this.description.getMaxCoords()); game = new ChaosGame(this.description, chaosCanvas); } - /** - * Initialize components related to the image view and zoom function. - */ + + /** Initialize components related to the image view and zoom function. */ private void initializeImageView() { // Image view this.imageView = new ChaosGameImageView(this); @@ -263,88 +202,82 @@ public class ChaosGameGui implements ChaosGameObserver { canvas.heightProperty().bind(imageView.fitHeightProperty()); this.clearImageView(); - } - /** - * Color the entire image view white. - */ + /** Color the entire image view white. */ public void clearImageView() { GraphicsContext gc = canvas.getGraphicsContext2D(); gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); imageView.setImage(null); } - /** - * Initialize the buttons related to managing the fractals. - */ + /** Initialize the buttons related to managing the fractals. */ private void initializeFractalComponents() { this.descriptionComboBox = new ComboBox<>(); - // Load fractal file button and tooltip this.loadFractalFromFileButton = new Button("Load Fractal"); - Tooltip loadFractalFromFileButtonTooltip = new Tooltip("Load a text file describing a new fractal chaos game"); - Tooltip.install(loadFractalFromFileButton,loadFractalFromFileButtonTooltip); + Tooltip loadFractalFromFileButtonTooltip = + new Tooltip("Load a text file describing a new fractal chaos game"); + Tooltip.install(loadFractalFromFileButton, loadFractalFromFileButtonTooltip); // Write fractal to file button and tooltip this.writeFractalToFileButton = new Button("Write to File"); - Tooltip writeFractalToFileButtonTooltip = new Tooltip("Write a text file defining the current fractal chaos game to chosen location"); + Tooltip writeFractalToFileButtonTooltip = + new Tooltip("Write a text file defining the current fractal chaos game to chosen location"); Tooltip.install(writeFractalToFileButton, writeFractalToFileButtonTooltip); } - /** - * Initialize the side menu for the GUI, including all its buttons and other - * components. - */ + /** Initialize the side menu for the GUI, including all its buttons and other components. */ private void initializeSideMenu() { // Create a Border style - Border blackBorder = new Border(new BorderStroke(Color.BLACK, - BorderStrokeStyle.SOLID, - new CornerRadii(10), - new BorderWidths(5))); + Border blackBorder = + new Border( + new BorderStroke( + Color.BLACK, BorderStrokeStyle.SOLID, new CornerRadii(10), new BorderWidths(5))); // Create Canvas Header Label canvasLabel = new Label("Play Controls"); canvasLabel.setAlignment(Pos.CENTER); - canvasLabel.setFont(new Font("Arial",20)); + canvasLabel.setFont(new Font("Arial", 20)); // Create Canvas Buttons this.startButton = new Button("Start"); this.stopButton = new Button("Pause"); this.clearButton = new Button("New"); this.quitButton = new Button("Quit"); - //this.sideMenuButton = new Button("Side Menu"); + // this.sideMenuButton = new Button("Side Menu"); // Create Tooltips - Tooltip startButtonTooltip = new Tooltip("Starts drawing the current fractal from the selected chaos game"); + Tooltip startButtonTooltip = + new Tooltip("Starts drawing the current fractal from the selected chaos game"); Tooltip stopButtonTooltip = new Tooltip("Pause drawing current fractal"); Tooltip clearButtonTooltip = new Tooltip("Clear the current fracal"); Tooltip quitButtonTooltip = new Tooltip("Quit the application"); // Attach Tooltips to Buttons - Tooltip.install(startButton,startButtonTooltip); - Tooltip.install(stopButton,stopButtonTooltip); - Tooltip.install(clearButton,clearButtonTooltip); + Tooltip.install(startButton, startButtonTooltip); + Tooltip.install(stopButton, stopButtonTooltip); + Tooltip.install(clearButton, clearButtonTooltip); Tooltip.install(quitButton, quitButtonTooltip); this.sideMenu = new VBox(); - //this.sideMenu.setAlignment(Pos.CENTER); + // this.sideMenu.setAlignment(Pos.CENTER); // Parameters VBox parameterBox = new VBox(); VBox controlButtonBox = new VBox(); controlButtonBox.setBorder(blackBorder); - controlButtonBox.setPadding(new Insets(5,5,5,5)); + controlButtonBox.setPadding(new Insets(5, 5, 5, 5)); VBox descriptionBox = new VBox(); descriptionBox.setBorder(blackBorder); - descriptionBox.setPadding(new Insets(5,5,5,5)); + descriptionBox.setPadding(new Insets(5, 5, 5, 5)); VBox bottomButtonBox = new VBox(); // Step Count GUI VBox stepCountBox = new VBox(); Label stepCountLabel = new Label("Step Count"); - stepCountLabel.setFont(new Font("Arial",20)); + stepCountLabel.setFont(new Font("Arial", 20)); Label steppingSpeedLabel = new Label("Stepping Speed"); stepCountLabel.setAlignment(Pos.CENTER); this.stepCountTextField = new TextField(); @@ -356,19 +289,25 @@ public class ChaosGameGui implements ChaosGameObserver { Label iterationLimterLabel = new Label("Iteration Limit"); this.iterationLimitTextField = new TextField(); this.iterationLimitTextField.setTextFormatter(Formatter.getIntFormatter()); - Formatter.limitTextFieldSize(iterationLimitTextField,4); + Formatter.limitTextFieldSize(iterationLimitTextField, 4); iterationLimitTextField.setText("500"); - stepCountBox.getChildren().addAll(stepCountLabel,steppingSpeedLabel,stepCountTextField,iterationLimterLabel,iterationLimitTextField); + stepCountBox + .getChildren() + .addAll( + stepCountLabel, + steppingSpeedLabel, + stepCountTextField, + iterationLimterLabel, + iterationLimitTextField); stepCountBox.setAlignment(Pos.CENTER); - stepCountBox.setPadding(new Insets(5,5,5,5)); + stepCountBox.setPadding(new Insets(5, 5, 5, 5)); stepCountBox.setBorder(blackBorder); // Create a Box for Coordinate Controls VBox modifyGameBox = new VBox(); modifyGameBox.setPadding(new Insets(5, 5, 5, 5)); - // Coordinate Control GUI Label coordinateHeader = new Label("Game Modification"); coordinateHeader.setFont(new Font("Arial", 20)); @@ -379,27 +318,28 @@ public class ChaosGameGui implements ChaosGameObserver { modifyGameButton = new Button("Create Modified Game"); Tooltip modifyGameButtonTooltip = new Tooltip("Create New Chaos Game From Current"); - Tooltip.install(modifyGameButton,modifyGameButtonTooltip); + Tooltip.install(modifyGameButton, modifyGameButtonTooltip); modifyGameBox.getChildren().addAll(modifyGameButton); modifyGameBox.setAlignment(Pos.CENTER); modifyGameBox.setBorder(blackBorder); Label colorHeaderLabel = new Label("Color Control"); - colorHeaderLabel.setFont(new Font("Arial",20)); + colorHeaderLabel.setFont(new Font("Arial", 20)); colorHeaderLabel.setAlignment(Pos.CENTER); VBox colorVBox = new VBox(); HBox colorBox = new HBox(); Label colorLabel = new Label("Show Redrawn Pixels"); this.colorCheckBox = new CheckBox(); - Tooltip colorCheckBoxTooltip = new Tooltip("Change pixel color for pixels drawn multiple times"); - Tooltip.install(colorCheckBox,colorCheckBoxTooltip); + Tooltip colorCheckBoxTooltip = + new Tooltip("Change pixel color for pixels drawn multiple times"); + Tooltip.install(colorCheckBox, colorCheckBoxTooltip); Region colorRegion = new Region(); colorRegion.setMinWidth(30); colorBox.getChildren().addAll(colorCheckBox, colorRegion, colorLabel); - colorVBox.setPadding(new Insets(5,5,5,5)); - colorVBox.getChildren().addAll(colorHeaderLabel,colorBox); + colorVBox.setPadding(new Insets(5, 5, 5, 5)); + colorVBox.getChildren().addAll(colorHeaderLabel, colorBox); colorVBox.setAlignment(Pos.CENTER); colorVBox.setBorder(blackBorder); @@ -408,7 +348,7 @@ public class ChaosGameGui implements ChaosGameObserver { Region separator2 = new Region(); separator2.setMinHeight(10); - //Create spacing + // Create spacing Region space = new Region(); Region spacer = new Region(); space.setMinHeight(10); @@ -420,8 +360,7 @@ public class ChaosGameGui implements ChaosGameObserver { // Add basic control buttons controlButtonBox.setAlignment(Pos.CENTER); - controlButtonBox.getChildren().addAll(canvasLabel,startButton, stopButton,clearButton); - + controlButtonBox.getChildren().addAll(canvasLabel, startButton, stopButton, clearButton); controlButtonBox.setSpacing(5); sideMenu.getChildren().add(controlButtonBox); @@ -429,36 +368,42 @@ public class ChaosGameGui implements ChaosGameObserver { // Add spacing sideMenu.getChildren().add(space); - - //Radio Button header label + // Radio Button header label Label chaosGameTypeLabel = new Label("Chaos Game Selection"); - chaosGameTypeLabel.setFont(new Font("Arial",20)); + chaosGameTypeLabel.setFont(new Font("Arial", 20)); chaosGameTypeLabel.setAlignment(Pos.CENTER); // Add fractal radio buttons - descriptionBox.getChildren().addAll(chaosGameTypeLabel,descriptionComboBox); + descriptionBox.getChildren().addAll(chaosGameTypeLabel, descriptionComboBox); descriptionBox.setSpacing(5); descriptionBox.setAlignment(Pos.CENTER); sideMenu.getChildren().add(descriptionBox); sideMenu.getChildren().addAll(separator1, colorVBox, separator2); - //this.initializeColorButtonHandler(); + // this.initializeColorButtonHandler(); // Add parameter VBox sideMenu.getChildren().add(parameterBox); // Add file buttons and quit button Label menuButtonLabel = new Label("Menu Controls"); - menuButtonLabel.setFont(new Font("Arial",20)); + menuButtonLabel.setFont(new Font("Arial", 20)); menuButtonLabel.setAlignment(Pos.CENTER); saveImageButton = new Button("Save Image"); - bottomButtonBox.getChildren().addAll(menuButtonLabel,saveImageButton,loadFractalFromFileButton,writeFractalToFileButton,quitButton); + bottomButtonBox + .getChildren() + .addAll( + menuButtonLabel, + saveImageButton, + loadFractalFromFileButton, + writeFractalToFileButton, + quitButton); bottomButtonBox.setSpacing(5); bottomButtonBox.setBorder(blackBorder); bottomButtonBox.setAlignment(Pos.CENTER); - bottomButtonBox.setPadding(new Insets(5,5,5,5)); + bottomButtonBox.setPadding(new Insets(5, 5, 5, 5)); sideMenu.getChildren().add(bottomButtonBox); // Add padding @@ -473,7 +418,6 @@ public class ChaosGameGui implements ChaosGameObserver { sideMenuButtonRegion.setMinWidth(400); HBox sideMenuButtonBox = new HBox(); - sideMenuButtonBox.getChildren().addAll(sideMenuButtonRegion, sideMenuButton); // The right VBox containing both the sidebar and the sidebar toggle button. @@ -488,28 +432,27 @@ public class ChaosGameGui implements ChaosGameObserver { imageView.setFocusTraversable(true); rightVBox.setFocusTraversable(false); borderPane.setFocusTraversable(false); - } /** - * Initialise the side bar button handler, allowing the user - * to show or hide the right sidebar. + * Initialise the side bar button handler, allowing the user to show or hide the right sidebar. */ private void initializeSideButtonHandler() { TranslateTransition openNav = new TranslateTransition(new Duration(350), sideMenu); openNav.setToX(0); TranslateTransition closeNav = new TranslateTransition(new Duration(350), sideMenu); - this.sideMenuButton.setOnAction(e -> { - if(sideMenu.getTranslateX() != 0){ - this.sideMenuButton.setText(">>"); - openNav.play(); - } else { - closeNav.setToX(sideMenu.getWidth()); - closeNav.play(); - this.sideMenuButton.setText("<<"); - } - }); + this.sideMenuButton.setOnAction( + e -> { + if (sideMenu.getTranslateX() != 0) { + this.sideMenuButton.setText(">>"); + openNav.play(); + } else { + closeNav.setToX(sideMenu.getWidth()); + closeNav.play(); + this.sideMenuButton.setText("<<"); + } + }); } /** @@ -517,13 +460,13 @@ public class ChaosGameGui implements ChaosGameObserver { * * @return the image view. */ - public ImageView getImageView(){ + public ImageView getImageView() { return this.imageView; } /** - * Update the canvas and set a new zoom factor for the image view based on the ratio - * between the old and new canvas heights. + * Update the canvas and set a new zoom factor for the image view based on the ratio between the + * old and new canvas heights. * * @param canvas the canvas to update with. */ @@ -533,8 +476,8 @@ public class ChaosGameGui implements ChaosGameObserver { } /** - * Update the observer based on changes to the chaos game. - * TODO: this method may need to be changed depending on how we implement the UI. The update method may need to be split. + * Update the observer based on changes to the chaos game. TODO: this method may need to be + * changed depending on how we implement the UI. The update method may need to be split. * * @param game the game this observer is monitoring. */ @@ -543,6 +486,47 @@ public class ChaosGameGui implements ChaosGameObserver { controller.drawChaosGame(); } + // GuiButtonObserver methods + @Override + public void onStartButtonPressed() { + controller.startGame(); + } + + @Override + public void onStopButtonPressed() { + controller.stopGame(); + } + + @Override + public void onClearButtonPressed() { + controller.clearCanvas(); + } + + @Override + public void onQuitButtonPressed() { + controller.quitGame(); + } + + @Override + public void onSaveImageButtonPressed() { + controller.saveImage(); + } + + @Override + public void onLoadFractalFromFileButtonPressed() { + controller.loadFractalFromFile(); + } + + @Override + public void onWriteToFileButtonPressed() { + controller.writeFractalToFile(); + } + + @Override + public void onModifyGameButtonPressed() { + controller.modifyGame(); + } + /** * Get the step count text field for this GUI. * @@ -557,7 +541,7 @@ public class ChaosGameGui implements ChaosGameObserver { * * @return the iteration limit text field. */ - public TextField getIterationLimitTextField(){ + public TextField getIterationLimitTextField() { return this.iterationLimitTextField; } @@ -633,9 +617,7 @@ public class ChaosGameGui implements ChaosGameObserver { return this.primaryStage; } - /** - * Resize the canvas to fit the new dimensions of the scene. - */ + /** Resize the canvas to fit the new dimensions of the scene. */ private void resizeCanvas() { double newWidth = scene.getWidth() - sideMenu.getWidth(); double newHeight = scene.getHeight(); @@ -668,7 +650,7 @@ public class ChaosGameGui implements ChaosGameObserver { * * @return the modify game button. */ - public Button getModifyGameButton(){ + public Button getModifyGameButton() { return this.modifyGameButton; } @@ -677,7 +659,7 @@ public class ChaosGameGui implements ChaosGameObserver { * * @return the description combo box. */ - public ComboBox getDescriptionComboBox(){ + public ComboBox getDescriptionComboBox() { return this.descriptionComboBox; } @@ -686,7 +668,7 @@ public class ChaosGameGui implements ChaosGameObserver { * * @return the save image button. */ - public Button getSaveImageButton(){ + public Button getSaveImageButton() { return this.saveImageButton; } } diff --git a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameImageView.java b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameImageView.java index 00c9fedc89ae5ee72ab5ed937ae571e3bf9cd3b5..2baf81d7df1d6c5eae41d790591c8d183750ef71 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameImageView.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameImageView.java @@ -6,45 +6,35 @@ import javafx.scene.input.ScrollEvent; import javafx.scene.transform.Affine; /** - * This class extends ImageView to implement proper zooming and panning - * according to the requirements of the chaos game. + * This class extends ImageView to implement proper zooming and panning according to the + * requirements of the chaos game. */ public class ChaosGameImageView extends ImageView { - /** - * The controller for this class: a chaos game GUI view. - */ + /** The controller for this class: a chaos game GUI view. */ private final ChaosGameGui controller; /** - * Affine initialised to the identity matrix, representing the current transformation - * as a result of zooming. + * Affine initialised to the identity matrix, representing the current transformation as a result + * of zooming. */ private final Affine transform = new Affine(); - /** - * The starting position of the mouse cursor when dragging. - */ + /** The starting position of the mouse cursor when dragging. */ private double startX; - /** - * The starting position of the mouse cursor when dragging. - */ + /** The starting position of the mouse cursor when dragging. */ private double startY; - /** - * The factor representing the magnitude of the current zoom. - */ + /** The factor representing the magnitude of the current zoom. */ private double zoomFactor = 1.0; /** - * Integer representing how many recursive levels of QuadTrees - * are required to get to the current zoom magnitude. + * Integer representing how many recursive levels of QuadTrees are required to get to the current + * zoom magnitude. */ private int zoomLevel = 0; - - /** * Constructor for the ChaosGameImageView. * @@ -87,7 +77,6 @@ public class ChaosGameImageView extends ImageView { this.zoomFactor *= newZoomFactor; this.zoomLevel = (int) (Math.log(this.zoomFactor) / Math.log(4)); // Update zoom level. - } catch (Exception e) { PopupManager.displayError("Zoom error", e.getMessage()); } @@ -121,6 +110,7 @@ public class ChaosGameImageView extends ImageView { * * @return the current transform. */ - public Affine getTransform() {return this.transform; } - + public Affine getTransform() { + return this.transform; + } } 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 46c8095e99f149e720392df0c6329f217361e41c..945d8db4ad0f2ab7f706399b38c80f0f671beda3 100644 --- a/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameObserver.java +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/ChaosGameObserver.java @@ -4,8 +4,8 @@ import edu.ntnu.stud.chaosgame.controller.game.ChaosGame; import edu.ntnu.stud.chaosgame.model.game.ChaosCanvas; /** - * Observer interface for monitoring changes to the active - * TODO: Do we want to have separate update methods for the canvas and description or just one for the whole game? (likely the latter) + * Observer interface for monitoring changes to the active TODO: Do we want to have separate update + * methods for the canvas and description or just one for the whole game? (likely the latter) */ public interface ChaosGameObserver { diff --git a/src/main/java/edu/ntnu/stud/chaosgame/view/GuiButtonObserver.java b/src/main/java/edu/ntnu/stud/chaosgame/view/GuiButtonObserver.java new file mode 100644 index 0000000000000000000000000000000000000000..e2eb1a8fa1aabf048b85da5a6916bdc2be06c418 --- /dev/null +++ b/src/main/java/edu/ntnu/stud/chaosgame/view/GuiButtonObserver.java @@ -0,0 +1,27 @@ +package edu.ntnu.stud.chaosgame.view; + +public interface GuiButtonObserver { + /** Used when start-button is pressed. */ + void onStartButtonPressed(); + + /** Used when stop-button is pressed. */ + void onStopButtonPressed(); + + /** Used when clear-button is pressed. */ + void onClearButtonPressed(); + + /** Used when quit-button is pressed. */ + void onQuitButtonPressed(); + + /** Used when save image button is pressed. */ + void onSaveImageButtonPressed(); + + /** Used when load fractal button is pressed. */ + void onLoadFractalFromFileButtonPressed(); + + /** Used when write to file button is pressed. */ + void onWriteToFileButtonPressed(); + + /** Used when modify game button is pressed. */ + void onModifyGameButtonPressed(); +}