GUIController.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. package de.tu_darmstadt.informatik.tk.scopviz.ui;
  2. import java.net.URL;
  3. import java.util.ArrayList;
  4. import java.util.ResourceBundle;
  5. import javax.swing.JPanel;
  6. import javax.swing.event.MouseInputListener;
  7. import org.jxmapviewer.JXMapViewer;
  8. import org.jxmapviewer.input.CenterMapListener;
  9. import org.jxmapviewer.input.PanKeyListener;
  10. import org.jxmapviewer.input.PanMouseInputListener;
  11. import org.jxmapviewer.input.ZoomMouseWheelListenerCursor;
  12. import de.tu_darmstadt.informatik.tk.scopviz.main.Layer;
  13. import de.tu_darmstadt.informatik.tk.scopviz.main.Main;
  14. import de.tu_darmstadt.informatik.tk.scopviz.metrics.TestMetric;
  15. import de.tu_darmstadt.informatik.tk.scopviz.ui.handlers.KeyboardShortcuts;
  16. import de.tu_darmstadt.informatik.tk.scopviz.ui.handlers.ResizeListener;
  17. import de.tu_darmstadt.informatik.tk.scopviz.ui.mapView.WorldView;
  18. import javafx.beans.value.ChangeListener;
  19. import javafx.beans.value.ObservableValue;
  20. import javafx.collections.FXCollections;
  21. import javafx.collections.ObservableList;
  22. import javafx.embed.swing.SwingNode;
  23. import javafx.fxml.FXML;
  24. import javafx.fxml.Initializable;
  25. import javafx.scene.control.Button;
  26. import javafx.scene.control.CheckBox;
  27. import javafx.scene.control.ChoiceBox;
  28. import javafx.scene.control.Label;
  29. import javafx.scene.control.MenuItem;
  30. import javafx.scene.control.TableColumn;
  31. import javafx.scene.control.TableRow;
  32. import javafx.scene.control.TableView;
  33. import javafx.scene.control.Tooltip;
  34. import javafx.scene.control.cell.CheckBoxTableCell;
  35. import javafx.scene.control.cell.PropertyValueFactory;
  36. import javafx.scene.control.cell.TextFieldTableCell;
  37. import javafx.scene.layout.AnchorPane;
  38. import javafx.scene.layout.Pane;
  39. import javafx.scene.layout.StackPane;
  40. import javafx.scene.layout.VBox;
  41. import javafx.scene.text.TextFlow;
  42. import javafx.util.Pair;
  43. /**
  44. * Controller class for the various GUI elements, gets instanced and initialized
  45. * by the FXML loading process. Can access GUI elements specified in the FXML
  46. * file through matching variable name here and id attribute in the FXML,
  47. *
  48. * @author Dominik Renkel, Jan Enders
  49. * @version 1.1
  50. *
  51. */
  52. public class GUIController implements Initializable {
  53. // The SwingNode and its containing Pane that house the graph viewer
  54. @FXML
  55. public SwingNode swingNode;
  56. @FXML
  57. public SwingNode swingNodeWorldView;
  58. @FXML
  59. public Pane pane;
  60. @FXML
  61. public StackPane stackPane;
  62. // The buttons present in the UI
  63. @FXML
  64. public Button zoomIn;
  65. @FXML
  66. public Button zoomOut;
  67. @FXML
  68. public Button underlayButton;
  69. @FXML
  70. public Button operatorButton;
  71. @FXML
  72. public Button mappingButton;
  73. @FXML
  74. public Button symbolRepButton;
  75. // The Toolbar Items
  76. @FXML
  77. public MenuItem newItem;
  78. @FXML
  79. public MenuItem open;
  80. @FXML
  81. public MenuItem add;
  82. @FXML
  83. public MenuItem save;
  84. @FXML
  85. public MenuItem saveAs;
  86. @FXML
  87. public MenuItem preferences;
  88. @FXML
  89. public MenuItem quit;
  90. @FXML
  91. public MenuItem delete;
  92. @FXML
  93. public MenuItem undelete;
  94. @FXML
  95. public MenuItem updateMetricMI;
  96. @FXML
  97. public MenuItem about;
  98. // The contents of the corresponding ScrollPanes
  99. @FXML
  100. public TableView<Pair<Object, String>> toolbox;
  101. @FXML
  102. public TableView<KeyValuePair> properties;
  103. @FXML
  104. public TableView<MetricRowData> metricbox;
  105. // The columns of the toolbox
  106. @FXML
  107. public TableColumn<Pair<Object, String>, String> toolboxStringColumn;
  108. @FXML
  109. public TableColumn<Pair<Object, String>, Object> toolboxObjectColumn;
  110. // The columns of the Properties pane
  111. // TODO: Fix Generic type arguments for propertiesObjectColumn
  112. @FXML
  113. public TableColumn<KeyValuePair, String> propertiesStringColumn;
  114. @FXML
  115. public TableColumn propertiesObjectColumn;
  116. @FXML
  117. public TableColumn<KeyValuePair, String> propertiesTypeColumn;
  118. // The columns of the metricbox
  119. @FXML
  120. public TableColumn<MetricRowData,String> metricBoxMetricColumn;
  121. @FXML
  122. public TableColumn<MetricRowData,String> metricBoxValueColumn;
  123. @FXML
  124. public TableColumn metricBoxUpdateColumn;
  125. @FXML
  126. public Button updateMetricButton;
  127. //The items of the top left box in the symbol visualization layer
  128. @FXML
  129. public VBox symbolToolVBox;
  130. @FXML
  131. public CheckBox edgesVisibleCheckbox;
  132. @FXML
  133. public CheckBox nodeLabelCheckbox;
  134. @FXML
  135. public CheckBox edgeWeightCheckbox;
  136. @FXML
  137. public ChoiceBox<String> mapViewChoiceBox;
  138. @FXML
  139. public TextFlow consoleWindow;
  140. @FXML
  141. public VBox rightSide;
  142. //The anchorpane of the top left box (toolbox, symbol visualization layer box)
  143. @FXML
  144. public AnchorPane topLeftAPane;
  145. //The anchorpane of the metric update button
  146. @FXML
  147. public AnchorPane updateButtonAPane;
  148. /**
  149. * Initializes all the references to the UI elements specified in the FXML
  150. * file. Gets called during FXML loading. Asserts the correct injection of
  151. * all referenced UI elements and initializes them.
  152. */
  153. @Override
  154. public void initialize(URL arg0, ResourceBundle arg1) {
  155. // Assert the correct injection of all references from FXML
  156. assertFXMLInjections();
  157. initializeToolbox();
  158. initializeProperties();
  159. initializeMetricbox();
  160. // Remove Header for the toolbox
  161. removeHeaderTableView(toolbox);
  162. // Initialize the Managers for the various for UI elements
  163. ToolboxManager.initializeItems();
  164. PropertiesManager.initializeItems(properties);
  165. ConsoleManager.initialize(this);
  166. GraphDisplayManager.init(this);
  167. // Bind all the handlers to their corresponding UI elements
  168. initializeZoomButtons();
  169. initializeLayerButton();
  170. initializeMenuBar();
  171. initializeSymbolRepToolbox();
  172. initializeDisplayPane();
  173. initializeWorldView();
  174. // Setup the Keyboard Shortcuts
  175. KeyboardShortcuts.initialize(Main.getInstance().getPrimaryStage());
  176. }
  177. private void initializeWorldView() {
  178. JXMapViewer mapViewer = new JXMapViewer();
  179. WorldView.initAttributes(mapViewer, this);
  180. // center map if double clicked / middle clicked
  181. mapViewer.addMouseListener(new CenterMapListener(mapViewer));
  182. // zoom with mousewheel
  183. mapViewer.addMouseWheelListener(new ZoomMouseWheelListenerCursor(mapViewer));
  184. // TODO make this work
  185. mapViewer.addKeyListener(new PanKeyListener(mapViewer));
  186. // "Drag map around" Listener
  187. MouseInputListener mia = new PanMouseInputListener(mapViewer);
  188. mapViewer.addMouseListener(mia);
  189. mapViewer.addMouseMotionListener(mia);
  190. swingNodeWorldView.setContent(mapViewer);
  191. // add resize Listener to the stackPane
  192. stackPane.heightProperty().addListener(new ResizeListener(swingNode, stackPane));
  193. stackPane.widthProperty().addListener(new ResizeListener(swingNode, stackPane));
  194. swingNodeWorldView.setVisible(false);
  195. }
  196. /**
  197. * Initializes the Menu Bar with all its contents.
  198. */
  199. private void initializeMenuBar() {
  200. newItem.setOnAction((event) -> MenuBarManager.newAction(event));
  201. open.setOnAction((event) -> MenuBarManager.openAction(event));
  202. add.setOnAction((event) -> MenuBarManager.addAction(event));
  203. add.setDisable(true);;
  204. save.setOnAction((event) -> MenuBarManager.saveAction(event));
  205. saveAs.setOnAction((event) -> MenuBarManager.saveAsAction(event));
  206. preferences.setOnAction((event) -> MenuBarManager.preferencesAction(event));
  207. quit.setOnAction((event) -> MenuBarManager.quitAction(event));
  208. delete.setOnAction((event) -> MenuBarManager.deleteAction(event));
  209. undelete.setOnAction((event) -> MenuBarManager.undeleteAction(event));
  210. updateMetricMI.setOnAction((event) -> MetricboxManager.updateMetrics());
  211. updateMetricMI.setDisable(true);
  212. about.setOnAction((event) -> MenuBarManager.aboutAction(event));
  213. }
  214. /**
  215. * Sets the handlers for the zoomin and zoomout buttons.
  216. */
  217. private void initializeZoomButtons() {
  218. zoomIn.setOnAction((event) -> ButtonManager.zoomInAction(event));
  219. zoomOut.setOnAction((event) -> ButtonManager.zoomOutAction(event));
  220. }
  221. /**
  222. * Initializes the special Toolbox for the Symbol Representation Layer.
  223. */
  224. private void initializeSymbolRepToolbox() {
  225. // Hide SymbolRep Toolbox View
  226. topLeftAPane.getChildren().remove(symbolToolVBox);
  227. edgesVisibleCheckbox.selectedProperty()
  228. .addListener((ov, oldVal, newVal) -> ButtonManager.edgeVisibilitySwitcher(ov, oldVal, newVal));
  229. nodeLabelCheckbox.selectedProperty()
  230. .addListener((ov, oldVal, newVal) -> ButtonManager.labelVisibilitySwitcher(ov, oldVal, newVal));
  231. edgeWeightCheckbox.selectedProperty()
  232. .addListener((ov, oldVal, newVal) -> ButtonManager.edgeWeightVisibilitySwitcher(ov, oldVal, newVal));
  233. mapViewChoiceBox.setItems(FXCollections.observableArrayList("Default", "Road", "Satellite", "Hybrid"));
  234. mapViewChoiceBox.getSelectionModel().selectFirst();
  235. mapViewChoiceBox.getSelectionModel().selectedItemProperty()
  236. .addListener((ov, oldVal, newVal) -> ButtonManager.mapViewChoiceChange(ov, oldVal, newVal));
  237. }
  238. /**
  239. * Set the Handlers for the Layer switch Buttons.
  240. */
  241. private void initializeLayerButton() {
  242. underlayButton.setOnAction((event) -> ButtonManager.underlayAction(event));
  243. operatorButton.setOnAction((event) -> ButtonManager.operatorAction(event));
  244. mappingButton.setOnAction((event) -> ButtonManager.mappingAction(event));
  245. symbolRepButton.setOnAction((event) -> ButtonManager.symbolRepAction(event));
  246. Tooltip tip = new Tooltip();
  247. tip.setText("Underlay");
  248. underlayButton.setTooltip(tip);
  249. tip = new Tooltip();
  250. tip.setText("Operator");
  251. operatorButton.setTooltip(tip);
  252. tip = new Tooltip();
  253. tip.setText("Mapping");
  254. mappingButton.setTooltip(tip);
  255. tip = new Tooltip();
  256. tip.setText("Geographical Visualization");
  257. symbolRepButton.setTooltip(tip);
  258. ArrayList<Button> layerButtons = new ArrayList<Button>();
  259. layerButtons.add(underlayButton);
  260. layerButtons.add(operatorButton);
  261. layerButtons.add(mappingButton);
  262. layerButtons.add(symbolRepButton);
  263. ButtonManager.initialize(layerButtons, this, underlayButton);
  264. }
  265. /**
  266. * Sets the minimum size and adds the handlers to the graph display.
  267. */
  268. private void initializeDisplayPane() {
  269. ResizeListener rLis = new ResizeListener(swingNode, pane);
  270. pane.heightProperty().addListener(rLis);
  271. pane.widthProperty().addListener(rLis);
  272. pane.setOnScroll(GraphDisplayManager.scrollHandler);
  273. swingNode.setContent((JPanel) Main.getInstance().getGraphManager().getView());
  274. pane.setMinSize(200, 200);
  275. }
  276. /**
  277. * Initialize the Toolbox.
  278. */
  279. @SuppressWarnings("unchecked")
  280. private void initializeToolbox() {
  281. ToolboxManager.initialize(this);
  282. toolboxStringColumn.setCellValueFactory(new ToolboxManager.PairKeyFactory());
  283. toolboxObjectColumn.setCellValueFactory(new ToolboxManager.PairValueFactory());
  284. toolboxObjectColumn.setCellFactory((column) -> {
  285. return new ToolboxManager.PairValueCell();
  286. });
  287. toolbox.getColumns().setAll(toolboxObjectColumn, toolboxStringColumn);
  288. // Click event for TableView row
  289. toolbox.setRowFactory(tv -> {
  290. TableRow<Pair<Object, String>> row = new TableRow<>();
  291. row.setOnMouseClicked(ToolboxManager.rowClickedHandler);
  292. return row;
  293. });
  294. // nothing is selected at the start
  295. toolbox.getSelectionModel().clearSelection();
  296. }
  297. /**
  298. * Initialize the Properties Window.
  299. */
  300. @SuppressWarnings("unchecked")
  301. private void initializeProperties() {
  302. propertiesObjectColumn.setResizable(true);
  303. propertiesStringColumn.setResizable(true);
  304. propertiesStringColumn.setCellValueFactory(new PropertyValueFactory<KeyValuePair, String>("key"));
  305. propertiesObjectColumn.setCellValueFactory(new PropertyValueFactory<KeyValuePair, Object>("value"));
  306. propertiesObjectColumn.setCellFactory(TextFieldTableCell.forTableColumn());
  307. propertiesObjectColumn.setOnEditCommit(PropertiesManager.setOnEditCommitHandler);
  308. propertiesTypeColumn.setCellValueFactory(new PropertyValueFactory<KeyValuePair, String>("classTypeAsString"));
  309. properties.getColumns().setAll(propertiesStringColumn, propertiesObjectColumn, propertiesTypeColumn);
  310. properties.setRowFactory(PropertiesManager.rightClickCallback);
  311. properties.setPlaceholder(new Label("No graph element selected"));
  312. properties.getSelectionModel().clearSelection();
  313. }
  314. /**
  315. * Initialize the metric box
  316. */
  317. @SuppressWarnings("unchecked")
  318. private void initializeMetricbox() {
  319. //TODO Möglicherweise auslagern
  320. metricbox.setRowFactory( tv -> {
  321. TableRow<MetricRowData> row = new TableRow<>();
  322. row.setOnMouseClicked(event -> {
  323. if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
  324. MetricRowData rowData = row.getItem();
  325. if(rowData.getMetric().isSetupRequired()){
  326. rowData.getMetric().setup();
  327. }
  328. }
  329. });
  330. return row ;
  331. });
  332. metricBoxMetricColumn.setResizable(true);
  333. metricBoxValueColumn.setResizable(true);
  334. metricBoxMetricColumn.setCellValueFactory(new PropertyValueFactory<MetricRowData, String>("metricName"));
  335. metricBoxValueColumn.setCellValueFactory(new PropertyValueFactory<MetricRowData, String>("value"));
  336. metricBoxUpdateColumn.setCellValueFactory(new PropertyValueFactory<>("checked"));
  337. metricBoxUpdateColumn.setCellFactory(CheckBoxTableCell.forTableColumn(metricBoxUpdateColumn));
  338. metricbox.getColumns().setAll(metricBoxMetricColumn, metricBoxValueColumn, metricBoxUpdateColumn);
  339. MetricboxManager.initialize(this);
  340. //Update button initialization
  341. updateMetricButton.setOnAction((event) -> MetricboxManager.updateMetrics());
  342. //TODO
  343. rightSide.getChildren().remove(updateButtonAPane);
  344. }
  345. /**
  346. * Removes the TableView Header for a given TableView
  347. *
  348. * @param tableView
  349. */
  350. private void removeHeaderTableView(TableView<?> tableView) {
  351. tableView.widthProperty().addListener(new ChangeListener<Number>() {
  352. @Override
  353. public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
  354. // Get the table header
  355. Pane header = (Pane) tableView.lookup("TableHeaderRow");
  356. if (header != null && header.isVisible()) {
  357. header.setMaxHeight(0);
  358. header.setMinHeight(0);
  359. header.setPrefHeight(0);
  360. header.setVisible(false);
  361. header.setManaged(false);
  362. }
  363. }
  364. });
  365. }
  366. /**
  367. * Asserts the correct Injection of all Elements from the FXML File.
  368. */
  369. private void assertFXMLInjections() {
  370. assert swingNode != null : "fx:id=\"swingNode\" was not injected: check your FXML file 'MainWindow.fxml'.";
  371. assert pane != null : "fx:id=\"pane\" was not injected: check your FXML file 'MainWindow.fxml'.";
  372. assert zoomIn != null : "fx:id=\"zoomIn\" was not injected: check your FXML file 'MainWindow.fxml'.";
  373. assert zoomOut != null : "fx:id=\"zoomOut\" was not injected: check your FXML file 'MainWindow.fxml'.";
  374. assert underlayButton != null : "fx:id=\"underlayButton\" was not injected: check your FXML file 'MainWindow.fxml'.";
  375. assert operatorButton != null : "fx:id=\"operatorButton\" was not injected: check your FXML file 'MainWindow.fxml'.";
  376. assert mappingButton != null : "fx:id=\"mappingButton\" was not injected: check your FXML file 'MainWindow.fxml'.";
  377. assert symbolRepButton != null : "fx:id=\"symbolRepButton\" was not injected: check your FXML file 'MainWindow.fxml'.";
  378. assert newItem != null : "fx:id=\"newItem\" was not injected: check your FXML file 'MainWindow.fxml'.";
  379. assert open != null : "fx:id=\"open\" was not injected: check your FXML file 'MainWindow.fxml'.";
  380. assert add != null : "fx:id=\"add\" was not injected: check your FXML file 'MainWindow.fxml'.";
  381. assert save != null : "fx:id=\"save\" was not injected: check your FXML file 'MainWindow.fxml'.";
  382. assert saveAs != null : "fx:id=\"saveAs\" was not injected: check your FXML file 'MainWindow.fxml'.";
  383. assert preferences != null : "fx:id=\"preferences\" was not injected: check your FXML file 'MainWindow.fxml'.";
  384. assert quit != null : "fx:id=\"quit\" was not injected: check your FXML file 'MainWindow.fxml'.";
  385. assert delete != null : "fx:id=\"delete\" was not injected: check your FXML file 'MainWindow.fxml'.";
  386. assert undelete != null : "fx:id=\"undelete\" was not injected: check your FXML file 'MainWindow.fxml'.";
  387. assert updateMetricMI != null : "fx:id=\"updateMetricMI\" was not injected: check your FXML file 'MainWindow.fxml'.";
  388. assert about != null : "fx:id=\"about\" was not injected: check your FXML file 'MainWindow.fxml'.";
  389. assert toolbox != null : "fx:id=\"toolbox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  390. assert properties != null : "fx:id=\"properties\" was not injected: check your FXML file 'MainWindow.fxml'.";
  391. assert metricbox != null : "fx:id=\"metricbox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  392. assert toolboxStringColumn != null : "fx:id=\"toolboxString\" was not injected: check your FXML file 'MainWindow.fxml'.";
  393. assert toolboxObjectColumn != null : "fx:id=\"toolboxObject\" was not injected: check your FXML file 'MainWindow.fxml'.";
  394. assert propertiesStringColumn != null : "fx:id=\"propertiesString\" was not injected: check your FXML file 'MainWindow.fxml'.";
  395. assert propertiesObjectColumn != null : "fx:id=\"propertiesObject\" was not injected: check your FXML file 'MainWindow.fxml'.";
  396. assert propertiesTypeColumn != null : "fx:id=\"propertiesType\" was not injected: check your FXML file 'MainWindow.fxml'.";
  397. assert rightSide != null : "fx:id=\"rightSide\" was not injected: check your FXML file 'MainWindow.fxml'.";
  398. assert consoleWindow != null : "fx:id=\"consoleWindow\" was not injected: check your FXML file 'MainWindow.fxml'.";
  399. assert metricBoxMetricColumn != null : "fx:id=\"metricBoxMetricColumn\" was not injected: check your FXML file 'MainWindow.fxml'.";
  400. assert metricBoxValueColumn != null : "fx:id=\"metricBoxValueColumn\" was not injected: check your FXML file 'MainWindow.fxml'.";
  401. assert metricBoxUpdateColumn != null : "fx:id=\"metricBoxUpdateColumn\" was not injected: check your FXML file 'MainWindow.fxml'.";
  402. assert updateMetricButton != null : "fx:id=\"updateMetricButton\" was not injected: check your FXML file 'MainWindow.fxml'.";
  403. assert topLeftAPane != null : "fx:id=\"topLeftAPane\" was not injected: check your FXML file 'MainWindow.fxml'.";
  404. assert updateButtonAPane != null : "fx:id=\"updateButton\" was not injected: check your FXML file 'MainWindow.fxml'.";
  405. assert symbolToolVBox != null : "fx:id=\"symbolToolVBox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  406. assert edgesVisibleCheckbox != null : "fx:id=\"edgesVisibleCheckbox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  407. assert nodeLabelCheckbox != null : "fx:id=\"nodeLabelCheckbox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  408. assert edgeWeightCheckbox != null : "fx:id=\"egdeWeightCheckbox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  409. assert mapViewChoiceBox != null : "fx:id=\"mapViewChoiceBox\" was not injected: check your FXML file 'MainWindow.fxml'.";
  410. assert stackPane != null : "fx:id=\"stackPane\" was not injected: check your FXML file 'MainWindow.fxml'.";
  411. assert swingNodeWorldView != null : "fx:id=\"swingNodeWorldView\" was not injected: check your FXML file 'MainWindow.fxml'.";
  412. }
  413. }