/* * 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.comms.Communicator; import org.reprap.comms.snap.SNAPAddress; import org.reprap.comms.snap.SNAPCommunicator; import org.reprap.utilities.ExtensionFileFilter; /** * * mainpage RepRap Host Controller Software * * section overview Overview * * Please see http://reprap.org/ for more details. * */ public class Main { 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 PreviewPanel preview = null; // private JCheckBoxMenuItem viewBuilder; // private JCheckBoxMenuItem viewPreview; 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() { 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) { System.err.println("MachineFactory.create() failed.\n" + ex.toString()); } } 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 fileMenu = new JMenu("File"); //fileMenu.setMnemonic(KeyEvent.VK_F); //menubar.add(fileMenu); //JMenuItem fileOpen = new JMenuItem("Open...", KeyEvent.VK_O); //fileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)); //fileOpen.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // onOpen(); // }}); //fileMenu.add(fileOpen); //fileMenu.addSeparator(); //JMenuItem filePrefs = new JMenuItem("Preferences...", KeyEvent.VK_R); //filePrefs.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // Preferences prefs = new Preferences(); // prefs.setVisible(true); // prefs.show(); // }}); //fileMenu.add(filePrefs); //fileMenu.addSeparator(); //JMenuItem fileExit = new JMenuItem("Exit", KeyEvent.VK_X); //fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK)); //fileExit.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // dispose(); // }}); //fileMenu.add(fileExit); JMenu viewMenu = new JMenu("View"); viewMenu.setMnemonic(KeyEvent.VK_V); menubar.add(viewMenu); // JMenuItem viewToggle = new JMenuItem("Toggle view", KeyEvent.VK_V); // viewToggle.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK)); // viewToggle.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // onViewToggle(); // }}); // viewMenu.add(viewToggle); // viewBuilder = new JCheckBoxMenuItem("Setup build"); // viewBuilder.setSelected(true); // viewBuilder.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // onViewBuilder(); // }}); // viewMenu.add(viewBuilder); // viewPreview = new JCheckBoxMenuItem("Progress"); // viewPreview.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // onViewPreview(); // }}); // viewMenu.add(viewPreview); JMenu manipMenu = new JMenu("Manipulate"); manipMenu.setMnemonic(KeyEvent.VK_M); menubar.add(manipMenu); JMenuItem manipX = new JMenuItem("Rotate X", 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", 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 manipZ = new JMenuItem("Rotate Z", KeyEvent.VK_Z); manipZ.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK)); manipZ.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onRotateZ(); }}); manipMenu.add(manipZ); 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 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, ActionEvent.CTRL_MASK)); deleteSTL.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { onDelete(); }}); manipMenu.add(deleteSTL); //JMenu produceMenu = new JMenu("Build"); //produceMenu.setMnemonic(KeyEvent.VK_P); //menubar.add(produceMenu); 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); }}); //produceMenu.add(cancelMenuItem); //produceMenu.addSeparator(); segmentPause = new JCheckBoxMenuItem("Pause before segment"); //produceMenu.add(segmentPause); layerPause = new JCheckBoxMenuItem("Pause before layer"); //produceMenu.add(layerPause); //produceMenu.addSeparator(); //JMenuItem estimateMenuItemB = new JMenuItem("Estimate build resources...", KeyEvent.VK_E); //estimateMenuItemB.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // estimateResourcesB(); // }}); //produceMenu.add(estimateMenuItemB); //JMenu toolsMenu = new JMenu("Tools"); //toolsMenu.setMnemonic(KeyEvent.VK_T); //menubar.add(toolsMenu); //JMenuItem toolsWorkingVolume = new JMenuItem("Working volume probe", KeyEvent.VK_W); //toolsWorkingVolume.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // try { // new org.reprap.gui.steppertest.WorkingVolumeFrame(); // } // catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Working volume probe exception: " + ex); // ex.printStackTrace(); // } // }}); //toolsMenu.add(toolsWorkingVolume); //JMenuItem toolsMaintenancePositions = new JMenuItem("Maintenance positions", KeyEvent.VK_M); //toolsMaintenancePositions.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // try { // new org.reprap.gui.steppertest.MaintenancePositionsFrame(); // } // catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Maintenance positions exception: " + ex); // ex.printStackTrace(); // } // }}); //toolsMenu.add(toolsMaintenancePositions); //JMenuItem toolsExerciser = new JMenuItem("Stepper exerciser", KeyEvent.VK_S); //toolsExerciser.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // try { // org.reprap.gui.steppertest.Main.main(null); // } // catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Stepper exerciser exception: " + ex); // ex.printStackTrace(); // } // }}); //toolsMenu.add(toolsExerciser); //JMenuItem toolsExtruderExerciser = new JMenuItem("Extruder exerciser", KeyEvent.VK_E); //toolsExtruderExerciser.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // try { // org.reprap.gui.extrudertest.Main.main(null); // } // catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Extruder exerciser exception: " + ex); // ex.printStackTrace(); // } // }}); //toolsMenu.add(toolsExtruderExerciser); //JMenuItem toolsExtruderProfiler = new JMenuItem("Extruder heat profiler", KeyEvent.VK_H); //toolsExtruderProfiler.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent arg0) { // try { // org.reprap.gui.extruderprofile.Main.main(null); // } // catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Extruder profiler exception: " + ex); // ex.printStackTrace(); // } // }}); //toolsMenu.add(toolsExtruderProfiler); //JMenu diagnosticsMenu = new JMenu("Diagnostics"); //toolsMenu.add(diagnosticsMenu); //JMenuItem diagnosticsCommsTest = new JMenuItem("Basic comms test"); //diagnosticsMenu.add(diagnosticsCommsTest); // 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); // if(org.reprap.Preferences.loadGlobalBool("DisplaySimulation")) // panel.setRightComponent(createPreviewPanel()); // else // preview = null; panel.setDividerLocation(panel.getPreferredSize().width); mainFrame.getContentPane().add(panel); mainFrame.setJMenuBar(menubar); mainFrame.pack(); Utility.positionWindowOnScreen(mainFrame); mainFrame.setVisible(true); } // private Box createPreviewPanel() throws Exception { // // Box pane = new Box(BoxLayout.Y_AXIS); // pane.add(new JLabel("Build progress")); // preview = new PreviewPanel(); // pane.setMinimumSize(new Dimension(0,0)); // if(preview != null) // pane.add(preview); // // return pane; // } // private void onProduceT() { // cancelMenuItem.setEnabled(true); // produceProduceT.setEnabled(false); // Thread t = new Thread() { // public void run() { // Thread.currentThread().setName("Producer"); // try { // // TODO Some kind of progress indicator would be good // // if (!viewPreview.isSelected()) { // viewPreview.setSelected(true); // updateView(); // } // //// if(preview != null) //// { //// preview.setSegmentPause(segmentPause); //// preview.setLayerPause(layerPause); //// } // // producer = new Producer(printer, preview, builder); // producer.setSegmentPause(segmentPause); // producer.setLayerPause(layerPause); // producer.produce(); // String usage = getResourceMessage(producer); // producer.dispose(); // producer = null; // cancelMenuItem.setEnabled(false); // produceProduceT.setEnabled(true); // JOptionPane.showMessageDialog(mainFrame, "Production complete. " + // usage); // } // catch (Exception ex) { // JOptionPane.showMessageDialog(mainFrame, "Production exception: " + ex); // ex.printStackTrace(); // } // } // }; // t.start(); // } /** * 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 (!viewPreview.isSelected()) { // viewPreview.setSelected(true); // updateView(); // } // if(preview != null) // { // preview.setSegmentPause(segmentPause); // preview.setLayerPause(layerPause); // } if(printer == null) System.err.println("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. " + usage); } catch (Exception ex) { JOptionPane.showMessageDialog(mainFrame, "Production exception: " + ex); ex.printStackTrace(); } } }; t.start(); } public String onOpen() { String result = null; File f; int returnVal = chooser.showOpenDialog(null);// chooser.showOpenDialog(mainFrame); if(returnVal == JFileChooser.APPROVE_OPTION) { f = chooser.getSelectedFile(); result = "file:" + f.getAbsolutePath(); builder.anotherSTLFile(result); return f.getName(); } return ""; } public void deleteAllSTLs() { builder.deleteAllSTLs(); } private void onRotateX() { builder.xRotate(); } private void onRotateY() { builder.yRotate(); } private void onRotateZ() { builder.zRotate(); } private void oninToMM() { builder.inToMM(); } // private void onMaterial() { // builder.materialSTL(); // } private void onDelete() { builder.deleteSTL(); } public void mouseToWorld() { builder.mouseToWorld(); } // private void onViewBuilder() { //// if (!viewBuilder.isSelected() && !viewPreview.isSelected()) //// viewPreview.setSelected(true); // updateView(); // } // private void onViewPreview() { // if (!viewPreview.isSelected() && !viewBuilder.isSelected()) // viewBuilder.setSelected(true); // updateView(); // } // private void onViewToggle() { // if (viewBuilder.isSelected()) { // viewPreview.setSelected(true); // viewBuilder.setSelected(false); // } else { // viewPreview.setSelected(false); // viewBuilder.setSelected(true); // } // updateView(); // } // private void updateView() { //// if (viewBuilder.isSelected() && viewPreview.isSelected()) //// panel.setDividerLocation(0.5); //// else if (viewBuilder.isSelected()) // panel.setDividerLocation(1.0); //// else //// panel.setDividerLocation(0.0); // } // private void estimateResourcesT() { // EstimationProducer eProducer = null; // try { // eProducer = new EstimationProducer(builder); // eProducer.produce(); // JOptionPane.showMessageDialog(mainFrame, // "Expected " + getResourceMessage(eProducer)); // // } catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Exception during estimation: " + ex); // } finally { // if (eProducer != null) // eProducer.dispose(); // } // } // private void estimateResourcesB() { // EstimationProducer eProducer = null; // try { // eProducer = new EstimationProducer(builder); // eProducer.produce(); // JOptionPane.showMessageDialog(mainFrame, // "Expected " + getResourceMessage(eProducer)); // // } catch (Exception ex) { // JOptionPane.showMessageDialog(null, "Exception during estimation: " + ex); // } finally { // if (eProducer != null) // eProducer.dispose(); // } //} 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() { /// TODO This class should be fixed so it gets the dispose on window close try { // Attempt to save screen position if requested org.reprap.Preferences prefs = org.reprap.Preferences.getGlobalPreferences(); if (prefs.loadBool("RememberWindowPosition")) { //prefs.setGlobalBool("MainWindowTop", xxx) } } catch (Exception ex) { } System.exit(0); } public static void main(String[] args) { Thread.currentThread().setName("Main"); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { try { initComms(); } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Error initialising comms: " + ex); ex.printStackTrace(); } 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; private static void initComms() throws Exception { SNAPAddress myAddress = new SNAPAddress(localNodeNumber); String port = ""; String err = ""; String machine = "simulator"; @SuppressWarnings("unused") Boolean use_serial = false; repRapAttached = false; try { port = org.reprap.Preferences.loadGlobalString("Port(name)"); machine = org.reprap.Preferences.loadGlobalString("RepRap_Machine"); use_serial = org.reprap.Preferences.loadGlobalBool("GCodeUseSerial"); } catch (Exception e) {} if (machine.equals("SNAPRepRap")) { try { communicator = new SNAPCommunicator(port, myAddress); } catch (gnu.io.NoSuchPortException e) { err = "\nCould not connect at " + port + ".\n\n"; err += "Check to make sure that is the right path.\n"; err += "Check that you have your serial connector plugged in.\n\n"; err += "The program will continue but your geometry preference has been set to 'nullcartesian' for this session."; org.reprap.Preferences.setGlobalString("RepRap_Machine", "simulator"); communicator = null; throw new Exception(err); } catch (gnu.io.PortInUseException e) { err = "\nThe " + port + " port is already in use by another program, or your bot isn't plugged in.\n"; err += "The program will continue but your geometry preference has been set to 'nullcartesian' for this session."; org.reprap.Preferences.setGlobalString("RepRap_Machine", "simulator"); throw new Exception(err); } catch (Exception e) { e.printStackTrace(); } repRapAttached = true; } } 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; }