First Commit (Fobi)

This commit is contained in:
Frank Schiebel 2021-07-12 14:04:20 +02:00
commit 2bff291a51
336 changed files with 88781 additions and 0 deletions

66
control/Controller.ctxt Normal file
View file

@ -0,0 +1,66 @@
#BlueJ class context
comment0.target=Controller
comment0.text=\r\n\ Die\ Klasse\ Controller\ stellt\ den\ Controller\ des\ Hauptfensters\ /\ Menu\ dar.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=
comment1.target=void\ initialize()
comment10.params=event
comment10.target=void\ mExperimentiereAuswahl(javafx.event.ActionEvent)
comment11.params=event
comment11.target=void\ mBeenden(javafx.event.ActionEvent)
comment12.params=
comment12.target=void\ menuChangeAnsicht()
comment13.params=event
comment13.target=void\ mChangeOptionBild(javafx.event.ActionEvent)
comment14.params=event
comment14.target=void\ mChangeOptionKantengewichte(javafx.event.ActionEvent)
comment15.params=event
comment15.target=void\ mChangeOptionKnoteninfo(javafx.event.ActionEvent)
comment16.params=event
comment16.target=void\ mChangeOptionKnotenname(javafx.event.ActionEvent)
comment17.params=event
comment17.target=void\ mChangeOptionKnotenwerte(javafx.event.ActionEvent)
comment18.params=event
comment18.target=void\ mChangeHilfefenster(javafx.event.ActionEvent)
comment19.params=event
comment19.target=void\ mOeffnen(javafx.event.ActionEvent)
comment2.params=tabOld\ tabNew
comment2.target=void\ changeTab(javafx.scene.control.Tab,\ javafx.scene.control.Tab)
comment20.params=dateiname
comment20.target=void\ graphLaden(java.lang.String)
comment21.params=event
comment21.target=void\ mSchliessen(javafx.event.ActionEvent)
comment22.params=event
comment22.target=void\ mSpeichern(javafx.event.ActionEvent)
comment23.params=event
comment23.target=void\ mBildExportieren(javafx.event.ActionEvent)
comment24.params=event
comment24.target=void\ mUeber(javafx.event.ActionEvent)
comment25.params=event
comment25.target=void\ mResetAlles(javafx.event.ActionEvent)
comment26.params=event
comment26.target=void\ mResetBesucht(javafx.event.ActionEvent)
comment27.params=event
comment27.target=void\ mResetFarbe(javafx.event.ActionEvent)
comment28.params=event
comment28.target=void\ mResetGeloescht(javafx.event.ActionEvent)
comment29.params=event
comment29.target=void\ mResetKantenmarkierung(javafx.event.ActionEvent)
comment3.params=
comment3.target=void\ oeffneHauptTab()
comment30.params=event
comment30.target=void\ mResetMarkierung(javafx.event.ActionEvent)
comment31.params=event
comment31.target=void\ mResetWert(javafx.event.ActionEvent)
comment4.params=event
comment4.target=void\ mNeuerGraph(javafx.event.ActionEvent)
comment5.params=
comment5.target=void\ schliesseTabs()
comment6.params=event
comment6.target=void\ mBearbeiten(javafx.scene.input.MouseEvent)
comment7.params=event
comment7.target=void\ mSimuliere(javafx.scene.input.MouseEvent)
comment8.params=event
comment8.target=void\ mExperimentiereKanten(javafx.event.ActionEvent)
comment9.params=event
comment9.target=void\ mExperimentiereKnoten(javafx.event.ActionEvent)
numComments=32

480
control/Controller.java Normal file
View file

@ -0,0 +1,480 @@
package control;
import imp.*;
import graph.*;
import algorithmen.*;
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 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 v6.7 (9.12.2020)
*/
public class Controller {
private String version = "6.8 (Februar 2021)";
@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;
public void initialize() {
dateidialog = new FileChooser();
dateidialog.setInitialDirectory(new File("beispielgraphen"));
oeffneHauptTab();
mNeuerGraph(null);
tpRekursionen.getSelectionModel().selectedItemProperty().
addListener((value, tabOld, tabNew) -> changeTab(tabOld, tabNew));
}
private void changeTab(Tab tabOld, Tab tabNew) {
if(tpRekursionen.getTabs().indexOf(tabNew)<tpRekursionen.getTabs().size()-2) {
tpRekursionen.getSelectionModel().select(tabOld);
} else {
if(tpRekursionen.getTabs().indexOf(tabNew)==tpRekursionen.getTabs().size()-2) {
tpRekursionen.getTabs().remove(tpRekursionen.getTabs().size()-1);
}
((TabMitController) tabNew).update();
this.menuChangeAnsicht();
}
}
private void oeffneHauptTab() {
try { // try-catch ist notwendig, um Fehler durch fehlende Dateien abzufangen.
HauptTabMitController newtab = new HauptTabMitController(graph, options);
newtab.setText("Graph");
tpRekursionen.getTabs().add(newtab);
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/haupttab.fxml"));
loader.setController(newtab);
newtab.setContent((Node) loader.load());
tpRekursionen.getSelectionModel().select(newtab);
}
catch(Exception e) {
System.out.println(e);
}
}
@FXML
void mNeuerGraph(ActionEvent event) {
while(tpRekursionen.getTabs().size()>1) tpRekursionen.getTabs().remove(1);
TabMitController tc = (TabMitController) (tpRekursionen.getTabs().get(0));
options = new GraphOptions();
graph = new Graph();
tc.setGraph(graph, options);
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) {
schliesseTabs();
((Stage)tpRekursionen.getScene().getWindow()).close();
}
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) {
File file = dateidialog.showOpenDialog(null);
if (file != null) {
graphLaden(file.getAbsolutePath());
}
}
void graphLaden(String dateiname) {
while(tpRekursionen.getTabs().size()>2) tpRekursionen.getTabs().remove(1);
TabMitController tc = (TabMitController) (tpRekursionen.getTabs().get(0));
options = new GraphOptions();
Table csvParser = new Table(dateiname,"",',','"');
options.ladeGraph(csvParser);
graph = new Graph();
graph.ladeGraph(csvParser);
tc.setGraph(graph, options);
if(tpRekursionen.getTabs().size()>1){
tc = (TabMitController) (tpRekursionen.getTabs().get(1));
tc.setGraph(graph, options);
}
menuChangeAnsicht();
}
@FXML
void mSchliessen(ActionEvent event) {
mNeuerGraph(event);
}
@FXML
void mSpeichern(ActionEvent event) {
dateidialog.getExtensionFilters().clear();
dateidialog.getExtensionFilters().add(new ExtensionFilter("Graph-Datei (*.csv)", "*.csv"));
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());
} 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();
}
}

View file

