Java tutorial
/* * Copyright (c) 2013, R. van Twisk * All rights reserved. * Licensed under the The BSD 3-Clause License; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://opensource.org/licenses/BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the aic-util nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.rvantwisk.cnctools.controllers; import com.rvantwisk.cnctools.ScreensConfiguration; import com.rvantwisk.cnctools.data.*; import com.rvantwisk.cnctools.data.tools.BallMill; import com.rvantwisk.cnctools.data.tools.EndMill; import com.rvantwisk.cnctools.misc.*; import com.rvantwisk.cnctools.operations.createRoundStock.RoundStockModel; import com.rvantwisk.cnctools.operations.customgcode.CustomGCodeController; import com.rvantwisk.cnctools.operations.customgcode.GCodeTaskModel; import com.rvantwisk.gcodegenerator.GCodeCollection; import javafx.beans.property.SimpleStringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.control.*; import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.layout.AnchorPane; import javafx.stage.FileChooser; import javafx.stage.WindowEvent; import javafx.util.Callback; import jfxtras.labs.dialogs.MonologFX; import jfxtras.labs.dialogs.MonologFXButton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.StandardOpenOption; import java.util.ResourceBundle; /** * Created with IntelliJ IDEA. * User: rvt * Date: 10/5/13 * Time: 6:11 PM * To change this template use File | Settings | File Templates. */ @SuppressWarnings("SpringJavaAutowiringInspection") public class CNCToolsController extends AbstractController { private static final String SEPERATOR = System.getProperty("line.separator"); private final Logger logger = LoggerFactory.getLogger(this.getClass()); @FXML TextArea descriptionValue; @FXML TableView tbl_millTasks; @FXML ListView<Project> v_projectList; @FXML TableColumn<TaskRunnable, Boolean> milltaskEnabled; @FXML Button addMillTask; @FXML Button removeMilltask; @FXML Button editMilltask; @FXML Button deleteProject; @FXML Button generateGCode; @FXML Button btnView; @FXML Button btnPostProcessor; @Autowired private ProjectModel projectModel; @Autowired private ToolDBManager toolDBManager; @FXML private ResourceBundle resources; @FXML private URL location; @FXML private AnchorPane details; @FXML private Label displayedIssueLabel; @FXML private Button btnMoveTaskDown; @FXML private Button btnMoveTaskUp; private ScreensConfiguration screens; public CNCToolsController(ScreensConfiguration screens) { this.screens = screens; } /** * Show's a dialog's with gcode from file * * @param project * @param fName */ public static void showGCodeFromFile(final Project project, final String fName) { FXMLDialog dialog = ScreensConfiguration.getInstance().taskEditDialog(); GCodeTaskModel model = new GCodeTaskModel(); model.setgCodeFile(fName); model.setReferencedFile(true); TaskRunnable taskRunnable = new TaskRunnable("G-Code", "", CustomGCodeController.class.getName(), "CustomGCode.fxml"); taskRunnable.setMilltaskModel(model); ScreensConfiguration.getInstance().registerBean(taskRunnable.getClassName()); TaskEditController controller = dialog.getController(); controller.setViewAs(TaskEditController.ViewAs.CLOSE); controller.setTask(project, taskRunnable.copy()); dialog.showAndWait(); } @FXML public void addProject(ActionEvent event) throws Exception { try { screens.projectDialog().showAndWait(); } catch (Exception e) { handleException(e); } } @FXML public void showAbout(ActionEvent event) throws Exception { try { screens.aboutDialog().showAndWait(); } catch (Exception e) { handleException(e); } } @FXML public void onPostProcessorConfig(ActionEvent actionEvent) { try { screens.postProcessorsDialog().showAndWait(); } catch (Exception e) { handleException(e); } } @FXML public void generateGCode(ActionEvent event) throws Exception { if (v_projectList.getSelectionModel().selectedItemProperty().get() != null) { final Project p = v_projectList.getSelectionModel().selectedItemProperty().get(); if (p.postProcessorProperty().get() == null) { MonologFX dialog = new MonologFX(MonologFX.Type.QUESTION); dialog.setTitleText("No postprocessor"); dialog.setMessage("No post processor configured, please select a post processor first!"); dialog.show(); } else { final GCodeCollection gCode = p.getGCode(toolDBManager); gCode.merge(); FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters() .addAll(new FileChooser.ExtensionFilter("NC File", "*.tap", "*.ngc")); fileChooser.setTitle("Save GCode"); File choosenName = fileChooser.showSaveDialog(null); if (choosenName != null) { choosenName.delete(); if (!p.getPostProcessor().isHasToolChanger()) { final GCodeCollection.GeneratedGCode preAmble = gCode.get(0); final GCodeCollection.GeneratedGCode postAmble = gCode.get(gCode.size() - 1); for (int i = 1; i <= (gCode.size() - 2); i++) { final String[] path = choosenName.getPath().split("\\.(?=[^\\.]+$)"); File thisSet = new File(path[0] + "-" + i + "." + path[1]); thisSet.delete(); // Concate all g-code String file = preAmble.getGCode().toString() + SEPERATOR + gCode.get(i).getGCode().toString() + SEPERATOR + postAmble.getGCode().toString() + SEPERATOR; saveGCode(file, thisSet); } } else { saveGCode(gCode.concate().toString(), choosenName); } } } } } private void saveGCode(String gCode, final File filename) { if (gCode == null) { throw new IllegalArgumentException("gCode most not be null"); } if (filename == null) { throw new IllegalArgumentException("filename most not be null"); } try (BufferedWriter br = Files.newBufferedWriter(filename.toPath(), Charset.forName("UTF-8"), new OpenOption[] { StandardOpenOption.CREATE_NEW })) { // Cleanup empty lines // We do this currently in memory because we don't expect large files anyways while (gCode.lastIndexOf(SEPERATOR + SEPERATOR) != -1) { gCode = gCode.replaceAll(SEPERATOR + SEPERATOR, SEPERATOR); } br.write(gCode.trim()); br.flush(); br.close(); } catch (IOException ex) { System.out.println(ex.getMessage()); } } @FXML public void deleteProject(ActionEvent event) throws Exception { try { if (v_projectList.getSelectionModel().selectedItemProperty().get() != null) { MonologFX dialog = new MonologFX(MonologFX.Type.QUESTION); dialog.setTitleText("Deleting a project"); dialog.setMessage("Are you sure you want to delete this project?"); if (dialog.show() == MonologFXButton.Type.YES) { Project p = v_projectList.getSelectionModel().getSelectedItem(); descriptionValue.setText(""); projectModel.projectsProperty().remove(v_projectList.getSelectionModel().getSelectedItem()); } } } catch (Exception e) { handleException(e); } } @FXML public void machinesConfiguration(ActionEvent event) throws Exception { } @FXML public void toolsConfiguration(ActionEvent event) throws Exception { try { screens.toolConfigurationsDialog().showAndWait(); } catch (Exception e) { handleException(e); } } @FXML public void addMillTask(ActionEvent event) throws Exception { try { FXMLDialog mt = screens.millTaskDialog(); AddMillTaskController mtc = mt.getController(); mtc.setCurrentProject(v_projectList.getSelectionModel().getSelectedItem()); mt.showAndWait(); } catch (Exception e) { handleException(e); } } @FXML public void removeMillTask(ActionEvent event) throws Exception { try { if (tbl_millTasks.getSelectionModel().getSelectedCells().size() > 0) { MonologFX dialog = new MonologFX(MonologFX.Type.QUESTION); dialog.setTitleText("Deleting a milltask"); dialog.setMessage("Are you sure you want to delete this task?"); if (dialog.show() == MonologFXButton.Type.YES) { Project project = projectModel.projectsProperty() .get(v_projectList.getSelectionModel().getSelectedIndex()); project.millTasksProperty().remove(tbl_millTasks.getSelectionModel().getSelectedIndex()); } } } catch (Exception e) { handleException(e); } } @FXML public void editMillTask(ActionEvent event) throws Exception { try { final Project project = v_projectList.getSelectionModel().selectedItemProperty().get(); TaskRunnable taskRunnable = (TaskRunnable) tbl_millTasks.getSelectionModel().selectedItemProperty() .get(); screens.registerBean(taskRunnable.getClassName()); FXMLDialog dialog = screens.taskEditDialog(); TaskEditController controller = dialog.getController(); controller.setTask(project, taskRunnable.copy()); dialog.showAndWait(); if (controller.getReturned() == Result.SAVE) { int index = tbl_millTasks.getSelectionModel().getSelectedIndex(); TaskRunnable modified = controller.getTask(); project.millTasksProperty().add(index, modified); project.millTasksProperty().remove(tbl_millTasks.getItems().indexOf(taskRunnable)); tbl_millTasks.getSelectionModel().select(modified); } } catch (Exception e) { handleException(e); } } private void addProjectDefaults() { Project p = new Project("Round stock 30mm", "Creates a round stock of 100mx30mm. Feedrate 2400"); projectModel.addProject(p); TaskRunnable mt = new TaskRunnable("Make Round", "Make square stock round (invalid milltask)", "com.rvantwisk.cnctools.operations.createRoundStock.CreateRoundStockController", "CreateRoundStock.fxml"); ToolParameter nt = Factory.newTool(); nt.setName("6MM end Mill"); mt.setMilltaskModel(new RoundStockModel(new SimpleStringProperty(""), DimensionProperty.DimMM(30.0), DimensionProperty.DimMM(20.0), DimensionProperty.DimMM(100.0))); p.millTasksProperty().add(mt); mt = new TaskRunnable("Make Square", "Make round stock square", "com.rvantwisk.cnctools.operations.createRoundStock.CreateRoundStockController", "CreateRoundStock.fxml"); nt = Factory.newTool(); nt.setName("8MM end Mill"); nt.radialDepthProperty().set(DimensionProperty.DimMM(4.0)); nt.axialDepthProperty().set(DimensionProperty.DimMM(4.0)); nt.setToolType(new EndMill(new DimensionProperty(8.0, Dimensions.Dim.MM))); mt.setMilltaskModel(new RoundStockModel(new SimpleStringProperty(""), DimensionProperty.DimMM(30.0), DimensionProperty.DimMM(20.0), DimensionProperty.DimMM(100.0))); p.millTasksProperty().add(mt); p = new Project("Facing 30mmx30mm", "Facing of wood. Feedrate 2400"); mt = new TaskRunnable("Make Round Form Square", "Make feed edge", "com.rvantwisk.cnctools.operations.createRoundStock.CreateRoundStockController", "CreateRoundStock.fxml"); nt = Factory.newTool(); nt.setName("10mm end Mill"); nt.radialDepthProperty().set(DimensionProperty.DimMM(5.0)); nt.axialDepthProperty().set(DimensionProperty.DimMM(5.0)); nt.setToolType(new EndMill(new DimensionProperty(10.0, Dimensions.Dim.MM))); mt.setMilltaskModel(new RoundStockModel(new SimpleStringProperty(""), DimensionProperty.DimMM(30.0), DimensionProperty.DimMM(20.0), DimensionProperty.DimMM(100.0))); p.millTasksProperty().add(mt); projectModel.addProject(p); } private void addDefaultToolSet() { StockToolParameter stp = Factory.newStockTool(); projectModel.toolDBProperty().add(stp); stp = Factory.newStockTool(); stp.radialDepthProperty().set(DimensionProperty.DimMM(4.0)); stp.axialDepthProperty().set(DimensionProperty.DimMM(5.0)); stp.setToolType(new EndMill(new DimensionProperty(10.0, Dimensions.Dim.MM))); stp.setName("End Mill 10mm (Spindle)"); projectModel.toolDBProperty().add(stp); stp = Factory.newStockTool(); stp.radialDepthProperty().set(DimensionProperty.DimMM(3.0)); stp.axialDepthProperty().set(DimensionProperty.DimMM(4.0)); stp.setToolType(new EndMill(new DimensionProperty(8.0, Dimensions.Dim.MM))); stp.setName("End Mill 8mm"); projectModel.toolDBProperty().add(stp); stp = Factory.newStockTool(); stp.radialDepthProperty().set(DimensionProperty.DimMM(2.5)); stp.axialDepthProperty().set(DimensionProperty.DimMM(3.0)); stp.setToolType(new EndMill(new DimensionProperty(6.0, Dimensions.Dim.MM))); stp.setName("End Mill 6mm"); projectModel.toolDBProperty().add(stp); stp = Factory.newStockTool(); stp.radialDepthProperty().set(DimensionProperty.DimMM(4.0)); stp.axialDepthProperty().set(DimensionProperty.DimMM(5.0)); stp.setToolType(new BallMill(new DimensionProperty(10.0, Dimensions.Dim.MM))); stp.setName("Ball Mill 10mm"); projectModel.toolDBProperty().add(stp); stp = Factory.newStockTool(); stp.radialDepthProperty().set(DimensionProperty.DimMM(3.0)); stp.axialDepthProperty().set(DimensionProperty.DimMM(4.0)); stp.setToolType(new BallMill(new DimensionProperty(8.0, Dimensions.Dim.MM))); stp.setName("Ball Mill 8mm"); projectModel.toolDBProperty().add(stp); stp = Factory.newStockTool(); stp.radialDepthProperty().set(DimensionProperty.DimMM(2.5)); stp.axialDepthProperty().set(DimensionProperty.DimMM(5.0)); stp.setToolType(new BallMill(new DimensionProperty(6.0, Dimensions.Dim.MM))); stp.setName("Ball Mill 6mm"); projectModel.toolDBProperty().add(stp); } private void addDefaultPostprocessorSet() { // Defaul't MM post processor CNCToolsPostProcessConfig ppc = Factory.newPostProcessor(); ppc.setName("LinuxCNC (mm)"); ppc.preabmleProperty().set("%\n" + "G17 G21 G40 G49\n" + "G64 P0.01"); projectModel.postProcessorsProperty().add(ppc); ppc = Factory.newPostProcessor(); ppc.setName("LinuxCNC (inch)"); ppc.axisDecimalsProperty().put("A", 4); ppc.axisDecimalsProperty().put("B", 4); ppc.axisDecimalsProperty().put("C", 4); ppc.axisDecimalsProperty().put("X", 4); ppc.axisDecimalsProperty().put("Y", 4); ppc.axisDecimalsProperty().put("Z", 4); ppc.axisDecimalsProperty().put("U", 4); ppc.axisDecimalsProperty().put("V", 4); ppc.axisDecimalsProperty().put("W", 4); ppc.preabmleProperty().set("%\n" + "G17 G20 G40 G49\n" + "G64 P0.001"); projectModel.postProcessorsProperty().add(ppc); } @FXML // This method is called by the FXMLLoader when initialization is complete void initialize() { assert addMillTask != null : "fx:id=\"addMillTask\" was not injected: check your FXML file 'CNCTools.fxml'."; assert btnMoveTaskDown != null : "fx:id=\"btnMoveTaskDown\" was not injected: check your FXML file 'CNCTools.fxml'."; assert btnMoveTaskUp != null : "fx:id=\"btnMoveTaskUp\" was not injected: check your FXML file 'CNCTools.fxml'."; assert btnPostProcessor != null : "fx:id=\"btnPostProcessor\" was not injected: check your FXML file 'CNCTools.fxml'."; assert btnView != null : "fx:id=\"btnView\" was not injected: check your FXML file 'CNCTools.fxml'."; assert deleteProject != null : "fx:id=\"deleteProject\" was not injected: check your FXML file 'CNCTools.fxml'."; assert descriptionValue != null : "fx:id=\"descriptionValue\" was not injected: check your FXML file 'CNCTools.fxml'."; assert details != null : "fx:id=\"details\" was not injected: check your FXML file 'CNCTools.fxml'."; assert displayedIssueLabel != null : "fx:id=\"displayedIssueLabel\" was not injected: check your FXML file 'CNCTools.fxml'."; assert editMilltask != null : "fx:id=\"editMilltask\" was not injected: check your FXML file 'CNCTools.fxml'."; assert generateGCode != null : "fx:id=\"generateGCode\" was not injected: check your FXML file 'CNCTools.fxml'."; //assert millTaskDescription != null : "fx:id=\"millTaskDescription\" was not injected: check your FXML file 'CNCTools.fxml'."; //assert millTaskName != null : "fx:id=\"millTaskName\" was not injected: check your FXML file 'CNCTools.fxml'."; //assert millTaskOperation != null : "fx:id=\"millTaskOperation\" was not injected: check your FXML file 'CNCTools.fxml'."; assert milltaskEnabled != null : "fx:id=\"milltaskEnabled\" was not injected: check your FXML file 'CNCTools.fxml'."; assert removeMilltask != null : "fx:id=\"removeMilltask\" was not injected: check your FXML file 'CNCTools.fxml'."; assert tbl_millTasks != null : "fx:id=\"tbl_millTasks\" was not injected: check your FXML file 'CNCTools.fxml'."; assert v_projectList != null : "fx:id=\"v_projectList\" was not injected: check your FXML file 'CNCTools.fxml'."; v_projectList.setItems(projectModel.projectsProperty()); projectModel.loadPostProcessors(); if (projectModel.postProcessorsProperty().size() == 0) { addDefaultPostprocessorSet(); projectModel.savePostProcessors(); MonologFX dialog = new MonologFX(MonologFX.Type.INFO); dialog.setTitleText("Postprocessor defaults loaded"); dialog.setMessage("No Post Processors where found, a new a new post processor set has been created."); dialog.show(); } projectModel.loadToolsFromDB(); if (projectModel.toolDBProperty().size() == 0) { addDefaultToolSet(); projectModel.saveToolDB(); MonologFX dialog = new MonologFX(MonologFX.Type.INFO); dialog.setTitleText("Tools defaults loaded"); dialog.setMessage("No tools where found, a new a new toolset has been created."); dialog.show(); } projectModel.loadProjectsFromDB(); if (projectModel.projectsProperty().size() == 0) { addProjectDefaults(); projectModel.saveProjects(); MonologFX dialog = new MonologFX(MonologFX.Type.INFO); dialog.setTitleText("Project defaults loaded"); dialog.setMessage( "No project was found, a new template project was created. Feel free to delete or modify"); dialog.show(); } deleteProject.disableProperty().bind(v_projectList.getSelectionModel().selectedItemProperty().isNull()); btnPostProcessor.disableProperty().bind(v_projectList.getSelectionModel().selectedItemProperty().isNull()); btnView.disableProperty().bind(v_projectList.getSelectionModel().selectedItemProperty().isNull()); removeMilltask.disableProperty().bind(tbl_millTasks.getSelectionModel().selectedItemProperty().isNull()); addMillTask.disableProperty().bind(v_projectList.getSelectionModel().selectedItemProperty().isNull()); editMilltask.disableProperty().bind(tbl_millTasks.getSelectionModel().selectedItemProperty().isNull()); generateGCode.disableProperty().bind(v_projectList.getSelectionModel().selectedItemProperty().isNull()); // Update description when project changes by means of databinding v_projectList.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Project>() { @Override public void changed(ObservableValue<? extends Project> observable, Project oldValue, Project newValue) { if (oldValue != null) { descriptionValue.textProperty().unbindBidirectional(oldValue.descriptionProperty()); } if (projectModel.projectsProperty().size() == 0) { tbl_millTasks.getItems().clear(); } else { tbl_millTasks.setItems(newValue.millTasksProperty()); descriptionValue.textProperty().bindBidirectional(newValue.descriptionProperty()); } } }); // Enable/Disable up/Down arrows tbl_millTasks.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TaskRunnable>() { @Override public void changed(ObservableValue<? extends TaskRunnable> observable, TaskRunnable o, TaskRunnable o2) { if (o2 != null) { final int index = tbl_millTasks.getSelectionModel().getSelectedIndex(); btnMoveTaskUp.setDisable(index == 0 ? true : false); btnMoveTaskDown.setDisable((index + 1) == tbl_millTasks.getItems().size() ? true : false); } else { btnMoveTaskUp.setDisable(true); btnMoveTaskDown.setDisable(true); } } }); btnMoveTaskUp.setDisable(true); btnMoveTaskDown.setDisable(true); // Set text in ListView v_projectList.setCellFactory(new Callback<ListView<Project>, ListCell<Project>>() { @Override public ListCell<Project> call(ListView<Project> p) { ListCell<Project> cell = new ListCell<Project>() { @Override protected void updateItem(Project t, boolean bln) { super.updateItem(t, bln); if (t != null) { setText(t.nameProperty().getValue()); } else { setText(null); } } }; return cell; } }); // checkbox renderer for milltasks milltaskEnabled.setCellFactory( new Callback<TableColumn<TaskRunnable, Boolean>, TableCell<TaskRunnable, Boolean>>() { @Override public TableCell<TaskRunnable, Boolean> call(TableColumn<TaskRunnable, Boolean> p) { CheckBoxTableCell<TaskRunnable, Boolean> cell = new CheckBoxTableCell<>(); cell.setEditable(true); cell.setAlignment(Pos.CENTER); return cell; } }); tbl_millTasks.setEditable(true); // Save DB on exit getDialog().setOnHidden(new EventHandler<WindowEvent>() { public void handle(WindowEvent we) { save(null); } }); } public void save(ActionEvent actionEvent) { try { projectModel.saveProjects(); } catch (Exception e) { handleException(e); } try { projectModel.saveToolDB(); } catch (Exception e) { handleException(e); } try { projectModel.savePostProcessors(); } catch (Exception e) { handleException(e); } } @FXML public void onSelectPostprocessor(ActionEvent actionEvent) { try { if (v_projectList.getSelectionModel().selectedItemProperty().get() != null) { Project project = v_projectList.getSelectionModel().getSelectedItem(); final FXMLDialog dialog = screens.postProcessorsDialog(); PostProcessorsController controller = dialog.getController(); controller.setMode(PostProcessorsController.Mode.SELECT); controller.setPostProcessConfig(project.getPostProcessor()); dialog.showAndWait(); if (controller.getReturned() == Result.USE) { project.setPostProcessor( ProjectModel.<CNCToolsPostProcessConfig>deepCopy(controller.getPostProcessConfig())); } } } catch (Exception e) { handleException(e); } } @FXML public void onViewGCode(ActionEvent actionEvent) { try { if (v_projectList.getSelectionModel().selectedItemProperty().get() != null) { final Project p = v_projectList.getSelectionModel().selectedItemProperty().get(); if (p.postProcessorProperty().get() == null) { MonologFX dialog = new MonologFX(MonologFX.Type.QUESTION); dialog.setTitleText("No postprocessor"); dialog.setMessage("No post processor configured, please select a post processor first!"); dialog.show(); } else { File file = File.createTempFile("cnctools", "gcode"); final GCodeCollection gCode = p.getGCode(toolDBManager); file.createNewFile(); file.deleteOnExit(); if (file != null) { try (BufferedWriter br = Files.newBufferedWriter(file.toPath(), Charset.forName("UTF-8"), new OpenOption[] { StandardOpenOption.WRITE })) { br.write(gCode.concate().toString()); br.write("\n"); br.flush(); br.close(); Project project = projectModel.projectsProperty() .get(v_projectList.getSelectionModel().getSelectedIndex()); showGCodeFromFile(project, file.getAbsolutePath()); } catch (IOException ex) { handleException(ex); } } } } } catch (Exception e) { handleException(e); } } /** * Handle exception and show a strack trace, at least to inform the user that something was wrong * This is also a last resort, if you can handle the exception in the dialog, please do so and instruct the user! * * @param exception */ public void handleException(Exception exception) { logger.error("generateGCode: General Exception", exception); final FXMLDialog dialog = screens.errorDialog(); ErrorController controller = dialog.getController(); StringBuilder sb = new StringBuilder(); sb.append(exception.toString()).append("\n"); for (StackTraceElement trace : exception.getStackTrace()) { if (trace.getClassName().startsWith("com.rvantwisk")) { sb.append(trace.getClassName()).append(":").append(trace.getMethodName()).append(":") .append(trace.getLineNumber()).append("\n"); } } controller.setMessage(sb.toString()); dialog.showAndWait(); } @FXML void onMoveTaskUp(ActionEvent event) { final Project p = v_projectList.getSelectionModel().selectedItemProperty().get(); final int index = tbl_millTasks.getSelectionModel().getSelectedIndex() - 1; final TaskRunnable t1 = p.millTasksProperty().get(index); final TaskRunnable t2 = p.millTasksProperty().get(index + 1); p.millTasksProperty().remove(index); p.millTasksProperty().remove(index); p.millTasksProperty().add(index, t2); p.millTasksProperty().add(index + 1, t1); } @FXML void onMovetaskDown(ActionEvent event) { final Project p = v_projectList.getSelectionModel().selectedItemProperty().get(); final int index = tbl_millTasks.getSelectionModel().getSelectedIndex(); final TaskRunnable t1 = p.millTasksProperty().get(index); final TaskRunnable t2 = p.millTasksProperty().get(index + 1); p.millTasksProperty().remove(index); p.millTasksProperty().remove(index); p.millTasksProperty().add(index, t2); p.millTasksProperty().add(index + 1, t1); } }