/
victor_t
/
maze
Обзор
Документация
Войти
/
victor_t
/
maze
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
1
CI/CD
Аналитика
Безопасность
master
src/view/CaveWindow.java
274 строки
8 KB
Victor
relocated project folder
03 июл 2026, 03:14
03 июл 2026, 03:14
827638e
Код
Авторство
О чём код?
package view; import controller.Controller; import java.io.File; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Spinner; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Duration; /** * Окно визуализации и управления симуляцией пещеры. * * <p>Класс {@code CaveWindow} реализует пользовательский интерфейс * для работы с моделью пещеры через {@link controller.Controller}.</p> * * <p>Позволяет: * <ul> * <li>загружать и сохранять пещеру из файла</li> * <li>генерировать случайную пещеру</li> * <li>выполнять пошаговую симуляцию</li> * <li>запускать автоматическую эволюцию</li> * </ul> * </p> */ public class CaveWindow { private final Controller controller; private final MazeCanvas caveCanvas; private final Spinner<Integer> rowSpinner; private final Spinner<Integer> colSpinner; private final Spinner<Integer> initSpinner; private final Spinner<Integer> birthSpinner; private final Spinner<Integer> deathSpinner; private final Spinner<Integer> msSpinner; private Timeline timeline; private final Stage stage; /** * Создает окно симуляции пещеры. * * @param controller контроллер для взаимодействия с моделью */ public CaveWindow(Controller controller) { this.controller = controller; this.stage = new Stage(); stage.setTitle("Cave Simulation"); caveCanvas = new MazeCanvas(); caveCanvas.setController(controller); caveCanvas.setCaveOpen(); rowSpinner = new Spinner<>(); colSpinner = new Spinner<>(); initSpinner = new Spinner<>(); birthSpinner = new Spinner<>(); deathSpinner = new Spinner<>(); msSpinner = new Spinner<>(); SpinnerUtils.setupIntegerSpinner(rowSpinner, 1, 50, 10, 1); SpinnerUtils.setupIntegerSpinner(colSpinner, 1, 50, 10, 1); SpinnerUtils.setupIntegerSpinner(initSpinner, 0, 100, 10, 1); SpinnerUtils.setupIntegerSpinner(birthSpinner, 0, 7, 10, 1); SpinnerUtils.setupIntegerSpinner(deathSpinner, 0, 7, 10, 1); SpinnerUtils.setupIntegerSpinner(msSpinner, 1, 10000, 100, 10); Button openFileBtn = new Button("Open File"); openFileBtn.setOnAction(e -> onOpenFile()); Button generateBtn = new Button("Generate"); generateBtn.setOnAction(e -> onGenerate()); Button saveBtn = new Button("Save"); saveBtn.setOnAction(e -> onSave()); Button stepBtn = new Button("Step"); stepBtn.setOnAction(e -> onStep()); Button autoBtn = new Button("Auto"); autoBtn.setOnAction(e -> onAuto()); Button stopBtn = new Button("Stop"); stopBtn.setOnAction(e -> onStop()); HBox row1 = new HBox(6, new Label("Rows:"), rowSpinner, new Label("Cols:"), colSpinner, new Label("Init %:"), initSpinner ); HBox row2 = new HBox(6, new Label("Birth:"), birthSpinner, new Label("Death:"), deathSpinner, new Label("ms:"), msSpinner ); HBox row3 = new HBox(6, openFileBtn, generateBtn, saveBtn, stepBtn, autoBtn, stopBtn ); VBox controls = new VBox(6, row1, row2, row3); controls.setPadding(new Insets(8)); BorderPane root = new BorderPane(); root.setCenter(caveCanvas); root.setBottom(controls); stage.setScene(new Scene(root)); stage.setResizable(false); stage.setOnCloseRequest(e -> onStop()); } /** * Отображает окно на экране. */ public void show() { stage.show(); } /** * Обрабатывает открытие файла с пещерой. * * <p>При успешной загрузке обновляет отображение и параметры размеров.</p> */ private void onOpenFile() { FileChooser fc = new FileChooser(); fc.setTitle("Open file with Cave"); fc.setInitialDirectory(new File(".")); File file = fc.showOpenDialog(stage); if (file == null) { showInfo("Please select a file", "Error 404"); return; } try { controller.caveLoadFromFile(file.getAbsolutePath()); caveCanvas.draw(); rowSpinner.getValueFactory().setValue(controller.getRowCave()); colSpinner.getValueFactory().setValue(controller.getColCave()); } catch (Exception ex) { showError("This file is not suitable for the cave", "Error"); onGenerate(); } } /** * Генерирует новую пещеру на основе значений из интерфейса. */ private void onGenerate() { int row = rowSpinner.getValue(); int col = colSpinner.getValue(); int chance = initSpinner.getValue(); controller.caveGenerate(row, col, chance); caveCanvas.draw(); } /** * Сохраняет текущую пещеру в файл. */ private void onSave() { FileChooser fc = new FileChooser(); fc.setTitle("Save Cave"); fc.setInitialDirectory(new File(".")); File file = fc.showSaveDialog(stage); if (file != null) { try { controller.caveSaveToFile(file.getAbsolutePath()); } catch (Exception ex) { showError("Unable to save file", "Error"); } } } /** * Выполняет один шаг симуляции пещеры. * * <p>Перерисовывает поле только при изменении состояния.</p> */ private void onStep() { int birth = birthSpinner.getValue(); int death = deathSpinner.getValue(); if (controller.caveOneStep(birth, death)) { caveCanvas.draw(); } } /** * Запускает автоматическую симуляцию. * * <p>Шаги выполняются с интервалом, заданным пользователем. * Симуляция останавливается, если состояние перестает изменяться.</p> */ private void onAuto() { if (timeline != null) { timeline.stop(); } timeline = new Timeline(new KeyFrame( Duration.millis(msSpinner.getValue()), e -> { int birth = birthSpinner.getValue(); int death = deathSpinner.getValue(); if (controller.caveOneStep(birth, death)) { caveCanvas.draw(); } else { timeline.stop(); } } )); timeline.setCycleCount(Timeline.INDEFINITE); timeline.play(); } /** * Останавливает автоматическую симуляцию. */ private void onStop() { if (timeline != null) { timeline.stop(); } } /** * Отображает информационное сообщение. * * @param text текст сообщения * @param title заголовок окна */ private void showInfo(String text, String title) { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle(title); alert.setContentText(text); alert.showAndWait(); } /** * Отображает сообщение об ошибке. * * @param text текст ошибки * @param title заголовок окна */ private void showError(String text, String title) { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(title); alert.setContentText(text); alert.showAndWait(); } }