diff --git a/src/main/java/ru/di9/ss14/extractor/gui/ExportInfoController.java b/src/main/java/ru/di9/ss14/extractor/gui/ExportInfoController.java new file mode 100644 index 0000000..46b6bf9 --- /dev/null +++ b/src/main/java/ru/di9/ss14/extractor/gui/ExportInfoController.java @@ -0,0 +1,116 @@ +package ru.di9.ss14.extractor.gui; + +import javafx.application.Platform; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.stage.Stage; +import lombok.Setter; +import ru.di9.ss14.extractor.ContentDbManager; +import ru.di9.ss14.extractor.ContentRec; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ResourceBundle; +import java.util.concurrent.atomic.AtomicReference; + +public class ExportInfoController implements Initializable { + private static final Path EMPTY_PATH = Paths.get(""); + + @FXML + public Label labelCurrentExport; + + @FXML + public Button btnCancel; + + @Setter + private Stage stage; + + @Setter + private ContentDbManager manager; + + private volatile boolean running = false; + private Task task; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + btnCancel.setDisable(false); + btnCancel.setText("Отменить"); + + btnCancel.setOnAction(e -> { + btnCancel.setDisable(true); + btnCancel.setText("Отменяется..."); + stopExport(); + }); + } + + public void startExport(ContentRec contentRec, Path currentDir) { + running = true; + + task = new Task<>() { + @Override + protected Void call() throws Exception { + exportRecursiveFolder(contentRec, currentDir, new AtomicReference<>(EMPTY_PATH)); + return null; + } + }; + + task.setOnSucceeded(e -> { + stage.close(); + task = null; + }); + task.setOnCancelled(e -> { + running = false; + stage.close(); + task = null; + }); + + var thread = new Thread(task); + thread.setDaemon(true); + thread.start(); + } + + public void stopExport() { + task.cancel(); + } + + private void exportRecursiveFolder(ContentRec contentRec, Path currentDir, AtomicReference refExportedPath) throws IOException { + if (!running) { + return; + } + + var subDir = currentDir.resolve(contentRec.getName()); + if (Files.notExists(subDir)) { + Files.createDirectory(subDir); + } + + for (ContentRec rec : contentRec.getChildren()) { + if (!running) { + break; + } + + refExportedPath.updateAndGet(p -> p.resolve(rec.getName())); + + if (rec.isFolder()) { + exportRecursiveFolder(rec, subDir, refExportedPath); + } else { + var path = subDir.resolve(rec.getName()); + try (var out = new FileOutputStream(path.toFile())) { + var exportedPath = refExportedPath.get(); + System.out.printf("export %s...\n", exportedPath); + final var ref = new AtomicReference<>(exportedPath); + Platform.runLater(() -> labelCurrentExport.setText(ref.get().toString())); + manager.readContent(rec.getId(), out); + } + refExportedPath.updateAndGet(p -> p.getParent() == null ? EMPTY_PATH : p.getParent()); + } + } + refExportedPath.updateAndGet(p -> p.getParent() == null ? EMPTY_PATH : p.getParent()); + } +} diff --git a/src/main/java/ru/di9/ss14/extractor/gui/MainController.java b/src/main/java/ru/di9/ss14/extractor/gui/MainController.java index eee8613..d221004 100644 --- a/src/main/java/ru/di9/ss14/extractor/gui/MainController.java +++ b/src/main/java/ru/di9/ss14/extractor/gui/MainController.java @@ -2,14 +2,15 @@ package ru.di9.ss14.extractor.gui; import javafx.concurrent.Task; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; +import javafx.scene.Parent; +import javafx.scene.Scene; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; -import javafx.stage.DirectoryChooser; -import javafx.stage.FileChooser; -import javafx.stage.Stage; +import javafx.stage.*; import lombok.Setter; import ru.di9.ss14.extractor.ContentDbManager; import ru.di9.ss14.extractor.ContentRec; @@ -18,12 +19,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.ResourceBundle; -import java.util.SortedSet; +import java.util.*; public class MainController implements Initializable { private static final int STATE_NOT_LOADED = 0; @@ -168,7 +165,7 @@ public class MainController implements Initializable { } try { - exportRecursiveFolder(contentRec, dir.toPath()); + showExportWindow(contentRec, dir.toPath()); } catch (IOException e) { throw new RuntimeException(e); } @@ -181,20 +178,28 @@ public class MainController implements Initializable { return contextMenu; } - private void exportRecursiveFolder(ContentRec contentRec, Path currentDir) throws IOException { - var subDir = currentDir.resolve(contentRec.getName()); - if (Files.notExists(subDir)) { - Files.createDirectory(subDir); - } + private void showExportWindow(ContentRec contentRec, Path currentDir) throws IOException { + var loader = new FXMLLoader(Objects.requireNonNull(getClass().getResource("/view/export-dialog.fxml"))); + Parent root = loader.load(); - for (ContentRec rec : contentRec.getChildren()) { - if (rec.isFolder()) { - exportRecursiveFolder(rec, subDir); - } else { - try (var out = new FileOutputStream(subDir.resolve(rec.getName()).toFile())) { - manager.readContent(rec.getId(), out); - } - } - } + var exportStage = new Stage(); + exportStage.setScene(new Scene(root)); + exportStage.setTitle("Статус сохранения"); + exportStage.initModality(Modality.APPLICATION_MODAL); + exportStage.initOwner(stage); + + var controller = (ExportInfoController)loader.getController(); + controller.setStage(exportStage); + controller.setManager(manager); + + exportStage.setOnShowing(event -> { + stage.getScene().getRoot().setDisable(true); + controller.startExport(contentRec, currentDir); + }); + exportStage.setOnHiding(event -> { + controller.stopExport(); + stage.getScene().getRoot().setDisable(false); + }); + exportStage.showAndWait(); } } diff --git a/src/main/resources/view/export-dialog.fxml b/src/main/resources/view/export-dialog.fxml new file mode 100644 index 0000000..6ab62ed --- /dev/null +++ b/src/main/resources/view/export-dialog.fxml @@ -0,0 +1,29 @@ + + + + + + + + + + + + +