@ -0,0 +1,32 @@
#BlueJ class context
comment0.target=EditTabMitController
comment0.text=\r\n\ Die\ Klasse\ EditTabMitController\ stellt\ einen\ Tab\ inclusive\ ihres\ Controllers\r\n\ zur\ Editierung\ eines\ Graphs\ dar.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=graph\ options
comment1.target=EditTabMitController(graph.Graph,\ graph.GraphOptions)
comment10.params=event
comment10.target=void\ bDistanzenBestimmen(javafx.event.ActionEvent)
comment11.params=event
comment11.target=void\ graphClicked(javafx.scene.input.MouseEvent)
comment12.params=
comment12.target=void\ mLoesche()
comment13.params=
comment13.target=void\ mWertAendern()
comment14.params=
comment14.target=void\ mInfotextAendern()
comment2.params=
comment2.target=void\ initialize()
comment3.params=size
comment3.target=void\ sGroesseAendern(java.lang.Number)
comment4.params=gerichtet
comment4.target=void\ setGerichtet(boolean)
comment5.params=gewichtet
comment5.target=void\ setGewichtet(boolean)
comment6.params=anzeigen
comment6.target=void\ setInfotext(boolean)
comment7.params=t
comment7.target=void\ setKnotenTyp(javafx.scene.control.Toggle)
comment8.params=event
comment8.target=void\ bBildLaden(javafx.event.ActionEvent)
comment9.params=event
comment9.target=void\ bBildLoeschen(javafx.event.ActionEvent)
numComments=15

View file

@ -0,0 +1,262 @@
package control;
import imp.*;
import graph.*;
import javafx.fxml.*;
import javafx.scene.control.*;
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.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
import javafx.collections.ObservableList;
import java.util.Optional;
/**
* Die Klasse EditTabMitController stellt einen Tab inclusive ihres Controllers
* zur Editierung eines Graphs dar.
*
* @author Thomas Schaller
* @version v6.7 (9.12.2020)
*/
public class EditTabMitController extends TabMitController {
public EditTabMitController(Graph graph, GraphOptions options) {
this.graph = graph;
this.options = options;
}
@FXML
private CheckBox cbGerichtet;
@FXML
private CheckBox cbGewichtet;
@FXML
private RadioButton rLeer;
@FXML
private ToggleGroup tgKnoten;
@FXML
private RadioButton rNummer;
@FXML
private RadioButton rWert;
@FXML
private CheckBox cbInfotext;
@FXML
private Label lBildname;
@FXML
private RadioButton rbMatrix;
@FXML
private ToggleGroup tgMatrixListe;
@FXML
private RadioButton rbListe;
@FXML
private Slider sGroesse;
private FileChooser dateidialog;
public void initialize() {
dateidialog = new FileChooser();
dateidialog.setInitialDirectory(new File("images"));
options.showEdgeWeights = graph.isGewichtet();
options.bildAnzeigen = true;
options.showVertexInfo = true;
viewer.setGraph(graph,options);
viewer.setEditable();
cbGerichtet.setSelected(graph.isGerichtet());
cbGewichtet.setSelected(graph.isGewichtet());
cbInfotext.setSelected(options.showVertexInfo);
tgKnoten.selectToggle(rLeer);
if(options.showVertexValue) { tgKnoten.selectToggle(rWert); }
if(options.showVertexText) { tgKnoten.selectToggle(rNummer); }
cbGerichtet.selectedProperty().addListener((cb, oldValue, newValue) -> setGerichtet(newValue));
cbGewichtet.selectedProperty().addListener((cb, oldValue, newValue) -> setGewichtet(newValue));
cbInfotext.selectedProperty().addListener((cb, oldValue, newValue) -> setInfotext(newValue));
tgKnoten.selectedToggleProperty().addListener((tg, oldValue, newValue) -> setKnotenTyp(newValue));
if(options.saveAsMatrix)
tgMatrixListe.selectToggle(rbMatrix);
else
tgMatrixListe.selectToggle(rbListe);
tgMatrixListe.selectedToggleProperty().addListener((tg, oldValue, newValue) -> options.saveAsMatrix = (newValue == rbMatrix));
lBildname.setText(options.bildDatei);
super.initialize();
// this.setOnSelectionChanged(e -> {if(!this.isSelected()) this.getTabPane().getTabs().remove(this);});
sGroesse.valueProperty().addListener((s,oldValue,newValue) -> sGroesseAendern(newValue));
}
void sGroesseAendern(Number size) {
options.vertexSize = size.intValue();
update();
}
void setGerichtet(boolean gerichtet) {
graph.setGerichtet(gerichtet);
update();
}
void setGewichtet(boolean gewichtet) {
graph.setGewichtet(gewichtet);
options.showEdgeWeights = gewichtet;
update();
}
void setInfotext(boolean anzeigen) {
options.showVertexInfo = anzeigen;
update();
}
void setKnotenTyp(Toggle t) {
if(t == rWert) { options.showVertexValue = true; options.showVertexText = false;}
if(t == rNummer) { options.showVertexValue = false; options.showVertexText = true;}
if(t == rLeer) { options.showVertexValue = false; options.showVertexText = false;}
update();
}
@FXML
void bBildLaden(ActionEvent event) {
String workingDir = System.getProperty("user.dir");
File file = dateidialog.showOpenDialog(null);
if (file != null) {
try{
Files.copy( file.toPath(), (new File(workingDir+"\\images\\"+file.getName())).toPath(), StandardCopyOption.REPLACE_EXISTING);
options.bildDatei = file.getName();
lBildname.setText(options.bildDatei);
update();
} catch( Exception e) {
System.out.println("Fehler beim Kopieren des Bildes");
}
}
}
@FXML
void bBildLoeschen(ActionEvent event) {
options.bildDatei = "";
lBildname.setText(options.bildDatei);
update();
}
@FXML
void bDistanzenBestimmen(ActionEvent event) {
for(Kante k: graph.getAlleKanten()) {
Knoten s = k.getStart();
Knoten z = k.getZiel();
k.setGewicht(Math.round(Math.sqrt((s.getX()-z.getX())*(s.getX()-z.getX())+
(s.getY()-z.getY())*(s.getY()-z.getY()))));
}
update();
}
@FXML
void graphClicked(MouseEvent event) { // MousePressed-Event
viewer.mouseClicked(event);
viewer.mouseDown(event);
if((viewer.getSelectedKnoten() != null || viewer.getSelectedKante() != null) && event.isSecondaryButtonDown()) { // Contextmenu
ContextMenu contextMenu = new ContextMenu();
MenuItem item1 = new MenuItem("Löschen");
item1.setOnAction(e -> this.mLoesche());
MenuItem item2 = new MenuItem("Gewicht ändern...");
item2.setOnAction(e -> this.mWertAendern());
MenuItem item3 = new MenuItem("Infotext ändern...");
item3.setOnAction(e -> this.mInfotextAendern());
// Add MenuItem to ContextMenu
contextMenu.getItems().clear();
contextMenu.getItems().add(item1);
if(viewer.getSelectedKante()!=null && graph.isGewichtet())
contextMenu.getItems().add(item2);
if (viewer.getSelectedKnoten() != null)
contextMenu.getItems().add( item3 );
contextMenu.show(viewer, event.getScreenX(), event.getScreenY());
}
}
public void mLoesche() {
if(viewer.getSelectedKnoten() != null) {
graph.entferneKnoten(viewer.getSelectedKnoten());
update();
}
if(viewer.getSelectedKante() != null) {
graph.entferneKante(viewer.getSelectedKante());
update();
}
}
public void mWertAendern() {
Knoten k = viewer.getSelectedKnoten();
Kante ka = viewer.getSelectedKante();
if(k != null || ka !=null) {
double v;
if(k != null) v = k.getDoubleWert();
else v = ka.getGewicht();
TextInputDialog dialog = new TextInputDialog(""+v);
dialog.setHeaderText(null);
dialog.setTitle("Wert ändern");
dialog.setContentText("Bitte geben Sie den neuen Wert ein:");
Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
try{
v = Double.parseDouble(result.get());
if(k != null) k.setWert(v);
else ka.setGewicht(v);
update();
} catch (Exception e) {
System.out.println("Keine Zahl eingegeben");
}
}
}
}
public void mInfotextAendern() {
Knoten k = viewer.getSelectedKnoten();
if(k != null ) {
TextInputDialog dialog = new TextInputDialog(k.getInfotext());
dialog.setHeaderText(null);
dialog.setTitle("Infotext ändern");
dialog.setContentText("Bitte geben Sie den Infotext ein:");
Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
String t = result.get();
t.replaceAll(",","");
k.setInfotext(t);
update();
}
}
}
}

