package control; import imp.*; import graph.*; import algorithmen.*; import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.io.FileWriter; import javafx.fxml.*; import javafx.scene.control.*; import javafx.scene.control.Alert.AlertType; import javafx.event.*; import javafx.scene.input.MouseEvent; import javafx.scene.layout.*; import javafx.scene.Node; import javafx.scene.text.*; import javafx.geometry.Pos; import javafx.stage.*; // Dateiöffnen / Speichern-Dialog import java.io.File; import java.nio.file.*; import javafx.stage.FileChooser.ExtensionFilter; import javafx.scene.image.Image; import javafx.geometry.Rectangle2D; import java.util.List; import java.util.ArrayList; import javafx.collections.ObservableList; /** * Die Klasse Controller stellt den Controller des Hauptfensters / Menu dar. * * @author Thomas Schaller * @version 03.03.2023 (v7.1) * v7.0: Die aktuelle Bildschirmposition und der angezeigte Graph werden in config.csv abgelegt. * v7.1: Verzeichnisauswahl für Laden/Speichern verbessert */ public class Controller { private String version = "7.0 (Februar 2023)"; private String pfad; // Pfad der aktuell angezeigten Datei @FXML private TabPane tpRekursionen; @FXML private CheckMenuItem mOptionKnotenwerte; @FXML private CheckMenuItem mOptionKnotenname; @FXML private CheckMenuItem mOptionKantengewichte; @FXML private CheckMenuItem mOptionKnoteninfo; @FXML private CheckMenuItem mOptionBild; @FXML private CheckMenuItem mHilfefenster; @FXML private MenuItem mmSpeichern; @FXML private Menu mmBearbeiten; @FXML private Menu mmExperimentieren; @FXML private Menu mmSimulieren; @FXML private Menu mmZuruecksetzen; @FXML private Menu mmAnsicht; private FileChooser dateidialog; private Graph graph; private GraphOptions options; private Stage stage; public void initialize() { dateidialog = new FileChooser(); dateidialog.setInitialDirectory(new File("beispielgraphen")); oeffneHauptTab(); mNeuerGraph(null); tpRekursionen.getSelectionModel().selectedItemProperty(). addListener((value, tabOld, tabNew) -> changeTab(tabOld, tabNew)); BufferedReader in =null; try{ in = new BufferedReader(new FileReader("config.csv")); String fullScreen = in.readLine(); String posSize = in.readLine(); String[] ps = posSize.split(","); Rectangle2D ss = Screen.getPrimary().getBounds(); stage.setX(Double.parseDouble(ps[0])); stage.setY(Double.parseDouble(ps[1])); stage.setWidth(Math.min(Double.parseDouble(ps[2]), ss.getWidth()-Double.parseDouble(ps[0]))); stage.setHeight(Math.min(Double.parseDouble(ps[3]), ss.getHeight()-Double.parseDouble(ps[1]))); String[] fs = fullScreen.split(","); if(fs[0].equals("true")) stage.setFullScreen(true); if(fs[1].equals("true")) stage.setMaximized(true); pfad = in.readLine(); File f = new File(pfad); f.getCanonicalPath(); if(!pfad.isBlank() && f.exists()){ graphLaden(pfad); dateidialog.setInitialDirectory((f.getAbsoluteFile()).getParentFile()); } else { pfad = ""; } } catch(Exception e) { pfad = ""; dateidialog.setInitialDirectory(new File("beispielgraphen")); } finally{ try{if(in != null) in.close();} catch(IOException e) {} showTitle(); } } public void saveAktConfig() { PrintWriter pWriter = null; String s = "config.csv"; try { pWriter = new PrintWriter(new FileWriter(s)); pWriter.println(stage.isFullScreen()+","+stage.isMaximized()); stage.setFullScreen(false); stage.setMaximized(false); pWriter.println(stage.getX()+","+stage.getY()+","+stage.getWidth()+","+ stage.getHeight()); pWriter.println(pfad); } catch (IOException ioe) { ioe.printStackTrace(); } finally { if (pWriter != null) { pWriter.flush(); pWriter.close(); } } } private void changeTab(Tab tabOld, Tab tabNew) { if(tpRekursionen.getTabs().indexOf(tabNew)1) tpRekursionen.getTabs().remove(1); TabMitController tc = (TabMitController) (tpRekursionen.getTabs().get(0)); graph = new Graph(); options = new GraphOptions(graph); tc.setGraph(graph, options); pfad = ""; showTitle(); menuChangeAnsicht(); } void schliesseTabs() { while(tpRekursionen.getTabs().size()>1) { TabMitController tc = (TabMitController) (tpRekursionen.getTabs().get(1)); if(tc instanceof SimulationTabMitController) { ((SimulationTabMitController) tc).showHilfe(false); } tpRekursionen.getTabs().remove(1); } } @FXML void mBearbeiten(MouseEvent event) { try { // try-catch ist notwendig, um Fehler durch fehlende Dateien abzufangen. schliesseTabs(); EditTabMitController newtab = new EditTabMitController(graph, options); newtab.setText("Bearbeiten"); tpRekursionen.getTabs().add(newtab); FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/edittab.fxml")); loader.setController(newtab); newtab.setContent((Node) loader.load()); tpRekursionen.getSelectionModel().select(newtab); } catch(Exception e) { //System.out.println(e); } } @FXML void mSimuliere(MouseEvent event) { try { // try-catch ist notwendig, um Fehler durch fehlende Dateien abzufangen. schliesseTabs(); SimulationTabMitController newtab = new SimulationTabMitController(graph, options); newtab.setText("Algorithmen-Simulation"); tpRekursionen.getTabs().add(newtab); FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/simulationstab.fxml")); loader.setController(newtab); newtab.setContent((Node) loader.load()); tpRekursionen.getSelectionModel().select(newtab); } catch(Exception e) { // System.out.println(e); } } @FXML void mExperimentiereKanten(ActionEvent event) { schliesseTabs(); GraphOptions neu = options.copy(); neu.bildAnzeigen = false; neu.auswahl = 0; neu.fokusArt = 1; neu.parent = null; // neu.markiert = Auswahl.BELIEBIG; // neu.geloescht = Auswahl.BELIEBIG; // neu.besucht = Auswahl.BELIEBIG; TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.tabOeffnen(neu); } @FXML void mExperimentiereKnoten(ActionEvent event) { schliesseTabs(); GraphOptions neu = options.copy(); neu.bildAnzeigen = false; neu.auswahl = 0; neu.fokusArt = 0; neu.parent = null; if(neu.farbenKanten[0].equals("invisible")) neu.farbenKanten[0]="808080"; TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.tabOeffnen(neu); } @FXML void mExperimentiereAuswahl(ActionEvent event) { schliesseTabs(); GraphOptions neu = options.copy(); neu.bildAnzeigen = false; neu.auswahl = 2; TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); if(tc.viewer.getSelectedKnoten() != null) { neu.fokusArt = 0; // Knoten neu.parent = tc.viewer.getSelectedKnoten(); tc.tabOeffnen(neu); } else { if(tc.viewer.getSelectedKante() != null) { neu.fokusArt = 1; //Kante neu.parent = tc.viewer.getSelectedKante(); tc.tabOeffnen(neu); } } } @FXML public void mBeenden(ActionEvent event) { saveAktConfig(); schliesseTabs(); ((Stage)tpRekursionen.getScene().getWindow()).close(); System.exit(0); } void menuChangeAnsicht() { TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); mOptionBild.setSelected(options.bildAnzeigen); mOptionKantengewichte.setSelected(options.showEdgeWeights); mOptionKnotenname.setSelected(options.showVertexText); mOptionKnotenwerte.setSelected(options.showVertexValue); mOptionKnoteninfo.setSelected(options.showVertexInfo); mmSpeichern.setDisable(!tc.getText().equals("Bearbeiten")); /* mmBearbeiten.setDisabled(!tc.getText().equals("Graph")); mmExperimentieren.setVisible(tc.getText().equals("Graph")); mmSimulieren.setVisible(tc.getText().equals("Graph")); mmZuruecksetzen.setVisible(!tc.getText().equals("Bearbeiten")); */ mmAnsicht.setDisable(tc.getText().equals("Bearbeiten")); if(tc.getText().equals("Algorithmen-Simulation")) { mHilfefenster.setDisable(false); } else { mHilfefenster.setSelected(false); mHilfefenster.setDisable(true); } } @FXML void mChangeOptionBild(ActionEvent event) { TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); options.bildAnzeigen = mOptionBild.isSelected(); tc.update(); } @FXML void mChangeOptionKantengewichte(ActionEvent event) { TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); options.showEdgeWeights = mOptionKantengewichte.isSelected(); tc.update(); } @FXML void mChangeOptionKnoteninfo(ActionEvent event) { TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); options.showVertexInfo = mOptionKnoteninfo.isSelected(); tc.update(); } @FXML void mChangeOptionKnotenname(ActionEvent event) { TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); options.showVertexText = mOptionKnotenname.isSelected(); if(options.showVertexText) { options.showVertexValue = false; mOptionKnotenwerte.setSelected(false); } tc.update(); } @FXML void mChangeOptionKnotenwerte(ActionEvent event) { TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); options.showVertexValue = mOptionKnotenwerte.isSelected(); if(options.showVertexValue) { options.showVertexText = false; mOptionKnotenname.setSelected(false); } tc.update(); } @FXML void mChangeHilfefenster(ActionEvent event) { TabMitController tc = (TabMitController) (tpRekursionen.getTabs().get(tpRekursionen.getTabs().size()-1)); if(tc instanceof SimulationTabMitController) { ((SimulationTabMitController) tc).showHilfe(mHilfefenster.isSelected()); } } @FXML void mOeffnen(ActionEvent event) { dateidialog.getExtensionFilters().clear(); dateidialog.getExtensionFilters().add(new ExtensionFilter("Graph-Datei (*.csv)", "*.csv")); File file = dateidialog.showOpenDialog(null); if (file != null) { graphLaden(file.getAbsolutePath()); dateidialog.setInitialDirectory(file.getAbsoluteFile().getParentFile()); } } void graphLaden(String p) { while(tpRekursionen.getTabs().size()>2) tpRekursionen.getTabs().remove(1); TabMitController tc = (TabMitController) (tpRekursionen.getTabs().get(0)); File f = new File(p); if(f.exists() ){ pfad = p; Table csvParser = new Table(pfad,"",',','"'); graph = new Graph(); graph.ladeGraph(csvParser); options = new GraphOptions(graph); options.ladeGraph(csvParser); tc.setGraph(graph, options); if(tpRekursionen.getTabs().size()>1){ tc = (TabMitController) (tpRekursionen.getTabs().get(1)); tc.setGraph(graph, options); } } menuChangeAnsicht(); showTitle(); } public void showTitle() { if(stage!=null) { if(pfad == null || pfad.equals("")) { stage.setTitle("GraphTester by Thomas Schaller - Version "+version); } else { String[] arr = pfad.split("[/\\\\]"); String dateiname = arr[arr.length-1]; stage.setTitle("GraphTester by Thomas Schaller - Version "+version+" - "+dateiname); } } } @FXML void mSchliessen(ActionEvent event) { mNeuerGraph(event); } @FXML void mSpeichern(ActionEvent event) { dateidialog.getExtensionFilters().clear(); dateidialog.getExtensionFilters().add(new ExtensionFilter("Graph-Datei (*.csv)", "*.csv")); if(!pfad.isBlank()) dateidialog.setInitialFileName(new File(pfad).getName()); else dateidialog.setInitialFileName(""); File file = dateidialog.showSaveDialog(null); if (file != null) { try{ TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); GraphOptions options = tc.getGraphOptions(); String text = options.getText(); text += "#\n# Graph:\n"; text +=graph.toCSVString(options.saveAsMatrix); String dateiName = file.getAbsolutePath(); String name = dateiName.substring(dateiName.lastIndexOf("\\")+1); if(name.contains(".")) dateiName = dateiName.substring(0, dateiName.lastIndexOf(".")); Files.write(Paths.get(file.getAbsolutePath()), text.getBytes()); pfad = file.getAbsolutePath(); dateidialog.setInitialDirectory(file.getAbsoluteFile().getParentFile()); showTitle(); } catch(Exception e) { } } } @FXML void mBildExportieren(ActionEvent event) { dateidialog.getExtensionFilters().clear(); dateidialog.getExtensionFilters().add(new ExtensionFilter("Bild des Graphen", "*.png","*.gif")); File file = dateidialog.showSaveDialog(null); if (file != null) { try{ TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); Picture p = tc.getViewer().updateImage(); String dateiName = file.getAbsolutePath(); p.save(dateiName); } catch(Exception e) { } } } @FXML void mUeber(ActionEvent event) { Alert alert = new Alert(AlertType.INFORMATION); alert.setTitle("Graphtester"); alert.setHeaderText(null); alert.setContentText("Mit diesem Programm können Sie Graphen modellieren, Graphenalgorithmen von Hand durchspielen oder implementierte Algorithmen schrittweise ausführen.\n\n"+ "Version: "+version+"\nThomas Schaller\nLandesfachgruppe Informatik (ZSL BW)\n"+ "Lizenz: CC BY-NC 4.0 (https://creativecommons.org/licenses/by-nc/4.0/deed.de)\n\n"+ "3rd Party:\n CommonsIO.jar, csv.jar, JDom.jar\n Lizenzinfo: siehe Ordner '+libs'" ); Image icon = new Image("view/icon.png"); Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); stage.getIcons().add(icon); alert.showAndWait(); } @FXML void mResetAlles(ActionEvent event) { graph.initialisiereAlleKanten(); graph.initialisiereAlleKnoten(); TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } @FXML void mResetBesucht(ActionEvent event) { for(Knoten k : graph.getAlleKnoten()) { k.setBesucht(false); } TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } @FXML void mResetFarbe(ActionEvent event) { for(Knoten k : graph.getAlleKnoten()) { k.setFarbeAutomatisch(true); } TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } @FXML void mResetGeloescht(ActionEvent event) { for(Kante k : graph.getAlleKanten()) { k.setGeloescht(false); } TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } @FXML void mResetKantenmarkierung(ActionEvent event) { for(Kante k : graph.getAlleKanten()) { k.setMarkiert(false); } TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } @FXML void mResetMarkierung(ActionEvent event) { for(Knoten k : graph.getAlleKnoten()) { k.setMarkiert(false); } TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } @FXML void mResetWert(ActionEvent event) { for(Knoten k : graph.getAlleKnoten()) { k.setWert(0.0); } TabMitController tc = (TabMitController) (tpRekursionen.getSelectionModel().getSelectedItem()); tc.update(); } }