Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

ask user "save modified? yes/no/cancel" when closing modified editor or when closing window/app

AuthorKarl Tauber <email>
Date2015-07-23 21:36:57 GMT+0200
Commit6fef94ab4a34c58b3fcf9e3559cebcf1e97a67a8
Parent7757b9a
Delta79 lines added, 13 lines removed, 66-line increase
src/main/java/org/markdownwriterfx/FileEditor.java
import javafx.scene.control.Tab;
import javafx.scene.control.Tooltip;
+import javafx.scene.text.Text;
import org.markdownwriterfx.editor.MarkdownEditorPane;
import org.markdownwriterfx.preview.MarkdownPreviewPane;
private void updateTab() {
Path path = this.path.get();
- String text = (path != null) ? path.getFileName().toString() : "Untitled";
- if (isModified())
- text = "*".concat(text);
- tab.setText(text);
+ tab.setText((path != null) ? path.getFileName().toString() : "Untitled");
tab.setTooltip((path != null) ? new Tooltip(path.toString()) : null);
+ tab.setGraphic(isModified() ? new Text("*") : null);
}
src/main/java/org/markdownwriterfx/FileEditorTabPane.java
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.scene.Node;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Alert.AlertType;
+import javafx.scene.control.ButtonType;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
private FileEditor createFileEditor(Path path) {
FileEditor fileEditor = new FileEditor(mainWindow, path);
+ fileEditor.getTab().setOnCloseRequest(e -> {
+ if (!canCloseEditor(fileEditor))
+ e.consume();
+ });
return fileEditor;
}
}
- void saveEditor(FileEditor fileEditor) {
+ boolean saveEditor(FileEditor fileEditor) {
if (fileEditor == null)
- return;
+ return false;
if (fileEditor.getPath() == null) {
FileChooser fileChooser = createFileChooser("Save Markdown File");
File file = fileChooser.showSaveDialog(mainWindow.getScene().getWindow());
if (file == null)
- return;
+ return false;
fileEditor.setPath(file.toPath());
}
- fileEditor.save();
+ return fileEditor.save();
}
- void closeEditor(FileEditor fileEditor) {
+ boolean canCloseEditor(FileEditor fileEditor) {
+ if (!fileEditor.isModified())
+ return true;
+
+ Alert alert = mainWindow.createAlert(AlertType.CONFIRMATION, "Close",
+ "'%s' has been modified. Save changes?", fileEditor.getTab().getText());
+ alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL);
+
+ ButtonType result = alert.showAndWait().get();
+ if (result != ButtonType.YES)
+ return (result == ButtonType.NO);
+
+ return saveEditor(fileEditor);
+ }
+
+ boolean closeEditor(FileEditor fileEditor) {
if (fileEditor == null)
- return;
+ return true;
Tab tab = fileEditor.getTab();
Event event = new Event(tab,tab,Tab.TAB_CLOSE_REQUEST_EVENT);
Event.fireEvent(tab, event);
if (event.isConsumed())
- return;
+ return false;
tabPane.getTabs().remove(tab);
if (tab.getOnClosed() != null)
Event.fireEvent(tab, new Event(Tab.CLOSED_EVENT));
+
+ return true;
+ }
+
+ boolean closeAllEditors() {
+ FileEditor[] allEditors = getAllEditors();
+ FileEditor activeEditor = activeFileEditor.get();
+
+ // try to close active tab first because in case user decides to cancel,
+ // then the other tabs stay open
+ if (activeEditor != null && !closeEditor(activeEditor))
+ return false;
+
+ // select first tab
+ if (!tabPane.getTabs().isEmpty())
+ tabPane.getSelectionModel().select(0);
+
+ // try to close all tabs
+ for (FileEditor fileEditor : allEditors) {
+ if (fileEditor == activeEditor)
+ continue;
+
+ if (!closeEditor(fileEditor))
+ return false;
+ }
+
+ return tabPane.getTabs().isEmpty();
+ }
+
+ private FileEditor[] getAllEditors() {
+ ObservableList<Tab> tabs = tabPane.getTabs();
+ FileEditor[] allEditors = new FileEditor[tabs.size()];
+ for (int i = 0; i < tabs.size(); i++)
+ allEditors[i] = (FileEditor) tabs.get(i).getUserData();
+ return allEditors;
}
src/main/java/org/markdownwriterfx/MainWindow.java
package org.markdownwriterfx;
-import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.event.ActionEvent;
+import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
+import javafx.stage.Window;
+import javafx.stage.WindowEvent;
import de.jensd.fx.glyphs.GlyphIcons;
import de.jensd.fx.glyphs.GlyphsDude;
scene = new Scene(borderPane);
+ scene.windowProperty().addListener((observable, oldWindow, newWindow) -> {
+ newWindow.setOnCloseRequest(e -> {
+ if (!fileEditorTabPane.closeAllEditors())
+ e.consume();
+ });
+ });
fileNew();
private void fileExit() {
- Platform.exit();
+ Window window = scene.getWindow();
+ Event.fireEvent(window, new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));
}