View file

@ -0,0 +1,8 @@
#BlueJ class context
comment0.target=HauptTabMitController
comment0.text=\r\n\ Die\ Klasse\ HauptTabMitController\ stellt\ einen\ Tab\ inclusive\ ihres\ Controllers\r\n\ f\u00FCr\ das\ Hauptfenster\ des\ Graphentesters\ dar.\ Einzelne\ Knoten\ oder\ Kanten\ k\u00F6nnen\ \r\n\ selektiert\ werden.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=graph\ options
comment1.target=HauptTabMitController(graph.Graph,\ graph.GraphOptions)
comment2.params=
comment2.target=void\ initialize()
numComments=3

View file

@ -0,0 +1,56 @@
package control;
import imp.*;
import graph.*;
import algorithmen.*;
import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.event.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.stage.*; // Dateiöffnen / Speichern-Dialog
import java.io.File;
import java.util.List;
import java.util.regex.Pattern;
import javafx.collections.ObservableList;
/**
* Die Klasse HauptTabMitController stellt einen Tab inclusive ihres Controllers
* für das Hauptfenster des Graphentesters dar. Einzelne Knoten oder Kanten können
* selektiert werden.
*
* @author Thomas Schaller
* @version v6.7 (9.12.2020)
*/
public class HauptTabMitController extends TabMitController {
public HauptTabMitController(Graph graph, GraphOptions options) {
this.graph = graph;
this.options = options;
setClosable(false);
}
public void initialize() {
super.initialize();
}
}

36
control/Hilfefenster.ctxt Normal file
View file

@ -0,0 +1,36 @@
#BlueJ class context
comment0.target=Hilfefenster
comment0.text=\r\n\ Die\ Klasse\ Hilfefenster\ stellt\ ein\ Hilfefenster\ f\u00FCr\ die\ Simulation\ eines\r\n\ Algorithmus\ bereit.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=
comment1.target=void\ initialize()
comment10.params=
comment10.target=void\ run()
comment11.params=a
comment11.target=void\ setReviewAllowed(boolean)
comment12.params=
comment12.target=void\ showState()
comment13.params=
comment13.target=void\ run()
comment14.params=t\ search\ nr
comment14.target=int\ calculateIndex(javafx.scene.control.TreeItem,\ javafx.scene.control.TreeItem,\ int)
comment15.params=event
comment15.target=void\ bCopyClicked(javafx.event.ActionEvent)
comment16.params=t\ tab
comment16.target=java.lang.String\ generateClipboardContent(javafx.scene.control.TreeItem,\ java.lang.String)
comment2.params=gp
comment2.target=void\ setGraphPlotter(graph.GraphPlotter)
comment3.params=
comment3.target=void\ loescheAlles()
comment4.params=
comment4.target=void\ run()
comment5.params=text
comment5.target=void\ append(java.lang.String)
comment6.params=
comment6.target=void\ run()
comment7.params=
comment7.target=void\ indentMore()
comment8.params=
comment8.target=void\ run()
comment9.params=
comment9.target=void\ indentLess()
numComments=17

176
control/Hilfefenster.java Normal file
View file

@ -0,0 +1,176 @@
package control;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import javafx.scene.input.MouseEvent;
import javafx.event.ActionEvent;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import java.util.List;
import java.util.ArrayList;
import javafx.stage.*;
import java.util.ConcurrentModificationException;
import javafx.application.Platform;
import graph.*;
/**
* Die Klasse Hilfefenster stellt ein Hilfefenster für die Simulation eines
* Algorithmus bereit.
*
* @author Thomas Schaller
* @version v6.7 (9.12.2020)
*/
public class Hilfefenster extends Stage implements Hilfe{
@FXML
private TreeView<String> tvAblauf;
private List<TreeItem<String>> stufen;
private List<List<String>> zustaende;
private TreeItem<String> last;
private GraphPlotter gp;
private List<String> aktuell;
private boolean reviewAllowed;
public void initialize() {
loescheAlles();
zustaende = new ArrayList<List<String>>();
aktuell = null;
reviewAllowed = false;
tvAblauf.getSelectionModel().selectedIndexProperty().addListener((obs,oldValue, newValue)->showState());
}
public void setGraphPlotter(GraphPlotter gp) {
this.gp = gp;
}
public void loescheAlles() {
Platform.runLater(new Runnable() {
@Override
public void run() {
stufen = new ArrayList<TreeItem<String>>();
zustaende = new ArrayList<List<String>>();
TreeItem<String> root = new TreeItem<String>("Algorithmus");
root.setExpanded(true);
last = root;
tvAblauf.setRoot(root);
tvAblauf.setShowRoot(false);
stufen.add(root);
}
});
}
public void append(String text) {
List<String> status = gp.getGraph().getStatus();
Platform.runLater(new Runnable() {
@Override
public void run() {
last = new TreeItem<String>(text);
stufen.get(stufen.size()-1).getChildren().add(last);
zustaende.add(status);
}
});
}
public void indentMore() {
Platform.runLater(new Runnable() {
@Override
public void run() {
if(stufen.size() == 1) { // Hauptknoten
TreeItem parent = stufen.get(0);
List<TreeItem> children = parent.getChildren();
for(int i=children.size()-1; i >= 0; i--) {
TreeItem t = children.get(i);
if(t.isExpanded()) {
t.setExpanded(false);
break;
}
}
}
stufen.add(last);
last.setExpanded(true);
last.expandedProperty().addListener((b, o, n) -> showState());
}
});
}
public void indentLess() {
Platform.runLater(new Runnable() {
@Override
public void run() {
if(stufen.size() > 1) stufen.remove(stufen.size()-1);
}
});
}
public void setReviewAllowed(boolean a) {
this.reviewAllowed = a;
if(!reviewAllowed) tvAblauf.getSelectionModel().clearSelection();
}
public void showState() {
Platform.runLater(new Runnable() {
@Override
public void run() {
if(reviewAllowed && tvAblauf.getSelectionModel().getSelectedIndex()>=0) {
TreeItem s = tvAblauf.getSelectionModel().getSelectedItem();
if(!s.isExpanded()) { // suche das letzte Kind
while(s.getChildren().size()>0){
List<TreeItem> c = s.getChildren();
s = c.get(c.size()-1);
}
}
gp.getGraph().setStatus(zustaende.get(calculateIndex(tvAblauf.getRoot(), s ,0)-1));
gp.updateImage();
}
}
});
}
private int calculateIndex(TreeItem t, TreeItem search, int nr) {
if(t == search) return nr;
nr++;
List<TreeItem> children = t.getChildren();
for(TreeItem c : children) {
int i = calculateIndex(c, search, nr);
if(i>0) return i;
nr = -i;
}
return -nr;
}
@FXML
void bCopyClicked(ActionEvent event) {
final Clipboard clipboard = Clipboard.getSystemClipboard();
final ClipboardContent content = new ClipboardContent();
String s = "";
for(Object c : tvAblauf.getRoot().getChildren()) {
if(c instanceof TreeItem) {
s += generateClipboardContent((TreeItem) c, "");
}
}
content.putString(s);
clipboard.setContent(content);
}
private String generateClipboardContent(TreeItem t, String tab) {
String s = tab+t.getValue();
for(Object c : t.getChildren()) {
if(c instanceof TreeItem) {
s += generateClipboardContent((TreeItem) c, tab+" ");
}
}
return s;
}
}

