package editor;
import java.io.*;
import java.util.*;
import java.nio.file.*;
import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.scene.control.*;
import javafx.scene.text.*;
import javafx.scene.input.*;
import javafx.geometry.*;
public class Editor extends Application {
private Stage primaryStage;
private TextArea textArea;
private FontDialog fontDialog;
private Menu mFile;
private Menu mFileNew;
private MenuItem miFileNewEmpty;
private MenuItem miFileNewRandom;
private MenuItem miFileOpen;
private MenuItem miFileSave;
private MenuItem miFileSaveAs;
private MenuItem miFileExit;
private Menu mFormat;
private MenuItem miFormatFont;
private CheckMenuItem miFormatWrap;
private ContextMenu contextMenu;
private MenuItem cmiFormatFont;
private CheckMenuItem cmiFormatWrap;
private File openedFile;
private boolean openedFileChanged;
private String fontFamily = "Tahoma";
private FontWeight fontWeight = FontWeight.NORMAL;
private FontPosture fontPosture = FontPosture.REGULAR;
private double fontSize = 16;
private static final int N = 1000; // V metode newRandomAction budeme generovat N riadkov o N nahodnych cifrach
private void updateOpenedFileInformation(File file, boolean hasChanged) {
openedFile = file;
openedFileChanged = hasChanged;
miFileSave.setDisable(!hasChanged);
updatePrimaryStageTitle();
}
private void updatePrimaryStageTitle() {
StringBuilder title = new StringBuilder("Textový editor (");
if (openedFile == null) {
title.append("neuložené v žiadnom súbore");
} else {
title.append(openedFile.getName());
}
title.append(")");
if (openedFileChanged) {
title.append("*");
}
primaryStage.setTitle(title.toString());
}
private void applyFont() {
textArea.setFont(Font.font(fontFamily, fontWeight, fontPosture, fontSize));
}
private void handleTextAreaChange() {
if (!openedFileChanged) {
updateOpenedFileInformation(openedFile, true);
}
}
private boolean saveBeforeClosingAlert() {
if (openedFileChanged) { // Ak dokument nie je ulozeny
Alert alert = new Alert(Alert.AlertType.CONFIRMATION); // Vytvor dialog typu Alert, variant CONFIRMATION
alert.setTitle("Uložiť súbor?"); // Nastav titulok dialogu
alert.setHeaderText(null); // Dialog nebude mat ziaden "nadpis"
alert.setContentText("Uložiť zmeny v súbore?"); // Nastav text dialogu
ButtonType buttonTypeYes = new ButtonType("Áno"); // Vytvor instancie reprezentujuce typy tlacidiel
ButtonType buttonTypeNo = new ButtonType("Nie");
// Vdaka druhemu argumentu sa bude ako tlacidlo "Zrusit" spravat aj "krizik" v dialogovom okne vpravo hore:
ButtonType buttonTypeCancel = new ButtonType("Zrušiť", ButtonBar.ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeYes, buttonTypeNo, buttonTypeCancel); // Nastav typy tlacidiel
Optional<ButtonType> result = alert.showAndWait(); // Zobraz dialog a cakaj, kym sa zavrie
if (result.get() == buttonTypeYes) { // Pokracuj podla typu stlaceneho tlacidla
return saveAction();
} else if (result.get() == buttonTypeNo) {
return true;
} else {
return false;
}
} else { // Ak je dokument ulozeny, netreba robit nic
return true;
}
}
/**
* Pomocna metoda, ktora vytvori dialog typu FileChooser a prednastavi niektore jeho vlastnosti.
* @return Vytvoreny dialog typu FileChooser.
*/
private FileChooser prepareFileChooser() {
FileChooser fileChooser = new FileChooser(); // Vytvorenie dialogoveho okna
fileChooser.setInitialDirectory(new File(System.getProperty("user.dir"))); // Nastavenie vychodzieho adresara
fileChooser.getExtensionFilters().addAll( // Filtre na pripony
new FileChooser.ExtensionFilter("Textové súbory (*.txt)", "*.txt"),
new FileChooser.ExtensionFilter("Všetky súbory (*.*)", "*.*"));
return fileChooser;
}
/**
* Pomocna metoda realizujuca vyber suboru na otvorenie.
* @return Vybrany subor alebo null v pripade, ze ziaden subor vybrany nebol.
*/
private File chooseFileToOpen() {
FileChooser fileChooser = prepareFileChooser();
fileChooser.setTitle("Otvoriť");
return fileChooser.showOpenDialog(primaryStage);
}
/**
* Pomocna metoda realizujuca vyber suboru na ulozenie.
* @return Vybrany subor alebo null v pripade, ze ziaden subor vybrany nebol.
*/
private File chooseFileToSave() {
FileChooser fileChooser = prepareFileChooser();
fileChooser.setTitle("Uložiť");
return fileChooser.showSaveDialog(primaryStage);
}
private String loadFromFile(File file) throws IOException {
return Files.readString(Paths.get(file.getPath()));
}
private void writeToFile(File file, String s) throws IOException {
Files.writeString(Paths.get(file.getPath()), s);
}
private boolean newEmptyAction() {
if (saveBeforeClosingAlert()) { // Pokracuj len ak sa podarilo zavriet dokument
updateOpenedFileInformation(null, true); // Nebude teraz otvoreny ziaden subor...
textArea.clear(); // Zmazeme obsah textoveho priestoru textArea
return true;
} else {
return false;
}
}
private boolean newRandomAction() {
if (newEmptyAction()) { // Skus vytvorit novy subor a pokracuj len, ak sa to podarilo
StringBuilder builder = new StringBuilder(); // Vygeneruj retazec o N x N nahodnych cifrach
Random random = new Random();
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
builder.append(random.nextInt(10));
}
builder.append(System.lineSeparator());
}
textArea.setText(builder.toString()); // Vypis vygenerovany retazec do textoveho priestoru textArea
return true;
} else {
return false;
}
}
private boolean openAction() {
if (saveBeforeClosingAlert()) { // Ak sa podarilo zavriet dokument
File file = chooseFileToOpen(); // Vyber subor na otvorenie
if (file != null) { // Ak bol nejaky subor vybrany ...
try {
textArea.setText(loadFromFile(file)); // ... vypis jeho obsah do textArea
updateOpenedFileInformation(file, false); // Aktualizuj informacie o otvorenom subore
} catch (IOException e) {
System.err.println("Nieco sa pokazilo.");
}
return true;
} else {
return false;
}
} else {
return false;
}
}
private boolean saveAction() {
if (openedFile == null) { // Ak nebol otvoreny ziaden subor ...
return saveAsAction(); // ... realizuj to iste ako pri "Ulozit ako"
} else { // V opacnom pripade ...
try {
writeToFile(openedFile, textArea.getText()); // ... prepis aktualne otvoreny subor
updateOpenedFileInformation(openedFile, false); // Aktualizuj informacie o otvorenom subore
} catch (IOException e) {
System.err.println("Nieco sa pokazilo.");
}
return true;
}
}
private boolean saveAsAction() {
File file = chooseFileToSave(); // Vyber subor, do ktoreho sa ma ukladat
if (file != null) { // Ak bol nejaky subor vybrany ...
try {
writeToFile(file, textArea.getText()); // ... zapis don obsah textArea
updateOpenedFileInformation(file, false); // Aktualizuj informacie o otvorenom subore
} catch (IOException e) {
System.err.println("Nieco sa pokazilo.");
}
return true;
} else {
return false;
}
}
private boolean exitAction() {
if (saveBeforeClosingAlert()) { // Pokracuj len ak sa podarilo zavriet dokument
Platform.exit(); // Ukonci aplikaciu
return true;
} else {
return false;
}
}
private boolean fontAction() {
FontAttributes fontAttributes = fontDialog.showFontDialog(
new FontAttributes(fontFamily, fontWeight, fontPosture, fontSize));
if (fontAttributes != null) {
fontFamily = fontAttributes.getFamily();
fontWeight = fontAttributes.getWeight();
fontPosture = fontAttributes.getPosture();
fontSize = fontAttributes.getSize();
applyFont();
}
return true;
}
private boolean handleStageCloseRequest(WindowEvent event) {
if (saveBeforeClosingAlert()) { // Ak sa podarilo zavriet subor
return true;
} else { // Ak sa nepodarilo zavriet subor ...
event.consume(); // ... nechceme ani zavriet okno
return false;
}
}
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
BorderPane borderPane = new BorderPane();
Scene scene = new Scene(borderPane);
textArea = new TextArea();
borderPane.setCenter(textArea);
textArea.setPadding(new Insets(5, 5, 5, 5));
textArea.setPrefWidth(1000);
textArea.setPrefHeight(700);
applyFont();
textArea.textProperty().addListener((observable, oldValue, newValue) -> handleTextAreaChange());
MenuBar menuBar = new MenuBar();
borderPane.setTop(menuBar);
mFile = new Menu("Súbor");
mFileNew = new Menu("Nový");
miFileNewEmpty = new MenuItem("Prázdny súbor");
miFileNewRandom = new MenuItem("Náhodné cifry");
mFileNew.getItems().addAll(miFileNewEmpty, miFileNewRandom);
miFileOpen = new MenuItem("Otvoriť...");
miFileSave = new MenuItem("Uložiť");
miFileSaveAs = new MenuItem("Uložiť ako...");
miFileExit = new MenuItem("Koniec");
mFile.getItems().addAll(mFileNew, miFileOpen, miFileSave, miFileSaveAs, new SeparatorMenuItem(), miFileExit);
mFormat = new Menu("Formát");
miFormatFont = new MenuItem("Písmo...");
miFormatWrap = new CheckMenuItem("Zalamovať riadky");
miFormatWrap.setSelected(false); // Nie je nutne, kedze false je tu vychodzia hodnota
mFormat.getItems().addAll(miFormatFont, miFormatWrap);
menuBar.getMenus().addAll(mFile, mFormat);
miFileNewEmpty.setAccelerator(new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN)); // Ctrl + N
miFileOpen.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.CONTROL_DOWN)); // Ctrl + O
miFileSave.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN)); // Ctrl + S
miFileNewEmpty.setOnAction(event -> newEmptyAction());
miFileNewRandom.setOnAction(event -> newRandomAction());
miFileOpen.setOnAction(event -> openAction());
miFileSave.setOnAction(event -> saveAction());
miFileSaveAs.setOnAction(event -> saveAsAction());
miFileExit.setOnAction(event -> exitAction());
miFormatFont.setOnAction(event -> fontAction());
contextMenu = new ContextMenu();
textArea.setContextMenu(contextMenu);
cmiFormatFont = new MenuItem("Formát písma...");
cmiFormatWrap = new CheckMenuItem("Zalamovať riadky");
cmiFormatWrap.setSelected(false);
contextMenu.getItems().addAll(cmiFormatFont, cmiFormatWrap);
cmiFormatFont.setOnAction(event -> fontAction());
textArea.wrapTextProperty().bindBidirectional(miFormatWrap.selectedProperty());
textArea.wrapTextProperty().bindBidirectional(cmiFormatWrap.selectedProperty());
fontDialog = new FontDialog();
updateOpenedFileInformation(null, true);
primaryStage.setOnCloseRequest(event -> handleStageCloseRequest(event));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}