/* * Created on Mar 29, 2006 * */ package org.reprap; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFileChooser; import javax.swing.filechooser.FileFilter; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JSplitPane; import javax.swing.KeyStroke; import javax.swing.WindowConstants; import org.reprap.geometry.Producer; import org.reprap.machines.MachineFactory; import org.reprap.gui.RepRapBuild; import org.reprap.gui.Utility; import org.reprap.gui.botConsole.BotConsoleFrame; import org.reprap.utilities.ExtensionFileFilter; import org.reprap.utilities.RrDeleteOnExit; import org.reprap.utilities.Debug; /** * * mainpage RepRap Host Controller Software * * section overview Overview * * Please see http://reprap.org/ for more details. * */ public class Main { public static RrDeleteOnExit ftd = null; //private static Communicator communicator = null; private static boolean repRapAttached = false; private Producer producer = null; private Printer printer = null; // Window to walk the file tree private JFileChooser chooser; private JFrame mainFrame; private RepRapBuild builder; private JCheckBoxMenuItem segmentPause; private JCheckBoxMenuItem layerPause; private JMenuItem cancelMenuItem; private JMenuItem produceProduceB; public void setSegmentPause(boolean state) { segmentPause.setState(state); } public void setLayerPause(boolean state) { layerPause.setState(state); } public void clickCancel() { cancelMenuItem.doClick(); } private JSplitPane panel; public Main() { ftd = new RrDeleteOnExit(); chooser = new JFileChooser(); // Do we want just to list .stl files, or all? // If all, comment out the next two lines FileFilter filter = new ExtensionFileFilter("STL", new String[] { "STL" }); chooser.setFileFilter(filter); try { printer = MachineFactory.create(); } catch (Exception ex) { Debug.e("MachineFactory.create() failed.\n"); ex.printStackTrace(); } } private void createAndShowGUI() throws Exception { JFrame.setDefaultLookAndFeelDecorated(false); mainFrame = new JFrame("RepRap grid: 20 mm"); mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Required so menus float over Java3D JPopupMenu.setDefaultLightWeightPopupEnabled(false); // Create menus JMenuBar menubar = new JMenuBar(); // JMenu viewMenu = new JMenu("View"); // viewMenu.setMnemonic(KeyEvent.VK_V); // menubar.add(viewMenu); JMenu manipMenu = new JMenu("Edit"); manipMenu.setMnemonic(KeyEvent.VK_M); menubar.add(manipMenu); JMenuItem manipX = new JMenuItem("Rotate X 90", KeyEvent.VK_X); manipX.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK)); manipX.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onRotateX(); }}); manipMenu.add(manipX); JMenuItem manipY = new JMenuItem("Rotate Y 90", KeyEvent.VK_Y); manipY.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK)); manipY.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onRotateY(); }}); manipMenu.add(manipY); JMenuItem manipZ45 = new JMenuItem("Rotate Z 45", KeyEvent.VK_Z); manipZ45.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK)); manipZ45.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onRotateZ(45); }}); manipMenu.add(manipZ45); JMenuItem manipZp25 = new JMenuItem("Z Anticlockwise 2.5", KeyEvent.VK_A); manipZp25.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.CTRL_MASK)); manipZp25.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onRotateZ(2.5); }}); manipMenu.add(manipZp25); JMenuItem manipZm25 = new JMenuItem("Z Clockwise 2.5", KeyEvent.VK_C); manipZm25.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK)); manipZm25.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onRotateZ(-2.5); }}); manipMenu.add(manipZm25); JMenuItem inToMM = new JMenuItem("Scale by 25.4 (in -> mm)", KeyEvent.VK_I); inToMM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, ActionEvent.CTRL_MASK)); inToMM.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { oninToMM(); }}); manipMenu.add(inToMM); JMenuItem changeMaterial = new JMenuItem("Change material", KeyEvent.VK_M); changeMaterial.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK)); changeMaterial.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onChangeMaterial(); }}); manipMenu.add(changeMaterial); JMenuItem nextP = new JMenuItem("Select next object that will be built", KeyEvent.VK_N); nextP.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK)); nextP.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onNextPicked(); }}); manipMenu.add(nextP); JMenuItem reorder = new JMenuItem("Reorder the building sequence", KeyEvent.VK_R); reorder.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.CTRL_MASK)); reorder.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onReorder(); }}); manipMenu.add(reorder); // JMenuItem deleteSTLW = new JMenuItem("Delete selected object", KeyEvent.VK_W); // deleteSTLW.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.CTRL_MASK)); // deleteSTLW.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // onDelete(); // }}); // manipMenu.add(deleteSTLW); JMenuItem deleteSTL = new JMenuItem("Delete selected object", KeyEvent.VK_DELETE); deleteSTL.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); deleteSTL.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onDelete(); }}); manipMenu.add(deleteSTL); produceProduceB = new JMenuItem("Start build...", KeyEvent.VK_B); // produceProduceB.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.CTRL_MASK)); // produceProduceB.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // onProduceB(); // }}); // produceMenu.add(produceProduceB); cancelMenuItem = new JMenuItem("Cancel", KeyEvent.VK_P); cancelMenuItem.setEnabled(false); // cancelMenuItem.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // if(producer != null) // producer.setCancelled(true); // }}); // // segmentPause = new JCheckBoxMenuItem("Pause before segment"); layerPause = new JCheckBoxMenuItem("Pause before layer"); // Create the main window area // This is a horizontal box layout that includes // both the builder and preview screens, one of // which may be invisible. Box builderFrame = new Box(BoxLayout.Y_AXIS); builderFrame.add(new JLabel("Setup build")); builder = new RepRapBuild(); builderFrame.setMinimumSize(new Dimension(0,0)); builderFrame.add(builder); panel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); panel.setPreferredSize(Utility.getDefaultAppSize()); panel.setMinimumSize(new Dimension(0, 0)); panel.setResizeWeight(0.5); panel.setOneTouchExpandable(true); panel.setContinuousLayout(true); panel.setLeftComponent(builderFrame); panel.setDividerLocation(panel.getPreferredSize().width); mainFrame.getContentPane().add(panel); mainFrame.setJMenuBar(menubar); mainFrame.pack(); Utility.positionWindowOnScreen(mainFrame); mainFrame.setVisible(true); } protected void finalize() throws Throwable { Debug.d("Main finalise()"); ftd.killThem(); } /** * Return the printer being used */ public Printer getPrinter() { return printer; } /** * Stop production * */ public void pause() { if(producer != null) producer.pause(); try { printer.stopMotor(); printer.stopValve(); printer.pause(); } catch (Exception ex) {} } /** * Resume production * NB: does not re-start the extruder * */ public void resume() { printer.resume(); if(producer != null) producer.resume(); } public int getLayers() { if(producer == null) return 0; return producer.getLayers(); } public int getLayer() { if(producer == null) return 0; return producer.getLayer(); } public void onProduceB() { cancelMenuItem.setEnabled(true); produceProduceB.setEnabled(false); Thread t = new Thread() { public void run() { Thread.currentThread().setName("Producer"); try { if(printer == null) Debug.e("Production attempted with null printer."); producer = new Producer(printer, builder); producer.setSegmentPause(segmentPause); producer.setLayerPause(layerPause); producer.produce(); String usage = getResourceMessage(producer); producer.dispose(); producer = null; cancelMenuItem.setEnabled(false); produceProduceB.setEnabled(true); JOptionPane.showMessageDialog(mainFrame, "Production complete - Exit"); dispose(); } catch (Exception ex) { JOptionPane.showMessageDialog(mainFrame, "Production exception: " + ex); ex.printStackTrace(); } } }; t.start(); } public File onOpen(String description, String[] extensions, String defaultRoot) { String result = null; File f; FileFilter filter = new ExtensionFileFilter(description, extensions); chooser.setFileFilter(filter); if(!defaultRoot.contentEquals("") && extensions.length == 1) { File defaultFile = new File(defaultRoot + "." + extensions[0]); chooser.setSelectedFile(defaultFile); } int returnVal = chooser.showOpenDialog(null); if(returnVal == JFileChooser.APPROVE_OPTION) { f = chooser.getSelectedFile(); result = "file:" + f.getAbsolutePath(); if(extensions[0].toUpperCase().contentEquals("RFO")) builder.addRFOFile(result); if(extensions[0].toUpperCase().contentEquals("STL")) builder.anotherSTLFile(result); return f; } return null; } public String saveRFO(String fileRoot) { String result = null; File f; FileFilter filter; File defaultFile = new File(fileRoot + ".rfo"); JFileChooser chooser = new JFileChooser(); chooser.setSelectedFile(defaultFile); filter = new ExtensionFileFilter("RFO file to write to", new String[] { "rfo" }); chooser.setFileFilter(filter); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setFileFilter(filter); int returnVal = chooser.showSaveDialog(null);// chooser.showOpenDialog(mainFrame); if(returnVal == JFileChooser.APPROVE_OPTION) { f = chooser.getSelectedFile(); result = "file:" + f.getAbsolutePath(); builder.saveRFOFile(result); return f.getName(); } return ""; } public String saveSCAD(String fileRoot) { String result = null; File f; FileFilter filter; File defaultFile = new File(fileRoot + ".scad"); JFileChooser chooser = new JFileChooser(); chooser.setSelectedFile(defaultFile); filter = new ExtensionFileFilter("Directory to put OpenSCAD files in", new String[] { "" }); chooser.setFileFilter(filter); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setFileFilter(filter); int returnVal = chooser.showSaveDialog(null);// chooser.showOpenDialog(mainFrame); if(returnVal == JFileChooser.APPROVE_OPTION) { f = chooser.getSelectedFile(); result = "file:" + f.getAbsolutePath(); builder.saveSCADFile(result); return f.getName(); } return ""; } public void deleteAllSTLs() { builder.deleteAllSTLs(); } private void onRotateX() { builder.xRotate(); } private void onRotateY() { builder.yRotate(); } private void onRotateZ(double angle) { builder.zRotate(angle); } private void oninToMM() { builder.inToMM(); } private void onChangeMaterial() { builder.changeMaterial(); } private void onNextPicked() { builder.nextPicked(); } private void onReorder() { builder.doReorder(); } // private void onMaterial() { // builder.materialSTL(); // } private void onDelete() { builder.deleteSTL(); } public void mouseToWorld() { builder.mouseToWorld(); } private String getResourceMessage(Producer rProducer) { double moved = Math.round(rProducer.getTotalDistanceMoved() * 10.0) / 10.0; double extruded = Math.round(rProducer.getTotalDistanceExtruded() * 10.0) / 10.0; double extrudedVolume = Math.round(rProducer.getTotalVolumeExtruded() * 10.0) / 10.0; double time = Math.round(rProducer.getTotalElapsedTime() * 10.0) / 10.0; return "Total distance travelled=" + moved + "mm. Total distance extruded=" + extruded + "mm. Total volume extruded=" + extrudedVolume + "mm^3. Elapsed time=" + time + "s"; } public void dispose() { Debug.d("Main dispose()"); ftd.killThem(); /// TODO This class should be fixed so it gets the dispose on window close System.exit(0); } public static void main(String[] args) { Thread.currentThread().setName("Main"); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { try { Thread.currentThread().setName("RepRap"); gui = new Main(); gui.createAndShowGUI(); } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Error in the main GUI: " + ex); ex.printStackTrace(); } gui.mainFrame.setFocusable(true); gui.mainFrame.requestFocus(); BotConsoleFrame.main(null); } }); } public static Main gui; public static void setRepRapPresent(boolean a) { repRapAttached = a; } public static boolean repRapPresent() { return repRapAttached; } // public static Communicator getCommunicator() { // return communicator; // } private static final int localNodeNumber = 0; }