View file

@ -0,0 +1,8 @@
#BlueJ class context
comment0.target=MyClassLoader
comment0.text=\r\n\ Hilfsklasse,\ um\ Algorithmen-Classen\ dynamisch\ nachladen\ zu\ k\u00F6nnen\ und\ \r\n\ aktualisierte\ Class-Dateien\ w\u00E4hrend\ der\ Laufzeit\ erneut\ laden\ zu\ k\u00F6nnen.\r\n\ \r\n\ @author\ Schaller\ (nach\ http\://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html)\r\n\ @version\ 16.02.2021\r\n
comment1.params=parent
comment1.target=MyClassLoader(java.lang.ClassLoader)
comment2.params=name
comment2.target=java.lang.Class\ loadClass(java.lang.String)
numComments=3

View file

@ -0,0 +1,53 @@
package control;
import java.io.*;
import java.net.*;
import java.util.regex.Pattern;
/**
* Hilfsklasse, um Algorithmen-Classen dynamisch nachladen zu können und
* aktualisierte Class-Dateien während der Laufzeit erneut laden zu können.
*
* @author Schaller (nach http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html)
* @version 16.02.2021
*/
public class MyClassLoader extends ClassLoader{
public MyClassLoader(ClassLoader parent) {
super(parent);
}
public Class loadClass(String name) throws ClassNotFoundException {
if(!name.contains("GraphAlgo_"))
return super.loadClass(name);
try {
URL myUrl = new URL("file:"+name.split(Pattern.quote("."))[0]+"/"+name.split(Pattern.quote("."))[1]+".class");
URLConnection connection = myUrl.openConnection();
InputStream input = connection.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int data = input.read();
while(data != -1){
buffer.write(data);
data = input.read();
}
input.close();
byte[] classData = buffer.toByteArray();
return defineClass(name, classData, 0, classData.length);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View file

@ -0,0 +1,24 @@
#BlueJ class context
comment0.target=SimulationTabMitController
comment0.text=\r\n\ Die\ Klasse\ SimulationTabMitController\ stellt\ einen\ Tab\ inclusive\ ihres\ Controllers\r\n\ zur\ Simulation\ eines\ Algorithmus\ dar.\ Der\ Algorithmus\ kann\ ausgew\u00E4hlt\ und\ schrittweise\ \r\n\ durchgef\u00FChrt\ werden.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=graph\ options
comment1.target=SimulationTabMitController(graph.Graph,\ graph.GraphOptions)
comment10.params=event
comment10.target=void\ mBreak(javafx.event.ActionEvent)
comment2.params=
comment2.target=void\ initialize()
comment3.params=
comment3.target=void\ afterClosing()
comment4.params=
comment4.target=void\ hilfefensterErzeugen()
comment5.params=b
comment5.target=void\ showHilfe(boolean)
comment6.params=graph\ options
comment6.target=void\ setGraph(graph.Graph,\ graph.GraphOptions)
comment7.params=event
comment7.target=void\ mReset(javafx.event.ActionEvent)
comment8.params=event
comment8.target=void\ mStep(javafx.event.ActionEvent)
comment9.params=event
comment9.target=void\ mStart(javafx.event.ActionEvent)
numComments=11

View file

@ -0,0 +1,280 @@
package control;
import imp.*;
import graph.*;
import algorithmen.*;
import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.event.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.stage.*; // Dateiöffnen / Speichern-Dialog
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.*;
import java.util.Collections;
import java.util.stream.Stream;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.regex.Pattern;
import javafx.collections.ObservableList;
/**
* Die Klasse SimulationTabMitController stellt einen Tab inclusive ihres Controllers
* zur Simulation eines Algorithmus dar. Der Algorithmus kann ausgewählt und schrittweise
* durchgeführt werden.
*
* @author Thomas Schaller
* @version v6.7 (9.12.2020)
*/
public class SimulationTabMitController extends TabMitController {
@FXML
private ComboBox<String> cbAlgorithmen;
@FXML
private Slider sSpeed;
@FXML
private Button bStep;
@FXML
private Button bStart;
@FXML
private Button bBreak;
@FXML
private Button bReset;
private GraphAlgo aktAlgo = null;
private ArrayList<String> algoNamen;
private Hilfefenster hilfe;
public SimulationTabMitController(Graph graph, GraphOptions options) {
this.graph = graph;
this.options = options;
this.setOnClosed((ev)->afterClosing());
}
public void initialize() {
this.algoNamen = new ArrayList<String>();
try {
File verzeichnis = new File("algorithmen");
if(verzeichnis != null) {
String[] entries = verzeichnis.list();
for (String name : entries) {
if (name.startsWith("GraphAlgo_") && name.endsWith(".class")){
Class c = Class.forName("algorithmen."+name.split(Pattern.quote("."))[0]);
GraphAlgo a = ((GraphAlgo)(c).getDeclaredConstructor().newInstance());
int i = 0;
while(i < cbAlgorithmen.getItems().size() && cbAlgorithmen.getItems().get(i).compareTo(a.getBezeichnung())<0)
i++;
//System.out.println("Algorithmus: "+a.getBezeichnung()+" geladen.");
cbAlgorithmen.getItems().add(i, a.getBezeichnung());
algoNamen.add(i, "algorithmen."+name.split(Pattern.quote("."))[0]);
}
} // end of for
}
verzeichnis = new File( "eigeneAlgorithmen" );
if(verzeichnis != null) {
String[] entries = verzeichnis.list();
for (String name : entries) {
if (name.startsWith("GraphAlgo_") && name.endsWith(".class")){
Class c = Class.forName("eigeneAlgorithmen."+name.split(Pattern.quote("."))[0]);
GraphAlgo a = ((GraphAlgo)(c).getDeclaredConstructor().newInstance());
int i = 0;
while(i < cbAlgorithmen.getItems().size() && cbAlgorithmen.getItems().get(i).compareTo(a.getBezeichnung())<0)
i++;
//System.out.println("Algorithmus: "+a.getBezeichnung()+" geladen.");
cbAlgorithmen.getItems().add(i, a.getBezeichnung());
algoNamen.add(i, "eigeneAlgorithmen."+name.split(Pattern.quote("."))[0]);
}
} // end of for
}
} catch(Exception e)
{
System.out.println("Exception " + e);
}
viewer.setGraph(graph,options);
this.hilfe = null;
this.aktAlgo = null;
super.initialize();
sSpeed.valueProperty().addListener(e -> { if (aktAlgo != null) aktAlgo.setSpeed(910-(int) (sSpeed.getValue()));});
bStart.managedProperty().bind(bStart.visibleProperty());
bBreak.managedProperty().bind(bBreak.visibleProperty());
bBreak.setVisible(false);
}
private void afterClosing() {
if (hilfe != null) hilfe.close();
}
private void hilfefensterErzeugen() {
try { // try-catch ist notwendig, um Fehler durch fehlende Dateien abzufangen.
if(hilfe != null) hilfe.close();
hilfe = new Hilfefenster();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/hilfefenster.fxml"));
loader.setController(hilfe);
Scene scene = new Scene((VBox) loader.load());
Image icon = new Image("/view/icon.png");
hilfe.getIcons().add(icon);
hilfe.setTitle("Hilfefenster");
hilfe.setScene(scene);
hilfe.setX(0);
hilfe.setY(0);
}
catch(Exception e) {
System.out.println(e);
}
}
public void showHilfe(boolean b) {
if(b) {
hilfefensterErzeugen();
hilfe.show();
if(aktAlgo != null && aktAlgo.isAlive()) {
aktAlgo.setGUIElemente(viewer,hilfe);
hilfe.append("Unvollständiger Ablauf");
}
}
else {
if (hilfe != null) hilfe.close();
hilfe = null;
}
}
public void setGraph(Graph graph, GraphOptions options) {
super.setGraph(graph,options);
mReset(null);
}
@FXML
void mReset(ActionEvent event) {
if(aktAlgo != null && aktAlgo.isAlive()) aktAlgo.stop();
graph.initialisiereAlleKnoten();
graph.initialisiereAlleKanten();
update();
//gp.setInfoText(gp.getGraph().toString());
bStep.setDisable(false);
bStart.setDisable(false);
bStart.setVisible(true);
bBreak.setVisible(false);
if (hilfe != null) hilfe.loescheAlles();
this.aktAlgo = null;
}
@FXML
void mStep(ActionEvent event) {
if (aktAlgo == null ) {
if(cbAlgorithmen.getSelectionModel().getSelectedIndex() >= 0) {
try{
ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
Class c = classLoader.loadClass(algoNamen.get(cbAlgorithmen.getSelectionModel().getSelectedIndex()));
aktAlgo = ((GraphAlgo)(c).getDeclaredConstructor().newInstance());
aktAlgo.setStartKnoten(viewer.getSelectedKnoten());
aktAlgo.setGUIElemente(viewer, hilfe);
aktAlgo.setSpeed(910-(int) (sSpeed.getValue()));
} catch( Exception e) {
System.out.println(e);
}
aktAlgo.start();
}
} else {
if(aktAlgo.isAlive()) {
aktAlgo.setSpeed(910-(int) (sSpeed.getValue()));
aktAlgo.setWaitforclick(false);
//gp.setInfoText(aktAlgo.getInfo());
} else {
//gp.setInfoText("Algorithmus ist beendet. "+aktAlgo.getInfo());
bStep.setDisable(true);
bStart.setDisable(true);
bBreak.setDisable(true);
} // end of if-else
} // end of if-else
try{
Thread.sleep(100);
} catch(Exception e) {}
if (!aktAlgo.isAlive()) {
//gp.setInfoText("Algorithmus ist beendet"+aktAlgo.getInfo());
bStep.setDisable(true);
bStart.setDisable(true);
bBreak.setDisable(true);
}
}
@FXML
void mStart(ActionEvent event) {
if (aktAlgo == null ) {
if(cbAlgorithmen.getSelectionModel().getSelectedIndex() >= 0) {
try{
ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
Class c = classLoader.loadClass(algoNamen.get(cbAlgorithmen.getSelectionModel().getSelectedIndex()));
aktAlgo = ((GraphAlgo)(c).getDeclaredConstructor().newInstance());
aktAlgo.setStartKnoten(viewer.getSelectedKnoten());
aktAlgo.setGUIElemente(viewer,hilfe);
aktAlgo.setSpeed(910-(int) (sSpeed.getValue()));
} catch( Exception e) {
System.out.println(e);
}
aktAlgo.setStepping(false);
aktAlgo.start();
}
} else {
if(aktAlgo.isAlive()) {
aktAlgo.setSpeed(910-(int) (sSpeed.getValue()));
aktAlgo.setStepping(false);
aktAlgo.setWaitforclick(false);
//gp.setInfoText(aktAlgo.getInfo());
} else {
//gp.setInfoText("Algorithmus ist beendet. "+aktAlgo.getInfo());
} // end of if-else
} // end of if-else
// gp.setInfoText(aktAlgo.getInfo());
bStep.setDisable(true);
bStart.setVisible(false);
bBreak.setVisible(true);
bBreak.setDisable(false);
}
public void mBreak(ActionEvent event) {
if(aktAlgo != null && aktAlgo.isAlive()) {
aktAlgo.setStepping(true);
bStart.setVisible(true);
bBreak.setVisible(false);
bStep.setDisable(false);
}
}
}

View file

@ -0,0 +1,16 @@
#BlueJ class context
comment0.target=TabMitController
comment0.text=\r\n\ Die\ Klasse\ TabMitController\ stellt\ die\ Oberklasse\ f\u00FCr\ alle\ Tabs\ des\ Graphentesters\r\n\ dar.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=
comment1.target=void\ initialize()
comment2.params=taboptions
comment2.target=void\ tabOeffnen(graph.GraphOptions)
comment3.params=
comment3.target=graph.GraphOptions\ getGraphOptions()
comment4.params=
comment4.target=void\ update()
comment5.params=graph\ options
comment5.target=void\ setGraph(graph.Graph,\ graph.GraphOptions)
comment6.params=
comment6.target=graph.GraphPlotter\ getViewer()
numComments=7

View file

@ -0,0 +1,79 @@
package control;
import imp.*;
import graph.*;
import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.event.*;
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.util.List;
import javafx.collections.ObservableList;
/**
* Die Klasse TabMitController stellt die Oberklasse für alle Tabs des Graphentesters
* dar.
*
* @author Thomas Schaller
* @version v6.7 (9.12.2020)
*/
public class TabMitController extends Tab {
protected Graph graph;
protected GraphOptions options;
@FXML
protected GraphPlotter viewer;
public void initialize() {
/* viewer.setHvalue(0.5);
viewer.setVvalue(0.5);*/
}
protected void tabOeffnen(GraphOptions taboptions) {
try { // try-catch ist notwendig, um Fehler durch fehlende Dateien abzufangen.
UnterTabMitController newtab = new UnterTabMitController(graph, taboptions);
newtab.setText("Teilgraph");
getTabPane().getTabs().add(newtab);
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/graphtab.fxml"));
loader.setController(newtab);
newtab.setContent((Node) loader.load());
getTabPane().getSelectionModel().select(newtab);
}
catch(Exception e) {
System.out.println(e);
}
}
public GraphOptions getGraphOptions() {
return options;
}
public void update() {
viewer.updateImage();
}
public void setGraph(Graph graph, GraphOptions options) {
this.graph = graph;
this.options = options;
if (viewer != null) viewer.setGraph(graph,options);
update();
}
public GraphPlotter getViewer() {
return viewer;
}
}

View file

@ -0,0 +1,78 @@
#BlueJ class context
comment0.target=UnterTabMitController
comment0.text=\r\n\ Die\ Klasse\ UnterTabMitController\ stellt\ einen\ Tab\ inclusive\ ihres\ Controllers\r\n\ zur\ h\u00E4ndischen\ Erforschung\ eines\ Algorithmus.\ Es\ wird\ immer\ ein\ einzelner\ Knoten\ \r\n\ oder\ eine\ Kante\ fokussiert.\r\n\r\n\ @author\ Thomas\ Schaller\r\n\ @version\ v6.7\ (9.12.2020)\r\n
comment1.params=graph\ options
comment1.target=UnterTabMitController(graph.Graph,\ graph.GraphOptions)
comment10.params=event
comment10.target=void\ bBesucht(javafx.event.ActionEvent)
comment11.params=event
comment11.target=void\ bEnde(javafx.event.ActionEvent)
comment12.params=event
comment12.target=void\ knotenFarbe(javafx.scene.input.MouseEvent)
comment13.params=event
comment13.target=void\ bMarkieren(javafx.event.ActionEvent)
comment14.params=
comment14.target=void\ updateInfofeld()
comment15.params=event
comment15.target=void\ graphClicked(javafx.scene.input.MouseEvent)
comment16.params=event
comment16.target=void\ bHinzufuegenAnfang(javafx.event.ActionEvent)
comment17.params=event
comment17.target=void\ bHinzufuegenEnde(javafx.event.ActionEvent)
comment18.params=event
comment18.target=void\ bLoeschenAusListe(javafx.event.ActionEvent)
comment19.params=event
comment19.target=void\ bNaechster(javafx.event.ActionEvent)
comment2.params=
comment2.target=void\ initialize()
comment20.params=event
comment20.target=void\ bSort(javafx.event.ActionEvent)
comment21.params=event
comment21.target=void\ bVoheriger(javafx.event.ActionEvent)
comment22.params=event
comment22.target=void\ bWertAendern(javafx.event.ActionEvent)
comment23.params=event
comment23.target=void\ bGeheZu(javafx.event.ActionEvent)
comment24.params=event
comment24.target=void\ mBeenden(javafx.event.ActionEvent)
comment25.params=event
comment25.target=void\ mBesucheKnoten(javafx.event.ActionEvent)
comment26.params=event
comment26.target=void\ mBesuchtLoeschen(javafx.event.ActionEvent)
comment27.params=event
comment27.target=void\ mFaerbeKnoten(javafx.event.ActionEvent)
comment28.params=event
comment28.target=void\ mMarkiereKnoten(javafx.event.ActionEvent)
comment29.params=event
comment29.target=void\ mMarkierungenLoeschen(javafx.event.ActionEvent)
comment3.params=graph\ options
comment3.target=void\ setGraph(graph.Graph,\ graph.GraphOptions)
comment30.params=event
comment30.target=void\ mOeffnen(javafx.event.ActionEvent)
comment31.params=event
comment31.target=void\ mSchliessen(javafx.event.ActionEvent)
comment32.params=event
comment32.target=void\ mSpeichern(javafx.event.ActionEvent)
comment33.params=event
comment33.target=void\ mUeber(javafx.event.ActionEvent)
comment34.params=event
comment34.target=void\ mWertSetzen(javafx.event.ActionEvent)
comment35.params=event
comment35.target=void\ mZurueck(javafx.event.ActionEvent)
comment36.params=event
comment36.target=void\ bStatusRestore(javafx.event.ActionEvent)
comment37.params=event
comment37.target=void\ bStatusSave(javafx.event.ActionEvent)
comment4.params=
comment4.target=void\ buildAuswahl()
comment5.params=
comment5.target=void\ update()
comment6.params=
comment6.target=void\ fillLvAuswahl()
comment7.params=
comment7.target=void\ showAuswahl()
comment8.params=auswahl
comment8.target=void\ setAuswahl(java.util.List)
comment9.params=event
comment9.target=void\ bAnfang(javafx.event.ActionEvent)
numComments=38

View file

@ -0,0 +1,593 @@
package control;
import imp.*;
import graph.*;
import javafx.fxml.*;
import javafx.scene.control.*;
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.collections.FXCollections;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Optional;
import javafx.collections.ObservableList;
/**
* Die Klasse UnterTabMitController stellt einen Tab inclusive ihres Controllers
* zur händischen Erforschung eines Algorithmus. Es wird immer ein einzelner Knoten
* oder eine Kante fokussiert.
*
* @author Thomas Schaller
* @version v6.7 (9.12.2020)
*/
public class UnterTabMitController extends TabMitController {
@FXML
private VBox infoBox;
@FXML
private Button wertButton;
@FXML
private Button besuchtButton;
@FXML
private Label knotenname;
@FXML
private Label knotenwert;
@FXML
private Label knotenMarkiert;
@FXML
private Label knotenBesucht;
@FXML
private GridPane farben;
@FXML
Button bStatus;
@FXML
Button bGehezu;
@FXML
Button bAnfang;
@FXML
Button bEnde;
@FXML
Button bSortieren;
@FXML
private CheckBox cbFarbeAutomatisch;
@FXML
private ListView<String> lvAuswahl;
private List<GraphElement> auswahl;
private List<String> sicherung;
public UnterTabMitController(Graph graph, GraphOptions options) {
this.graph = graph;
this.options = options;
}
public void initialize() {
if(graph.getAnzahlKnoten()==0) {
getTabPane().getTabs().remove(this);
return;
}
buildAuswahl();
this.bAnfang.managedProperty().bind(bAnfang.visibleProperty());
this.bEnde.managedProperty().bind(bEnde.visibleProperty());
this.bSortieren.managedProperty().bind(bSortieren.visibleProperty());
viewer.setGraph(graph,options);
viewer.setHvalue(0.5);
viewer.setVvalue(0.5);
//auswahl = viewer.getGraph().getAlleKnoten();
for(int x = 0; x< 4; x++) {
for(int y = 0; y <3; y++) {
Label l = new Label();
l.setPrefSize(20,20);
l.setMaxSize(200, 200);
if(options.farbenKnoten.length > y*4+x) {
l.setStyle("-fx-background-color:#"+options.farbenKnoten[y*4+x]);
l.setAlignment(Pos.CENTER);
l.setFont(Font.font("System", FontWeight.BOLD, 12));
}
else
l.setStyle("-fx-background-color:#FFFFFF");
l.setOnMouseClicked(e -> knotenFarbe(e));
farben.add(l, x, y);
}
}
fillLvAuswahl();
lvAuswahl.getSelectionModel().selectedItemProperty().addListener(
(obs, oldValue, newValue) -> showAuswahl());
cbFarbeAutomatisch.selectedProperty().addListener((o, oldValue, newValue) -> {
Knoten k = viewer.getSelectedKnoten();
if (k!=null) {
k.setFarbeAutomatisch(newValue);
viewer.updateImage();
updateInfofeld();
}
});
super.initialize();
}
public void setGraph(Graph graph, GraphOptions options) {
if(graph.getAnzahlKnoten()==0) {
getTabPane().getTabs().remove(this);
return;
}
options.fokusArt = this.options.fokusArt;
options.auswahl = this.options.auswahl;
options.bildAnzeigen = false;
if(options.fokusArt == 0 && this.options.parent!= null) options.parent = graph.getKnoten(0);
if(options.fokusArt == 1 && this.options.parent!= null) options.parent = graph.getKante(0,1);
this.graph = graph;
this.options = options;
viewer.setRestrictTo(null);
buildAuswahl();
super.setGraph(graph,options);
}
public void buildAuswahl() {
auswahl = new ArrayList<GraphElement>();
if(options.auswahl == 0) { // Alle Knoten/Kanten gewählt
if(options.fokusArt == 0) // Knoten
auswahl = new ArrayList<GraphElement>(graph.getAlleKnoten());
else
auswahl = new ArrayList<GraphElement>(graph.getAlleKanten());
} else {
if(options.auswahl == 1) { // Nachbarn
auswahl = new ArrayList<GraphElement>(graph.getNachbarknoten(((Knoten) (options.parent))));
} else { // single
auswahl.add(options.parent);
}
}
if(auswahl.size() == 0) getTabPane().getTabs().remove(this);
}
public void update() {
super.update();
updateInfofeld();
fillLvAuswahl();
}
private void fillLvAuswahl() {
if(auswahl.size()==0 ) {
getTabPane().getTabs().remove(this);
} else {
ObservableList<String> items = FXCollections.observableArrayList ();
for(GraphElement ge : auswahl) {
if(ge instanceof Knoten) {
Knoten k = (Knoten) ge;
String beschreibung="";
if(options.showVertexInfo && !k.getInfotext().isEmpty())
beschreibung = k.getInfotext();
else
beschreibung = "Knoten"+ graph.getNummer(k);
if(options.showVertexValue) {
if(k.getDoubleWert() == k.getIntWert())
beschreibung += " ("+k.getIntWert()+")";
else
beschreibung += " ("+k.getDoubleWert()+")";
}
items.add(beschreibung);
}
if(ge instanceof Kante) {
Kante k = (Kante) ge;
if(options.showEdgeWeights) {
if(k.getGewicht() == (int) k.getGewicht())
items.add("Kante ("+((int)k.getGewicht())+")");
else
items.add("Kante ("+k.getGewicht()+")");
}
else
items.add("Kante Nr."+graph.getNummer(k));
}
}
lvAuswahl.setItems(items);
showAuswahl();
}
}
private void showAuswahl() {
if(lvAuswahl.getSelectionModel().getSelectedIndex()==-1) {
if(auswahl.contains(viewer.getRestrictTo())) {
lvAuswahl.getSelectionModel().select(auswahl.indexOf(viewer.getRestrictTo()));
} else {
lvAuswahl.getSelectionModel().selectFirst();
}
}
viewer.setRestrictTo(auswahl.get(lvAuswahl.getSelectionModel().getSelectedIndex()));
updateInfofeld();
}
public void setAuswahl(List<GraphElement> auswahl) {
this.auswahl = auswahl;
fillLvAuswahl();
}
@FXML
void bAnfang(ActionEvent event) {
if(lvAuswahl.getSelectionModel().getSelectedIndex() > 0) {
lvAuswahl.getSelectionModel().selectFirst();
showAuswahl();
}
}
@FXML
void bBesucht(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if (k!=null) {
k.setBesucht(!k.isBesucht());
viewer.updateImage();
updateInfofeld();
}else {
Kante ka = viewer.getSelectedKante();
if(ka!=null) {
ka.setGeloescht(!ka.isGeloescht());
viewer.updateImage();
updateInfofeld();
}
}
}
@FXML
void bEnde(ActionEvent event) {
if(lvAuswahl.getSelectionModel().getSelectedIndex() < lvAuswahl.getItems().size()-1) {
lvAuswahl.getSelectionModel().selectLast();
showAuswahl();
}
}
@FXML
void knotenFarbe(MouseEvent event) {
Node source = (Node) event.getSource();
Integer colIndex = farben.getColumnIndex(source);
Integer rowIndex = farben.getRowIndex(source);
Knoten k = viewer.getSelectedKnoten();
if (k!=null) {
k.setFarbe(rowIndex*4+colIndex);
ObservableList<Node> ln = farben.getChildren();
for(Node n : ln) {
if(n instanceof Label)
if(n == source){
((Label) n).setText("X");
}
else
((Label) n).setText(" ");
}
viewer.updateImage();
updateInfofeld();
}
}
@FXML
void bMarkieren(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if (k!=null) {
k.setMarkiert(!k.isMarkiert());
viewer.updateImage();
updateInfofeld();
} else {
Kante ka = viewer.getSelectedKante();
if(ka!=null) {
ka.setMarkiert(!ka.isMarkiert());
viewer.updateImage();
updateInfofeld();
}
}
}
public void updateInfofeld() {
GraphElement f = viewer.getRestrictTo();
if( f instanceof Knoten) {
this.setText(viewer.getGraph().getKnoteninfo((Knoten) f, false));
}
Knoten k = viewer.getSelectedKnoten();
Kante ka = viewer.getSelectedKante();
if(k!=null) {
infoBox.setVisible(true);
knotenname.setText("Knoten: "+viewer.getGraph().getNummer(k));
knotenwert.setText("Wert: "+k.getDoubleWert());
knotenMarkiert.setText(k.isMarkiert() ? "markiert" : "unmarkiert");
knotenBesucht.setText(k.isBesucht() ? "besucht" : "nicht besucht");
besuchtButton.setText("Besuchen");
wertButton.setVisible(true);
farben.setVisible(true);
bGehezu.setVisible(k != viewer.getRestrictTo());
bAnfang.setVisible(k != viewer.getRestrictTo());
bEnde.setVisible(k != viewer.getRestrictTo());
bSortieren.setVisible((options.showEdgeWeights && auswahl.get(0) instanceof Kante) || (options.showVertexValue && auswahl.get(0) instanceof Knoten));
cbFarbeAutomatisch.setSelected(k.isFarbeAutomatisch());
ObservableList<Node> ln = farben.getChildren();
for(Node n : ln) {
if(n instanceof Label){
Integer colIndex = farben.getColumnIndex(n);
Integer rowIndex = farben.getRowIndex(n);
if(rowIndex*4+colIndex == k.getFarbe()){
((Label) n).setText("X");
}
else
((Label) n).setText(" ");
}
}
} else {
if(ka != null) {
infoBox.setVisible(true);
knotenname.setText("Kante:");
knotenwert.setText("Gewicht: "+ka.getGewicht());
knotenMarkiert.setText(ka.isMarkiert() ? "markiert" : "unmarkiert");
knotenBesucht.setText(ka.isGeloescht() ? "gelöscht" : "nicht gelöscht");
besuchtButton.setText("Löschen");
wertButton.setVisible(false);
farben.setVisible(false);
}
else
infoBox.setVisible(false);
}
}
@FXML
void graphClicked(MouseEvent event) {
viewer.mouseClicked(event);
updateInfofeld();
if(viewer.getSelectedKnoten() != null && event.isSecondaryButtonDown()) { // Contextmenu
ContextMenu contextMenu = new ContextMenu();
CheckMenuItem item1 = new CheckMenuItem("Markiert");
item1.setSelected(viewer.getSelectedKnoten().isMarkiert());
item1.setOnAction((e) -> this.bMarkieren(e));
CheckMenuItem item2 = new CheckMenuItem("Besucht");
item2.setOnAction((e) -> this.bBesucht(e));
item2.setSelected(viewer.getSelectedKnoten().isBesucht());
MenuItem item3 = new MenuItem("Wert ändern");
item3.setOnAction((e) -> this.bWertAendern(e));
MenuItem item5 = new MenuItem("Füge am Anfang der ToDo-Liste hinzu");
item5.setOnAction((e) -> this.bHinzufuegenAnfang(e));
MenuItem item6 = new MenuItem("Füge am Ende der ToDo-Liste hinzu");
item6.setOnAction((e) -> this.bHinzufuegenEnde(e));
MenuItem item7 = new MenuItem("Loesche aus Liste");
item7.setOnAction((e) -> this.bLoeschenAusListe(e));
SeparatorMenuItem sep = new SeparatorMenuItem();
SeparatorMenuItem sep2 = new SeparatorMenuItem();
MenuItem item4 = new MenuItem("Gehe zu ...");
item4.setOnAction((e) -> this.bGeheZu(e));
// Add MenuItem to ContextMenu
contextMenu.getItems().addAll(item3, item1, item2, sep, item5, item6, item7, sep2, item4);
contextMenu.show(viewer, event.getScreenX(), event.getScreenY());
}
if(viewer.getSelectedKante() != null && event.isSecondaryButtonDown()) { // Contextmenu
ContextMenu contextMenu = new ContextMenu();
CheckMenuItem item1 = new CheckMenuItem("Markiert");
item1.setSelected(viewer.getSelectedKante().isMarkiert());
item1.setOnAction((e) -> this.bMarkieren(e));
CheckMenuItem item2 = new CheckMenuItem("Gelöscht");
item2.setSelected(viewer.getSelectedKante().isGeloescht());
item2.setOnAction((e) -> this.bBesucht(e));
SeparatorMenuItem sep = new SeparatorMenuItem();
MenuItem item4 = new MenuItem("Gehe zu ...");
item4.setOnAction((e) -> this.bGeheZu(e));
// Add MenuItem to ContextMenu
contextMenu.getItems().addAll( item1, item2, sep, item4);
contextMenu.show(viewer, event.getScreenX(), event.getScreenY());
}
}
@FXML
void bHinzufuegenAnfang(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if(k!=null) {
auswahl.add(0,k);
fillLvAuswahl();
}
}
@FXML
void bHinzufuegenEnde(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if(k!=null) {
auswahl.add(k);
fillLvAuswahl();
}
}
@FXML
void bLoeschenAusListe(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if(k!=null && auswahl.contains(k)) {
auswahl.remove(k);
fillLvAuswahl();
}
}
@FXML
void bNaechster(ActionEvent event) {
if(lvAuswahl.getSelectionModel().isSelected(auswahl.size()-1))
lvAuswahl.getSelectionModel().selectFirst();
else
lvAuswahl.getSelectionModel().selectNext();
showAuswahl();
}
// @FXML
// void bListeAnpassen(ActionEvent event) {
// buildAuswahl();
// fillLvAuswahl();
// }
// @FXML
// void bNeuerTab(ActionEvent event) {
// GraphOptions neu = options.copy();
// neu.parent = viewer.getRestrictTo();
// if(neu.parent == null) neu.parent = viewer.getSelectedKnoten();
// neu.bildAnzeigen = false;
// tabOeffnen(neu);
// }
@FXML
void bSort(ActionEvent event) {
Collections.sort(auswahl);
fillLvAuswahl();
}
@FXML
void bVoheriger(ActionEvent event) {
if(lvAuswahl.getSelectionModel().isSelected(0))
lvAuswahl.getSelectionModel().selectLast();
else
lvAuswahl.getSelectionModel().selectPrevious();
showAuswahl();
}
@FXML
void bWertAendern(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if (k!=null) {
TextInputDialog dialog = new TextInputDialog(""+k.getDoubleWert());
dialog.setTitle("Wert ändern");
dialog.setContentText("Bitte geben Sie den neuen Wert ein:");
Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
try{
double v = Double.parseDouble(result.get());
k.setWert(v);
this.fillLvAuswahl();
viewer.updateImage();
updateInfofeld();
} catch (Exception e) {
System.out.println("Keine Zahl eingegeben");
}
}
}
}
@FXML
void bGeheZu(ActionEvent event) {
Knoten k = viewer.getSelectedKnoten();
if (k!=null) {
GraphOptions neu = options.copy();
neu.auswahl = 2; // single
neu.parent = k;
neu.bildAnzeigen = false;
this.tabOeffnen(neu);
}
}
@FXML
void mBeenden(ActionEvent event) {
}
@FXML
void mBesucheKnoten(ActionEvent event) {
}
@FXML
void mBesuchtLoeschen(ActionEvent event) {
}
@FXML
void mFaerbeKnoten(ActionEvent event) {
}
@FXML
void mMarkiereKnoten(ActionEvent event) {
}
@FXML
void mMarkierungenLoeschen(ActionEvent event) {
}
@FXML
void mOeffnen(ActionEvent event) {
}
@FXML
void mSchliessen(ActionEvent event) {
}
@FXML
void mSpeichern(ActionEvent event) {
}
@FXML
void mUeber(ActionEvent event) {
}
@FXML
void mWertSetzen(ActionEvent event) {
}
@FXML
void mZurueck(ActionEvent event) {
}
@FXML
void bStatusRestore(ActionEvent event) {
if(sicherung != null) { graph.setStatus(sicherung); update(); }
}
@FXML
void bStatusSave(ActionEvent event) {
sicherung = graph.getStatus();
bStatus.setDisable(false);
}
}

97
control/package.bluej Normal file
View file

@ -0,0 +1,97 @@
#BlueJ package file
dependency1.from=TabMitController
dependency1.to=UnterTabMitController
dependency1.type=UsesDependency
dependency2.from=SimulationTabMitController
dependency2.to=Hilfefenster
dependency2.type=UsesDependency
dependency3.from=SimulationTabMitController
dependency3.to=MyClassLoader
dependency3.type=UsesDependency
dependency4.from=Controller
dependency4.to=TabMitController
dependency4.type=UsesDependency
dependency5.from=Controller
dependency5.to=HauptTabMitController
dependency5.type=UsesDependency
dependency6.from=Controller
dependency6.to=SimulationTabMitController
dependency6.type=UsesDependency
dependency7.from=Controller
dependency7.to=EditTabMitController
dependency7.type=UsesDependency
objectbench.height=93
objectbench.width=451
package.divider.horizontal=0.599476439790576
package.divider.vertical=0.8
package.editor.height=393
package.editor.width=636
package.editor.x=193
package.editor.y=208
package.frame.height=600
package.frame.width=800
package.numDependencies=7
package.numTargets=8
package.showExtends=true
package.showUses=true
readme.height=60
readme.name=@README
readme.width=49
readme.x=10
readme.y=10
target1.height=50
target1.name=EditTabMitController
target1.showInterface=false
target1.type=ClassTarget
target1.width=160
target1.x=10
target1.y=80
target2.height=50
target2.name=HauptTabMitController
target2.showInterface=false
target2.type=ClassTarget
target2.width=170
target2.x=10
target2.y=140
target3.height=50
target3.name=Hilfefenster
target3.showInterface=false
target3.type=ClassTarget
target3.width=100
target3.x=500
target3.y=60
target4.height=50
target4.name=TabMitController
target4.showInterface=false
target4.type=ClassTarget
target4.width=130
target4.x=300
target4.y=110
target5.height=50
target5.name=SimulationTabMitController
target5.showInterface=false
target5.type=ClassTarget
target5.width=200
target5.x=10
target5.y=210
target6.height=50
target6.name=Controller
target6.showInterface=false
target6.type=ClassTarget
target6.width=90
target6.x=500
target6.y=250
target7.height=70
target7.name=MyClassLoader
target7.showInterface=false
target7.type=ClassTarget
target7.width=120
target7.x=140
target7.y=330
target8.height=50
target8.name=UnterTabMitController
target8.showInterface=false
target8.type=ClassTarget
target8.width=170
target8.x=10
target8.y=270