public static boolean openFolderAvailable() { if (Base.isWindows() || Base.isMacOS()) return true; if (Base.isLinux()) { // Assume that this is set to something valid if (preferences.get("launcher.linux", null) != null) { return true; } // Attempt to use gnome-open try { Process p = Runtime.getRuntime().exec(new String[] {"gnome-open"}); p.waitFor(); // Not installed will throw an IOException (JDK 1.4.2, Ubuntu // 7.04) preferences.put("launcher.linux", "gnome-open"); return true; } catch (Exception e) { } // Attempt with kde-open try { Process p = Runtime.getRuntime().exec(new String[] {"kde-open"}); p.waitFor(); preferences.put("launcher.linux", "kde-open"); return true; } catch (Exception e) { } } return false; }
/** * Make sure the sketch hasn't been moved or deleted by some nefarious user. If they did, try to * re-create it and save. Only checks to see if the main folder is still around, but not its * contents. */ protected void ensureExistence() { if (folder.exists()) return; Base.showWarning( "Sketch Disappeared", "The sketch folder has disappeared.\n " + "Will attempt to re-save in the same location,\n" + "but anything besides the code will be lost.", null); try { folder.mkdirs(); modified = true; for (int i = 0; i < codeCount; i++) { code[i].save(); // this will force a save } for (int i = 0; i < hiddenCount; i++) { hidden[i].save(); // this will force a save } calcModified(); } catch (Exception e) { Base.showWarning( "Could not re-save sketch", "Could not properly re-save the sketch. " + "You may be in trouble at this point,\n" + "and it might be time to copy and paste " + "your code to another text editor.", e); } }
/** * Implements the other cross-platform headache of opening a folder in the machine's native file * browser. */ public static void openFolder(File file) { try { String folder = file.getAbsolutePath(); if (Base.isWindows()) { // doesn't work // Runtime.getRuntime().exec("cmd /c \"" + folder + "\""); // works fine on winxp, prolly win2k as well Runtime.getRuntime().exec("explorer \"" + folder + "\""); // not tested // Runtime.getRuntime().exec("start explorer \"" + folder + // "\""); } else if (Base.isMacOS()) { openURL(folder); // handles char replacement, etc } else if (Base.isLinux()) { String launcher = preferences.get("launcher.linux", null); if (launcher != null) { Runtime.getRuntime().exec(new String[] {launcher, folder}); } } } catch (IOException e) { e.printStackTrace(); } }
protected JComponent createBeepPanel() { JPanel beepPanel = new JPanel(); final JFormattedTextField beepFreq = new JFormattedTextField(Base.getLocalFormat()); final JFormattedTextField beepDur = new JFormattedTextField(Base.getLocalFormat()); final JButton beepButton = new JButton("Beep Beep!"); beepFreq.setColumns(5); beepDur.setColumns(5); final int EFFECT_DO_IMMEDATELY = 0; // / beepButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { Base.logger.severe("running sendBeep"); machine.runCommand( new SendBeep( ((Number) beepFreq.getValue()).intValue(), ((Number) beepDur.getValue()).intValue(), EFFECT_DO_IMMEDATELY)); } }); beepPanel.add(new JLabel("Frequency"), "split"); beepPanel.add(beepFreq, "growy"); beepPanel.add(new JLabel("Duration"), "gap unrel"); beepPanel.add(beepDur, "growx"); beepPanel.add(beepButton, "gap unrel"); return beepPanel; }
public String getMachineInfo() { Driver driver = Base.getMachineLoader().getDriver(); String info = new String(); info += "System Information" + "\n"; info += " ReplicatorG version: " + Base.VERSION_NAME + "\n"; info += " Java version: " + System.getProperty("java.version") + "\n"; info += "\n"; info += "Machine" + "\n"; info += " Profile Name: " + Base.preferences.get("machine.name", "") + "\n"; info += " Driver Type: " + Base.getMachineLoader().getDriver().getDriverName() + "\n"; info += " Name: " + Base.getMachineLoader().getMachine().getMachineName() + "\n"; // TODO: Only if a printer is connected? info += " Motherboard firmware version: " + driver.getFirmwareInfo() + "\n"; // Status dump // Communication Statistics if (driver instanceof OnboardParameters) { CommunicationStatistics stats = ((OnboardParameters) driver).getCommunicationStatistics(); info += " Motherboard communication statistics" + "\n"; info += " Number of packets received from the USB interface:" + stats.packetCount + "\n"; info += " Number of packets sent over the RS485 interface:" + stats.sentPacketCount + "\n"; info += " Number of packets sent over the RS485 interface that were not responded to:" + stats.packetFailureCount + "\n"; info += " Number of packet retries attempted:" + stats.packetRetryCount + "\n"; info += " Number of bytes received over the RS485 interface that were discarded as noise:" + stats.noiseByteCount + "\n"; } // EEPROM dump // Toolhead info (per toolhead) // Default skeinforge version/profile info? // Machine Driver XML dump info += "\n"; info += "Machine Driver XML:" + "\n"; Node machineNode = MachineFactory.getMachineNode(Base.preferences.get("machine.name", "")); if (machineNode != null) { info += convertNodeToHtml(machineNode) + "\n"; } // Test communication return info; }
/** * Add a file to the sketch. * * <p>.gcode files will be added to the sketch folder. <br> * All other files will be added to the "data" folder. * * <p>If they don't exist already, the "code" or "data" folder will be created. * * <p> * * @return true if successful. */ public boolean addFile(File sourceFile) { String filename = sourceFile.getName(); File destFile = null; boolean addingCode = false; destFile = new File(this.folder, filename); addingCode = true; // make sure they aren't the same file if (!addingCode && sourceFile.equals(destFile)) { Base.showWarning( "You can't fool me", "This file has already been copied to the\n" + "location where you're trying to add it.\n" + "I ain't not doin nuthin'.", null); return false; } // in case the user is "adding" the code in an attempt // to update the sketch's tabs if (!sourceFile.equals(destFile)) { try { Base.copyFile(sourceFile, destFile); } catch (IOException e) { Base.showWarning("Error adding file", "Could not add '" + filename + "' to the sketch.", e); return false; } } // make the tabs update after this guy is added if (addingCode) { String newName = destFile.getName(); int newFlavor = -1; if (newName.toLowerCase().endsWith(".gcode")) { newName = newName.substring(0, newName.length() - 6); newFlavor = GCODE; } // see also "nameCode" for identical situation SketchCode newCode = new SketchCode(newName, destFile, newFlavor); insertCode(newCode); sortCode(); setCurrent(newName); editor.header.repaint(); } return true; }
public RealtimePanel(MachineInterface machine2) { super("Real time control and tuning"); Image icon = Base.getImage("images/icon.gif", this); setIconImage(icon); machine = machine2; driver = machine.getDriver(); ((RealtimeControl) driver).enableRealtimeControl(true); // create all our GUI interfaces JPanel speedPanel = new JPanel(); JPanel extrusionPanel = new JPanel(); add(new JLabel("Build speed (during extrusion)")); // Speed feedrateControl = new ControlSlider("Feedrate", "%", 5, 800, 100, speedPanel); // feedrateControl.getSlider().setMajorTickSpacing(10); Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>(); labelTable.put(new Integer(10), new JLabel("Slow")); labelTable.put(new Integer(100), new JLabel("")); labelTable.put(new Integer(300), new JLabel("Fast")); labelTable.put(new Integer(500), new JLabel("Insane!")); feedrateControl.slider.setLabelTable(labelTable); // add(new JLabel("Travel feedrate (no extrusion"),"growx,wrap"); travelFeedrateControl = new ControlSlider("Travel feedrate", "%", 5, 800, 100, speedPanel); travelFeedrateControl.slider.setLabelTable(labelTable); // Extrusion extrusionPanel.add(new JLabel("Extrusion"), "growx,wrap"); extrusionControl = new ControlSlider("Material muliplier", "%", 5, 500, 100, extrusionPanel); // TODO: extrusion scaling is not implemented in the driver yet. extrusionControl.slider.setEnabled(false); extrusionControl.field.setEnabled(false); mainPanel = new JPanel(); mainPanel.setLayout(new MigLayout()); mainPanel.add(speedPanel, "flowy,wrap"); mainPanel.add(extrusionPanel, "flowy,wrap"); new SpeedLimit(mainPanel); // Show comms debug checkbox JCheckBox showCommsDebug = new JCheckBox("Show communications"); if (((RealtimeControl) driver).getDebugLevel() >= 2) showCommsDebug.setSelected(true); showCommsDebug.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { if (((JCheckBox) e.getSource()).isSelected()) { ((RealtimeControl) driver).setDebugLevel(2); } else { ((RealtimeControl) driver).setDebugLevel(1); } } }); mainPanel.add(showCommsDebug, "flowy,wrap"); add(mainPanel); }
public void mouseDragged(MouseEvent e) { if (startPoint == null) return; Point p = e.getPoint(); DragMode mode = DragMode.NONE; if (Base.isMacOS()) { if (button == MouseEvent.BUTTON1 && !e.isShiftDown()) { mode = DragMode.TRANSLATE_OBJECT; } } else { if (button == MouseEvent.BUTTON1) { mode = DragMode.TRANSLATE_OBJECT; } } double xd = (double) (p.x - startPoint.x); double yd = -(double) (p.y - startPoint.y); switch (mode) { case NONE: super.mouseDragged(e); break; case TRANSLATE_OBJECT: doTranslate(xd, yd); break; } startPoint = p; }
/** * path is location of the main .gcode file, because this is also simplest to use when opening the * file from the finder/explorer. */ public Sketch(MainWindow editor, String path) throws IOException { this.editor = editor; File mainFile = new File(path); // System.out.println("main file is " + mainFile); mainFilename = mainFile.getName(); // System.out.println("main file is " + mainFilename); // get the name of the sketch by chopping .gcode // off of the main file name if (mainFilename.endsWith(".gcode")) { name = mainFilename.substring(0, mainFilename.length() - 6); } else { name = mainFilename; mainFilename = mainFilename + ".gcode"; } tempBuildFolder = Base.getBuildFolder(); // Base.addBuildFolderToClassPath(); String parentPath = new File(path).getParent(); if (parentPath == null) { parentPath = "."; } folder = new File(parentPath); // System.out.println("sketch dir is " + folder); load(); }
/** Save all code in the current sketch. */ public boolean save() throws IOException { // make sure the user didn't hide the sketch folder ensureExistence(); // first get the contents of the editor text area if (current.modified) { current.program = editor.getText(); } // don't do anything if not actually modified // if (!modified) return false; if (isReadOnly()) { // if the files are read-only, need to first do a "save as". Base.showMessage( "Sketch is read-only", "Some files are marked \"read-only\", so you'll\n" + "need to re-save this sketch to another location."); // if the user cancels, give up on the save() if (!saveAs()) return false; } for (int i = 0; i < codeCount; i++) { if (code[i].modified) code[i].save(); } calcModified(); return true; }
/** Save all code in the current sketch. */ public boolean save() throws IOException { if (mainFilename == null) { return saveAs(); } if (isReadOnly()) { // if the files are read-only, need to first do a "save as". Base.showMessage( "File is read-only", "This file is marked \"read-only\", so you'll\n" + "need to re-save this file to another location."); // if the user cancels, give up on the save() if (!saveAs()) return false; return true; } BuildCode code = getCode(); if (code != null) { if (hasMainWindow) { if (code.isModified()) { code.program = editor.getText(); code.save(); } } } BuildModel model = getModel(); if (model != null) { if (model.isModified()) { model.save(); } } return true; }
/** * Change internal settings based on what was chosen in the prefs, then send a message to the * editor saying that it's time to do the same. */ public void applyFrame() { // put each of the settings into the table String newSizeText = fontSizeField.getText(); try { int newSize = Integer.parseInt(newSizeText.trim()); String fontName = Base.preferences.get("editor.font", "Monospaced,plain,12"); if (fontName != null) { String pieces[] = fontName.split(","); pieces[2] = String.valueOf(newSize); StringBuffer buf = new StringBuffer(); for (String piece : pieces) { if (buf.length() > 0) buf.append(","); buf.append(piece); } Base.preferences.put("editor.font", buf.toString()); } } catch (Exception e) { Base.logger.warning("ignoring invalid font size " + newSizeText); } String origUpdateUrl = Base.preferences.get("replicatorg.updates.url", ""); if (!origUpdateUrl.equals(firmwareUpdateUrlField.getText())) { FirmwareUploader.invalidateFirmware(); Base.preferences.put("replicatorg.updates.url", firmwareUpdateUrlField.getText()); FirmwareUploader.checkFirmware(); // Initiate a new firmware check } String logPath = logPathField.getText(); Base.preferences.put("replicatorg.logpath", logPath); Base.setLogFile(logPath); editor.applyPreferences(); }
/** * @param path The relative path to the file in the .replicatorG directory * @param autoCopy If true, copy over the file of the same name in the application directory if * none is found in the prefs directory. * @return */ public static File getUserFile(String path, boolean autoCopy) { if (path.contains("..")) { Base.logger.info("Attempted to access parent directory in " + path + ", skipping"); return null; } // First look in the user's local .replicatorG directory for the path. File f = new File(getUserDirectory(), path); // Make the parent file if not already there File dir = f.getParentFile(); if (!dir.exists()) { dir.mkdirs(); } if (autoCopy && !f.exists()) { // Check if there's an application-level version File original = getApplicationFile(path); // If so, copy it over if (original.exists()) { try { Base.copyFile(original, f); } catch (IOException ioe) { Base.logger.log( Level.SEVERE, "Couldn't copy " + path + " to your local .replicatorG directory", f); } } } return f; }
public void hideCode() { // make sure the user didn't hide the sketch folder ensureExistence(); // if read-only, give an error if (isReadOnly()) { // if the files are read-only, need to first do a "save as". Base.showMessage( "Sketch is Read-Only", "Some files are marked \"read-only\", so you'll\n" + "need to re-save the sketch in another location,\n" + "and try again."); return; } // don't allow hide of the main code // TODO maybe gray out the menu on setCurrent(0) if (currentIndex == 0) { Base.showMessage( "Can't do that", "You cannot hide the main " + ".gcode file from a sketch\n"); return; } // rename the file File newFile = new File(current.file.getAbsolutePath() + ".x"); if (!current.file.renameTo(newFile)) { Base.showWarning("Error", "Could not hide " + "\"" + current.file.getName() + "\".", null); return; } current.file = newFile; // move it to the hidden list if (hiddenCount == hidden.length) { SketchCode temp[] = new SketchCode[hiddenCount + 1]; System.arraycopy(hidden, 0, temp, 0, hiddenCount); hidden = temp; } hidden[hiddenCount++] = current; // remove it from the main list removeCode(current); // update the tabs setCurrent(0); editor.header.repaint(); }
private void showCurrentSettings() { Font editorFont = Base.getFontPref("editor.font", "Monospaced,plain,12"); fontSizeField.setText(String.valueOf(editorFont.getSize())); String firmwareUrl = Base.preferences.get("replicatorg.updates.url", FirmwareUploader.DEFAULT_UPDATES_URL); firmwareUpdateUrlField.setText(firmwareUrl); String logPath = Base.preferences.get("replicatorg.logpath", ""); logPathField.setText(logPath); }
/** * Generic Constructor. Creates an output file and registers as a machineListener * * @filename : desired output file */ public DataCapture(String filename) { try { outFile = new FileWriter(filename); } catch (IOException e) { Base.logger.severe("Couldn't open data capture file for writing:" + e.getMessage()); } // Listen to the machine, do you hear what it is telling you? Base.getMachineLoader().addMachineListener(this); }
/** * This gets the first feedrate used in a layer * * @param l * @return */ private String getFirstFeedrate(final Layer l) { final List<String> search = l.getCommands(); GCodeCommand gcode; for (int i = 0; i < search.size(); i++) { gcode = new GCodeCommand(search.get(i)); if (gcode.getCodeValue('F') != -1) return "F" + Base.getGcodeFormat().format(gcode.getCodeValue('F')); } return ""; }
public void unhideCode(String what) { SketchCode unhideCode = null; String name = what.substring(0, (what.indexOf(".") == -1 ? what.length() : what.indexOf("."))); String extension = what.indexOf(".") == -1 ? "" : what.substring(what.indexOf(".")); for (int i = 0; i < hiddenCount; i++) { if (hidden[i].name.equals(name) && Sketch.flavorExtensionsShown[hidden[i].flavor].equals(extension)) { // unhideIndex = i; unhideCode = hidden[i]; // remove from the 'hidden' list for (int j = i; j < hiddenCount - 1; j++) { hidden[j] = hidden[j + 1]; } hiddenCount--; break; } } // if (unhideIndex == -1) { if (unhideCode == null) { System.err.println("internal error: could find " + what + " to unhide."); return; } if (!unhideCode.file.exists()) { Base.showMessage("Can't unhide", "The file \"" + what + "\" no longer exists."); // System.out.println(unhideCode.file); return; } String unhidePath = unhideCode.file.getAbsolutePath(); File unhideFile = new File(unhidePath.substring(0, unhidePath.length() - 2)); if (!unhideCode.file.renameTo(unhideFile)) { Base.showMessage( "Can't unhide", "The file \"" + what + "\" could not be" + "renamed and unhidden."); return; } unhideCode.file = unhideFile; insertCode(unhideCode); sortCode(); setCurrent(unhideCode.name); editor.header.repaint(); }
/** Cleanup temporary files used during a build/run. */ public void cleanup() { // if the java runtime is holding onto any files in the build dir, we // won't be able to delete them, so we need to force a gc here System.gc(); // note that we can't remove the builddir itself, otherwise // the next time we start up, internal runs using Runner won't // work because the build dir won't exist at startup, so the classloader // will ignore the fact that that dir is in the CLASSPATH in run.sh Base.removeDescendants(tempBuildFolder); }
public DualStrusionConstruction( File leftFile, File rightFile, MutableGCodeSource startSource, MutableGCodeSource endSource, MachineType type, boolean useWipes) { this.leftFile = leftFile; this.rightFile = rightFile; this.useWipes = useWipes; this.machineType = type; startGCode = startSource.copy(); endGCode = endSource.copy(); if (useWipes) { leftWipe = Base.getMachineLoader().getMachineInterface().getModel().getWipeFor(ToolheadAlias.LEFT); rightWipe = Base.getMachineLoader().getMachineInterface().getModel().getWipeFor(ToolheadAlias.RIGHT); if (leftWipe == null || rightWipe == null) { String error = "Could not find wipes for the current machine: " + Base.getMachineLoader().getMachineInterface().getModel().toString() + ". Continuing without wipes."; JOptionPane.showConfirmDialog( null, error, "Could not find wipes!", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); useWipes = false; } } else { leftWipe = null; rightWipe = null; } }
public void newCode() { // make sure the user didn't hide the sketch folder ensureExistence(); // if read-only, give an error if (isReadOnly()) { // if the files are read-only, need to first do a "save as". Base.showMessage( "Sketch is Read-Only", "Some files are marked \"read-only\", so you'll\n" + "need to re-save the sketch in another location,\n" + "and try again."); return; } renamingCode = false; // editor.status.edit("Name for new file:", ""); }
public void renameCode() { // make sure the user didn't hide the sketch folder ensureExistence(); // if read-only, give an error if (isReadOnly()) { // if the files are read-only, need to first do a "save as". Base.showMessage( "Sketch is Read-Only", "Some files are marked \"read-only\", so you'll\n" + "need to re-save the sketch in another location,\n" + "and try again."); return; } // ask for new name of file (internal to window) // TODO maybe just popup a text area? renamingCode = true; // editor.status.edit(prompt, oldName); }
private ControlPanelWindow(MachineInterface newMachine) { super("Control Panel"); Image icon = Base.getImage("images/icon.gif", this); setIconImage(icon); // save our machine! machine = newMachine; machine.runCommand(new InvalidatePosition()); // Listen to it-- stop and close if we're in build mode. Base.getMachineLoader().addMachineListener(this); // default behavior setDefaultCloseOperation(DISPOSE_ON_CLOSE); // no menu bar. setJMenuBar(createMenuBar()); chooser = new JColorChooser(Color.BLACK); ActionListener okListener = new ActionListener() { public void actionPerformed(ActionEvent e) { Color ledColor = chooser.getColor(); Base.logger.severe("running setLedStrip"); try { machine.getDriver().setLedStrip(ledColor, 0); } catch (replicatorg.drivers.RetryException f) { Base.logger.severe("foo" + f.toString()); } // machine.runCommand(new SetLedStrip(ledColor, 0)); ledStripButton.setText(ShowColorChooserAction.buttonStringFromColor(ledColor)); } }; ledStripButton = new JButton(new ShowColorChooserAction(this, chooser, okListener, null, Color.BLACK)); // create all our GUI interfaces mainPanel = new JPanel(); mainPanel.setLayout(new MigLayout("gap 5, ins 5, flowy")); jogPanel = new JogPanel(machine); mainPanel.add(jogPanel, "split 4, growx, growy"); mainPanel.add(createActivationPanel(), "split, growx"); if (newMachine.getMachineType() == MachineType.THE_REPLICATOR) { mainPanel.add(ledStripButton, "growx"); // mainPanel.add(createBeepPanel(), "growx"); } mainPanel.add(alternateToolsPanel(), "newline, growy"); this.setResizable(false); add(mainPanel); // add our listener hooks. addWindowListener(this); // addWindowFocusListener(this); // addWindowStateListener(this); // start our various threads. updateThread = new UpdateThread(this); updateThread.start(); pollThread = new PollThread(machine); pollThread.start(); }
public class ExtruderOnboardParameters extends JPanel { private static final long serialVersionUID = 6353987389397209816L; private OnboardParameters target; // Float gui objects show at least 2 places, max 8 places for clarity it's a float private static final NumberFormat floatFormat = (NumberFormat) Base.getLocalFormat().clone(); { floatFormat.setMaximumFractionDigits(8); floatFormat.setMinimumFractionDigits(2); } private static final NumberFormat mmNumberFormat = (NumberFormat) Base.getLocalFormat().clone(); { floatFormat.setMaximumFractionDigits(0); floatFormat.setMinimumFractionDigits(0); } interface Commitable { public void commit(); // In a sane universe, this would be called "validate". In a sane universe // where Java actually implemented inheritance in a sane and happy manner. public boolean isCommitable(); } final int FIELD_WIDTH = 10; class ThermistorTablePanel extends JPanel implements Commitable { private static final long serialVersionUID = 7765098486598830410L; private JFormattedTextField betaField = new JFormattedTextField(floatFormat); private JFormattedTextField r0Field = new JFormattedTextField(floatFormat); private JFormattedTextField t0Field = new JFormattedTextField(floatFormat); // Toolhead or Heated Platform? private final int which; // private final ToolModel tool; private final int toolIndex; ThermistorTablePanel(int which, String titleText, int toolIndex /*ToolModel tool*/) { super(new MigLayout()); this.which = which; // this.tool = tool; this.toolIndex = toolIndex; setBorder(BorderFactory.createTitledBorder(titleText)); betaField.setColumns(FIELD_WIDTH); r0Field.setColumns(FIELD_WIDTH); t0Field.setColumns(FIELD_WIDTH); double beta = target.getBeta(which, toolIndex); if (beta == -1) beta = 4066; betaField.setValue((int) beta); add(new JLabel("Beta")); add(betaField, "wrap"); double r0 = target.getR0(which, toolIndex); if (r0 == -1) r0 = 100000; r0Field.setValue((int) r0); add(new JLabel("Thermistor Resistance")); add(r0Field, "wrap"); double t0 = target.getT0(which, toolIndex); if (t0 == -1) t0 = 25; t0Field.setValue((int) t0); add(new JLabel("Base Temperature")); add(t0Field, "wrap"); } public void commit() { int beta = ((Number) betaField.getValue()).intValue(); int r0 = ((Number) r0Field.getValue()).intValue(); int t0 = ((Number) t0Field.getValue()).intValue(); target.createThermistorTable(which, r0, t0, beta, this.toolIndex); } public boolean isCommitable() { return true; } } Vector<Commitable> commitList = new Vector<Commitable>(); private boolean commit() { for (Commitable c : commitList) { if (!c.isCommitable()) { return false; } } for (Commitable c : commitList) { c.commit(); } JOptionPane.showMessageDialog( this, "Changes will not take effect until the extruder board is reset. You can \n" + "do this by turning your machine off and then on, or by disconnecting and \n" + "reconnecting the extruder cable. Make sure you don't still have a USB2TTL \n" + "cable attached to the extruder controller, as the cable will keep the board \n" + "from resetting.", "Extruder controller reminder", JOptionPane.INFORMATION_MESSAGE); return true; } private class BackoffPanel extends JPanel implements Commitable { private static final long serialVersionUID = 6593800743174557032L; private JFormattedTextField stopMsField = new JFormattedTextField(mmNumberFormat); private JFormattedTextField reverseMsField = new JFormattedTextField(mmNumberFormat); private JFormattedTextField forwardMsField = new JFormattedTextField(mmNumberFormat); private JFormattedTextField triggerMsField = new JFormattedTextField(mmNumberFormat); // private final ToolModel tool; private int toolIndex; BackoffPanel(int toolIndex /*ToolModel tool*/) { this.toolIndex = toolIndex; setLayout(new MigLayout()); setBorder(BorderFactory.createTitledBorder("Reversal parameters")); stopMsField.setColumns(FIELD_WIDTH); reverseMsField.setColumns(FIELD_WIDTH); forwardMsField.setColumns(FIELD_WIDTH); triggerMsField.setColumns(FIELD_WIDTH); add(new JLabel("Time to pause (ms)")); add(stopMsField, "wrap"); add(new JLabel("Time to reverse (ms)")); add(reverseMsField, "wrap"); add(new JLabel("Time to advance (ms)")); add(forwardMsField, "wrap"); add(new JLabel("Min. extrusion time before reversal (ms)")); add(triggerMsField, "wrap"); OnboardParameters.BackoffParameters bp = target.getBackoffParameters(toolIndex); stopMsField.setValue(bp.stopMs); reverseMsField.setValue(bp.reverseMs); forwardMsField.setValue(bp.forwardMs); triggerMsField.setValue(bp.triggerMs); } public void commit() { OnboardParameters.BackoffParameters bp = new OnboardParameters.BackoffParameters(); bp.forwardMs = ((Number) forwardMsField.getValue()).intValue(); bp.reverseMs = ((Number) reverseMsField.getValue()).intValue(); bp.stopMs = ((Number) stopMsField.getValue()).intValue(); bp.triggerMs = ((Number) triggerMsField.getValue()).intValue(); target.setBackoffParameters(bp, toolIndex); } public boolean isCommitable() { return true; } } private class ExtraFeaturesPanel extends JPanel implements Commitable { private JCheckBox swapMotors; private JComboBox extCh, hbpCh, abpCh; private OnboardParameters.ExtraFeatures ef; // private final ToolModel tool; private int toolIndex; ExtraFeaturesPanel(int toolIndex /*ToolModel tool*/) { // this.tool = tool; this.toolIndex = toolIndex; setLayout(new MigLayout()); ef = target.getExtraFeatures(toolIndex); swapMotors = new JCheckBox("Use 2A/2B to drive DC motor instead of 1A/1B", ef.swapMotorController); add(swapMotors, "span 3,growx,wrap"); Vector<String> choices = new Vector<String>(); choices.add("Channel A"); choices.add("Channel B"); choices.add("Channel C"); extCh = new JComboBox(choices); extCh.setSelectedIndex(ef.heaterChannel); add(new JLabel("Extruder heater uses:")); add(extCh); add(new JLabel("(default ch. B)"), "wrap"); hbpCh = new JComboBox(choices); hbpCh.setSelectedIndex(ef.hbpChannel); add(new JLabel("Platform heater uses:")); add(hbpCh); add(new JLabel("(default ch. A)"), "wrap"); abpCh = new JComboBox(choices); abpCh.setSelectedIndex(ef.abpChannel); add(new JLabel("ABP motor uses:")); add(abpCh); add(new JLabel("(default ch. C)"), "wrap"); } public void commit() { ef.swapMotorController = swapMotors.isSelected(); ef.heaterChannel = extCh.getSelectedIndex(); ef.hbpChannel = hbpCh.getSelectedIndex(); ef.abpChannel = abpCh.getSelectedIndex(); target.setExtraFeatures(ef, toolIndex); } public boolean isCommitable() { int a = extCh.getSelectedIndex(); int b = hbpCh.getSelectedIndex(); int c = abpCh.getSelectedIndex(); if (a == b || b == c || a == c) { JOptionPane.showMessageDialog( this, "Two or more features are using the same mosfet channel!", "Channel conflict", JOptionPane.ERROR_MESSAGE); return false; } return true; } } private class PIDPanel extends JPanel implements Commitable { private NumberFormat eightPlaces = (NumberFormat) floatFormat.clone(); { eightPlaces.setMaximumFractionDigits(8); } private JFormattedTextField pField = new JFormattedTextField(floatFormat); private JFormattedTextField iField = new JFormattedTextField(eightPlaces); private JFormattedTextField dField = new JFormattedTextField(floatFormat); private final int which; // private final ToolModel tool; private int toolIndex; PIDPanel(int which, String name, int toolIndex) { this.which = which; this.toolIndex = toolIndex; setLayout(new MigLayout()); setBorder(BorderFactory.createTitledBorder(name)); pField.setColumns(FIELD_WIDTH); iField.setColumns(FIELD_WIDTH); dField.setColumns(FIELD_WIDTH); add(new JLabel("P parameter")); add(pField, "wrap"); add(new JLabel("I parameter")); add(iField, "wrap"); add(new JLabel("D parameter")); add(dField, "wrap"); OnboardParameters.PIDParameters pp = target.getPIDParameters(which, toolIndex); pField.setValue(pp.p); iField.setValue(pp.i); dField.setValue(pp.d); } public void commit() { OnboardParameters.PIDParameters pp = new OnboardParameters.PIDParameters(); pp.p = ((Number) pField.getValue()).floatValue(); pp.i = ((Number) iField.getValue()).floatValue(); pp.d = ((Number) dField.getValue()).floatValue(); target.setPIDParameters(which, pp, toolIndex); } public boolean isCommitable() { return true; } } class RegulatedCoolingFan extends JPanel implements Commitable { private static final long serialVersionUID = 7765098486598830410L; private JCheckBox coolingFanEnabled; private JFormattedTextField coolingFanSetpoint = new JFormattedTextField(floatFormat); // private final ToolModel tool; private final int toolIndex; RegulatedCoolingFan(/*ToolModel tool*/ int toolIndex) { super(new MigLayout()); // this.tool = tool; this.toolIndex = toolIndex; coolingFanEnabled = new JCheckBox( "Enable regulated cooling fan (stepper extruders only)", target.getCoolingFanEnabled(toolIndex)); add(coolingFanEnabled, "growx,wrap"); coolingFanSetpoint.setColumns(FIELD_WIDTH); coolingFanSetpoint.setValue((int) target.getCoolingFanSetpoint(toolIndex)); add(new JLabel("Setpoint (C)")); add(coolingFanSetpoint, "wrap"); } public void commit() { boolean enabled = coolingFanEnabled.isSelected(); int setpoint = ((Number) coolingFanSetpoint.getValue()).intValue(); target.setCoolingFanParameters(enabled, setpoint, toolIndex); } public boolean isCommitable() { return true; } } public ExtruderOnboardParameters(OnboardParameters target, ToolModel tool, JFrame parent) { this.target = target; int toolIndex = tool.getIndex(); Version v = new Version(0, 0); if (target instanceof Sanguino3GDriver) { v = ((Sanguino3GDriver) target).getToolVersion(); } setLayout(new MigLayout()); ThermistorTablePanel ttp; if (tool.hasExtruderThermistor()) { ttp = new ThermistorTablePanel(OnboardParameters.EXTRUDER, "Extruder thermistor", toolIndex); this.add(ttp); commitList.add(ttp); } if (tool.hasAutomatedPlatform()) { ttp = new ThermistorTablePanel( OnboardParameters.BUILD_PLATFORM, "Heated build platform thermistor", toolIndex); this.add(ttp, "wrap"); commitList.add(ttp); } if (tool.hasExtruderThermocouple()) { PIDPanel pidPanel = new PIDPanel(OnboardParameters.EXTRUDER, "Extruder PID parameters", toolIndex); this.add(pidPanel, "growx"); commitList.add(pidPanel); } if (v.atLeast(new Version(2, 4))) { PIDPanel pp = new PIDPanel(OnboardParameters.BUILD_PLATFORM, "Heated build platform", toolIndex); this.add(pp, "growx,wrap"); commitList.add(pp); } if (v.atLeast(new Version(2, 9))) { RegulatedCoolingFan rcf = new RegulatedCoolingFan(toolIndex); this.add(rcf, "span 2,growx,wrap"); commitList.add(rcf); } String machineType = target.getMachineType(); if (!(machineType.equals("MightyBoard") || machineType.equals("The Replicator") || machineType.equals("MightyBoard(unverified)"))) { JButton commitButton = new JButton("Commit Changes"); commitButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (ExtruderOnboardParameters.this.commit()) {} } }); add(commitButton, "newline, span 2"); } } }
/** * Implements the cross-platform headache of opening URLs TODO This code should be replaced by * PApplet.link(), however that's not a static method (because it requires an AppletContext when * used as an applet), so it's mildly trickier than just removing this method. */ public static void openURL(String url) { // System.out.println("opening url " + url); try { if (Base.isWindows()) { // this is not guaranteed to work, because who knows if the // path will always be c:\progra~1 et al. also if the user has // a different browser set as their default (which would // include me) it'd be annoying to be dropped into ie. // Runtime.getRuntime().exec("c:\\progra~1\\intern~1\\iexplore " // + currentDir // the following uses a shell execute to launch the .html file // note that under cygwin, the .html files have to be chmodded // +x // after they're unpacked from the zip file. i don't know why, // and don't understand what this does in terms of windows // permissions. without the chmod, the command prompt says // "Access is denied" in both cygwin and the "dos" prompt. // Runtime.getRuntime().exec("cmd /c " + currentDir + // "\\reference\\" + // referenceFile + ".html"); if (url.startsWith("http://")) { // open dos prompt, give it 'start' command, which will // open the url properly. start by itself won't work since // it appears to need cmd Runtime.getRuntime().exec("cmd /c start " + url); } else { // just launching the .html file via the shell works // but make sure to chmod +x the .html files first // also place quotes around it in case there's a space // in the user.dir part of the url Runtime.getRuntime().exec("cmd /c \"" + url + "\""); } } else if (Base.isMacOS()) { // com.apple.eio.FileManager.openURL(url); if (!url.startsWith("http://")) { // prepend file:// on this guy since it's a file url = "file://" + url; // replace spaces with %20 for the file url // otherwise the mac doesn't like to open it // can't just use URLEncoder, since that makes slashes into // %2F characters, which is no good. some might say // "useless" if (url.indexOf(' ') != -1) { StringBuffer sb = new StringBuffer(); char c[] = url.toCharArray(); for (int i = 0; i < c.length; i++) { if (c[i] == ' ') { sb.append("%20"); } else { sb.append(c[i]); } } url = sb.toString(); } } com.apple.mrj.MRJFileUtils.openURL(url); } else if (Base.isLinux()) { String launcher = preferences.get("launcher.linux", "gnome-open"); if (launcher != null) { Runtime.getRuntime().exec(new String[] {launcher, url}); } } else { String launcher = preferences.get("launcher", null); if (launcher != null) { Runtime.getRuntime().exec(new String[] {launcher, url}); } else { Base.logger.warning("Unspecified platform, no launcher available."); } } } catch (IOException e) { Base.showWarning("Could not open URL", "An error occurred while trying to open\n" + url, e); } }
/** * This is called upon return from entering a new file name. (that is, from either newCode or * renameCode after the prompt) This code is almost identical for both the newCode and renameCode * cases, so they're kept merged except for right in the middle where they diverge. */ public void nameCode(String newName) { // make sure the user didn't hide the sketch folder ensureExistence(); // if renaming to the same thing as before, just ignore. // also ignoring case here, because i don't want to write // a bunch of special stuff for each platform // (osx is case insensitive but preserving, windows insensitive, // *nix is sensitive and preserving.. argh) if (renamingCode && newName.equalsIgnoreCase(current.name)) { // exit quietly for the 'rename' case. // if it's a 'new' then an error will occur down below return; } // don't allow blank names if (newName.trim().equals("")) { return; } if (newName.trim().equals(".gcode")) { return; } String newFilename = null; int newFlavor = 0; // separate into newName (no extension) and newFilename (with ext) // add .gcode to file if it has no extension if (newName.endsWith(".gcode")) { newFilename = newName; newName = newName.substring(0, newName.length() - 6); newFlavor = GCODE; } else { newFilename = newName + ".gcode"; newFlavor = GCODE; } // dots are allowed for the .gcode and .java, but not in the name // make sure the user didn't name things poo.time.gcode // or something like that (nothing against poo time) if (newName.indexOf('.') != -1) { newFilename = newName + ".gcode"; } // create the new file, new SketchCode object and load it File newFile = new File(folder, newFilename); if (newFile.exists()) { // yay! users will try anything Base.showMessage( "Nope", "A file named \"" + newFile + "\" already exists\n" + "in \"" + folder.getAbsolutePath() + "\""); return; } File newFileHidden = new File(folder, newFilename + ".x"); if (newFileHidden.exists()) { // don't let them get away with it if they try to create something // with the same name as something hidden Base.showMessage( "No Way", "A hidden tab with the same name already exists.\n" + "Use \"Unhide\" to bring it back."); return; } if (renamingCode) { if (currentIndex == 0) { // get the new folder name/location File newFolder = new File(folder.getParentFile(), newName); if (newFolder.exists()) { Base.showWarning( "Cannot Rename", "Sorry, a sketch (or folder) named " + "\"" + newName + "\" already exists.", null); return; } // unfortunately this can't be a "save as" because that // only copies the sketch files and the data folder // however this *will* first save the sketch, then rename // first get the contents of the editor text area if (current.modified) { current.program = editor.getText(); try { // save this new SketchCode current.save(); } catch (Exception e) { Base.showWarning("Error", "Could not rename the sketch. (0)", e); return; } } if (!current.file.renameTo(newFile)) { Base.showWarning( "Error", "Could not rename \"" + current.file.getName() + "\" to \"" + newFile.getName() + "\"", null); return; } // save each of the other tabs because this is gonna be // re-opened try { for (int i = 1; i < codeCount; i++) { // if (code[i].modified) code[i].save(); code[i].save(); } } catch (Exception e) { Base.showWarning("Error", "Could not rename the sketch. (1)", e); return; } // now rename the sketch folder and re-open boolean success = folder.renameTo(newFolder); if (!success) { Base.showWarning("Error", "Could not rename the sketch. (2)", null); return; } // if successful, set base properties for the sketch File mainFile = new File(newFolder, newName + ".gcode"); mainFilename = mainFile.getAbsolutePath(); // having saved everything and renamed the folder and the main // .gcode, // use the editor to re-open the sketch to re-init state // (unfortunately this will kill positions for carets etc) editor.handleOpenUnchecked( mainFilename, currentIndex, editor.textarea.getSelectionStart(), editor.textarea.getSelectionEnd(), editor.textarea.getScrollPosition()); // get the changes into the sketchbook menu // (re-enabled in 0115 to fix bug #332) // editor.sketchbook.rebuildMenus(); } else { // else if something besides code[0] if (!current.file.renameTo(newFile)) { Base.showWarning( "Error", "Could not rename \"" + current.file.getName() + "\" to \"" + newFile.getName() + "\"", null); return; } // just reopen the class itself current.name = newName; current.file = newFile; current.flavor = newFlavor; } } else { // creating a new file try { newFile.createNewFile(); // TODO returns a boolean } catch (IOException e) { Base.showWarning( "Error", "Could not create the file \"" + newFile + "\"\n" + "in \"" + folder.getAbsolutePath() + "\"", e); return; } SketchCode newCode = new SketchCode(newName, newFile, newFlavor); insertCode(newCode); } // sort the entries sortCode(); // set the new guy as current setCurrent(newName + flavorExtensionsShown[newFlavor]); // update the tabs // editor.header.repaint(); editor.header.rebuild(); // force the update on the mac? Toolkit.getDefaultToolkit().sync(); // editor.header.getToolkit().sync(); }
/** @param driver Needed for the Replicator-specific options */ public PreferencesWindow(final MachineInterface machine) { super("Preferences"); setResizable(true); Image icon = Base.getImage("images/icon.gif", this); setIconImage(icon); JTabbedPane prefTabs = new JTabbedPane(); JPanel basic = new JPanel(); // Container content = this.getContentPane(); Container content = basic; content.setLayout(new MigLayout("fill")); content.add(new JLabel("MainWindow font size: "), "split"); fontSizeField = new JFormattedTextField(Base.getLocalFormat()); fontSizeField.setColumns(4); content.add(fontSizeField); content.add(new JLabel(" (requires restart of ReplicatorG)"), "wrap"); boolean checkTempDuringBuild = Base.preferences.getBoolean("build.monitor_temp", true); boolean displaySpeedWarning = Base.preferences.getBoolean("build.speed_warning", true); addCheckboxForPref( content, "Monitor temperature during builds", "build.monitor_temp", checkTempDuringBuild); addCheckboxForPref( content, "Display Accelerated Speed Warnings", "build.speed_warning", displaySpeedWarning); addCheckboxForPref( content, "Automatically connect to machine at startup", "replicatorg.autoconnect", true); addCheckboxForPref( content, "Show experimental machine profiles", "machine.showExperimental", false); addCheckboxForPref( content, "Review GCode for potential toolhead problems before building", "build.safetyChecks", true); addCheckboxForPref( content, "Break Z motion into separate moves (normally false)", "replicatorg.parser.breakzmoves", false); addCheckboxForPref( content, "Show starfield in model preview window", "ui.show_starfield", false); addCheckboxForPref( content, "Notifications in System tray", "ui.preferSystemTrayNotifications", false); addCheckboxForPref( content, "Automatically regenerate gcode when building from model view.", "build.autoGenerateGcode", true); addCheckboxForPref( content, "Use native avrdude for uploading code", "uploader.useNative", false); JPanel advanced = new JPanel(); content = advanced; content.setLayout(new MigLayout("fill")); JButton modelColorButton; modelColorButton = new JButton("Choose model color"); modelColorButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { // Note that this color is also defined in EditingModel.java Color modelColor = new Color(Base.preferences.getInt("ui.modelColor", -19635)); modelColor = JColorChooser.showDialog(null, "Choose Model Color", modelColor); if (modelColor == null) return; Base.preferences.putInt("ui.modelColor", modelColor.getRGB()); Base.getEditor().refreshPreviewPanel(); } }); modelColorButton.setVisible(true); content.add(modelColorButton, "split"); JButton backgroundColorButton; backgroundColorButton = new JButton("Choose background color"); backgroundColorButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { // Note that this color is also defined in EditingModel.java Color backgroundColor = new Color(Base.preferences.getInt("ui.backgroundColor", 0)); backgroundColor = JColorChooser.showDialog(null, "Choose Background Color", backgroundColor); if (backgroundColor == null) return; Base.preferences.putInt("ui.backgroundColor", backgroundColor.getRGB()); Base.getEditor().refreshPreviewPanel(); } }); backgroundColorButton.setVisible(true); content.add(backgroundColorButton, "wrap"); content.add(new JLabel("Firmware update URL: "), "split"); firmwareUpdateUrlField = new JTextField(34); content.add(firmwareUpdateUrlField, "growx, wrap"); { JLabel arcResolutionLabel = new JLabel("Arc resolution (in mm): "); content.add(arcResolutionLabel, "split"); double value = Base.preferences.getDouble("replicatorg.parser.curve_segment_mm", 1.0); JFormattedTextField arcResolutionField = new JFormattedTextField(Base.getLocalFormat()); arcResolutionField.setValue(new Double(value)); content.add(arcResolutionField); String arcResolutionHelp = "<html><small><em>" + "The arc resolution is the default segment length that the gcode parser will break arc codes <br>" + "like G2 and G3 into. Drivers that natively handle arcs will ignore this setting." + "</em></small></html>"; arcResolutionField.setToolTipText(arcResolutionHelp); arcResolutionLabel.setToolTipText(arcResolutionHelp); // content.add(new JLabel(arcResolutionHelp),"growx,wrap"); arcResolutionField.setColumns(10); arcResolutionField.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName() == "value") { try { Double v = (Double) evt.getNewValue(); if (v == null) return; Base.preferences.putDouble( "replicatorg.parser.curve_segment_mm", v.doubleValue()); } catch (ClassCastException cce) { Base.logger.warning( "Unexpected value type: " + evt.getNewValue().getClass().toString()); } } } }); } { JLabel sfTimeoutLabel = new JLabel("Skeinforge timeout: "); content.add(sfTimeoutLabel, "split, gap unrelated"); int value = Base.preferences.getInt("replicatorg.skeinforge.timeout", -1); JFormattedTextField sfTimeoutField = new JFormattedTextField(Base.getLocalFormat()); sfTimeoutField.setValue(new Integer(value)); content.add(sfTimeoutField, "wrap 10px, growx"); String sfTimeoutHelp = "<html><small><em>" + "The Skeinforge timeout is the number of seconds that replicatorg will wait while the<br>" + "Skeinforge preferences window is open. If you find that RepG freezes after editing profiles<br>" + "you can set this number greater than -1 (-1 means no timeout)." + "</em></small></html>"; sfTimeoutField.setToolTipText(sfTimeoutHelp); sfTimeoutLabel.setToolTipText(sfTimeoutHelp); // content.add(new JLabel(sfTimeoutHelp),"growx,wrap"); sfTimeoutField.setColumns(10); sfTimeoutField.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName() == "value") { try { Integer v = ((Number) evt.getNewValue()).intValue(); if (v == null) return; Base.preferences.putInt("replicatorg.skeinforge.timeout", v.intValue()); } catch (ClassCastException cce) { Base.logger.warning( "Unexpected value type: " + evt.getNewValue().getClass().toString()); } } } }); } { content.add(new JLabel("Debugging level (default INFO):"), "split"); content.add(makeDebugLevelDropdown(), "wrap"); final JCheckBox logCb = new JCheckBox("Log to file"); logCb.setSelected(Base.preferences.getBoolean("replicatorg.useLogFile", false)); content.add(logCb, "split"); logCb.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { Base.preferences.putBoolean("replicatorg.useLogFile", logCb.isSelected()); } }); final JLabel logPathLabel = new JLabel("Log file name: "); content.add(logPathLabel, "split"); logPathField = new JTextField(34); content.add(logPathField, "growx, wrap 10px"); logPathField.setEnabled(logCb.isSelected()); logPathLabel.setEnabled(logCb.isSelected()); logCb.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { JCheckBox box = (JCheckBox) e.getSource(); logPathField.setEnabled(box.isSelected()); logPathLabel.setEnabled(box.isSelected()); } }); } { final int defaultTemp = 75; final String tooltipGeneral = "When enabled, starting all builds heats components to this temperature"; final String tooltipHead = "Set preheat temperature for the specified toolhead"; final String tooltipPlatform = "Set preheat temperature for the build platfom"; final JCheckBox preheatCb = new JCheckBox("Preheat builds"); preheatCb.setToolTipText(tooltipGeneral); content.add(preheatCb, "split"); preheatCb.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { Base.preferences.putBoolean("build.doPreheat", preheatCb.isSelected()); } }); preheatCb.setSelected(Base.preferences.getBoolean("build.doPreheat", false)); final JLabel t0Label = new JLabel("Toolhead Right: "); final JLabel t1Label = new JLabel("Toolhead Left: "); final JLabel pLabel = new JLabel("Platform: "); Integer t0Value = Base.preferences.getInt("build.preheatTool0", defaultTemp); Integer t1Value = Base.preferences.getInt("build.preheatTool1", defaultTemp); Integer pValue = Base.preferences.getInt("build.preheatPlatform", defaultTemp); final JFormattedTextField t0Field = new JFormattedTextField(Base.getLocalFormat()); final JFormattedTextField t1Field = new JFormattedTextField(Base.getLocalFormat()); final JFormattedTextField pField = new JFormattedTextField(Base.getLocalFormat()); t0Field.setToolTipText(tooltipHead); t0Label.setToolTipText(tooltipHead); t1Field.setToolTipText(tooltipHead); t1Label.setToolTipText(tooltipHead); pField.setToolTipText(tooltipPlatform); pLabel.setToolTipText(tooltipPlatform); t0Field.setValue(t0Value); t1Field.setValue(t1Value); pField.setValue(pValue); // let's avoid creating too many Anon. inner Listeners, also is fewer lines (and just as // clear)! PropertyChangeListener p = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName() == "value") { double target; if (evt.getSource() == t0Field) { target = ((Number) t0Field.getValue()).doubleValue(); target = confirmTemperature(target, "temperature.acceptedLimit", 200.0); if (target == Double.MIN_VALUE) { t0Field.setValue(Base.preferences.getInt("build.preheatTool0", defaultTemp)); return; } Base.preferences.putInt("build.preheatTool0", (int) target); } else if (evt.getSource() == t1Field) { target = ((Number) t1Field.getValue()).doubleValue(); target = confirmTemperature(target, "temperature.acceptedLimit", 200.0); if (target == Double.MIN_VALUE) { t0Field.setValue(Base.preferences.getInt("build.preheatTool1", defaultTemp)); return; } Base.preferences.putInt("build.preheatTool1", (int) target); } else if (evt.getSource() == pField) { target = ((Number) pField.getValue()).doubleValue(); target = confirmTemperature(target, "temperature.acceptedLimit.bed", 110.0); if (target == Double.MIN_VALUE) { t0Field.setValue(Base.preferences.getInt("build.preheatPlatform", defaultTemp)); return; } Base.preferences.putInt("build.preheatPlatform", (int) target); } } } }; t0Field.addPropertyChangeListener(p); t1Field.addPropertyChangeListener(p); pField.addPropertyChangeListener(p); content.add(t0Label, "split, gap 20px"); content.add(t0Field, "split, growx"); content.add(t1Label, "split, gap unrelated"); content.add(t1Field, "split, growx"); content.add(pLabel, "split, gap unrelated"); content.add(pField, "split, growx, wrap 10px"); } { JButton b = new JButton("Select Python interpreter..."); content.add(b, "spanx,wrap 10px"); b.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { SwingPythonSelector sps = new SwingPythonSelector(PreferencesWindow.this); String path = sps.selectFreeformPath(); if (path != null) { PythonUtils.setPythonPath(path); } } }); } addInitialFilePrefs(content); prefTabs.add(basic, "Basic"); prefTabs.add(advanced, "Advanced"); content = getContentPane(); content.setLayout(new MigLayout()); content.add(prefTabs, "wrap"); JButton allPrefs = new JButton("View Preferences Table"); content.add(allPrefs, "split"); allPrefs.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { JFrame advancedPrefs = new AdvancedPrefs(); advancedPrefs.setVisible(true); } }); // Also available as a menu item in the main gui. JButton delPrefs = new JButton("Reset all preferences"); content.add(delPrefs); delPrefs.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent evt) { editor.resetPreferences(); } }); JButton button; button = new JButton("Close"); button.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { applyFrame(); dispose(); } }); content.add(button, "tag ok"); showCurrentSettings(); // closing the window is same as hitting cancel button addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); } }); ActionListener disposer = new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { dispose(); } }; Base.registerWindowCloseKeys(getRootPane(), disposer); pack(); Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); setLocation((screen.width - getWidth()) / 2, (screen.height - getHeight()) / 2); // handle window closing commands for ctrl/cmd-W or hitting ESC. getContentPane() .addKeyListener( new KeyAdapter() { public void keyPressed(KeyEvent e) { KeyStroke wc = MainWindow.WINDOW_CLOSE_KEYSTROKE; if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) || (KeyStroke.getKeyStrokeForEvent(e).equals(wc))) { dispose(); } } }); }
public static void main(String args[]) { // make sure that this is running on java 1.5 or better. if (Base.javaVersion < 1.5f) { Base.quitWithError( "Need to install Java 1.5", "This version of ReplicatorG requires\n" + "Java 1.5 or later to run properly.\n" + "Please visit java.com to upgrade.", null); } if (Base.isMacOS()) { // Default to sun's XML parser, PLEASE. Some apps are installing some janky-ass xerces. System.setProperty( "javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"); System.setProperty("com.apple.mrj.application.apple.menu.about.name", "ReplicatorG"); } // parse command line input for (int i = 0; i < args.length; i++) { // grab any opened file from the command line if (supportedExtension(args[i])) { Base.openedAtStartup = args[i]; } // Allow for [--debug] [DEBUGLEVEL] if (args[i].equals("--debug")) { int debugLevelArg = 2; if ((i + 1) < args.length) { try { debugLevelArg = Integer.parseInt(args[i + 1]); } catch (NumberFormatException e) { } ; } if (debugLevelArg == 0) { logger.setLevel(Level.INFO); logger.info("Debug level is 'INFO'"); } else if (debugLevelArg == 1) { logger.setLevel(Level.FINE); logger.info("Debug level is 'FINE'"); } else if (debugLevelArg == 2) { logger.setLevel(Level.FINER); logger.info("Debug level is 'FINER'"); } else if (debugLevelArg == 3) { logger.setLevel(Level.FINEST); logger.info("Debug level is 'FINEST'"); } else if (debugLevelArg >= 4) { logger.setLevel(Level.ALL); logger.info("Debug level is 'ALL'"); } } else if (args[i].startsWith("-")) { System.out.println("Usage: ./replicatorg [[--debug] [DEBUGLEVEL]] [filename.stl]"); System.exit(1); } } // Warn about read-only directories { File userDir = getUserDirectory(); String header = null; if (!userDir.exists()) header = new String("Unable to create user directory"); else if (!userDir.canWrite()) header = new String("Unable to write to user directory"); else if (!userDir.isDirectory()) header = new String("User directory must be a directory"); if (header != null) { Base.showMessage( header, "<html><body>ReplicatorG can not write to the directory " + userDir.getAbsolutePath() + ".<br>" + "Some functions of ReplicatorG, like toolpath generation and firmware updates,<br>" + "require ReplicatorG to write data to this directory. You should end this<br>" + "session, change the permissions on this directory, and start again."); } } // Use the default system proxy settings System.setProperty("java.net.useSystemProxies", "true"); // Use antialiasing implicitly System.setProperty("j3d.implicitAntialiasing", "true"); // Start the firmware check thread. FirmwareUploader.checkFirmware(); // MAC OS X ONLY: // register a temporary/early version of the mrj open document handler, // because the event may be lost (sometimes, not always) by the time // that MainWindow is properly constructed. MRJOpenDocumentHandler startupOpen = new MRJOpenDocumentHandler() { public void handleOpenFile(File file) { // this will only get set once.. later will be handled // by the MainWindow version of this fella if (Base.openedAtStartup == null) { Base.openedAtStartup = file.getAbsolutePath(); } } }; MRJApplicationUtils.registerOpenDocumentHandler(startupOpen); // Create the new application "Base" class. new Base(); }
public Base() { // set the look and feel before opening the window try { if (Base.isMacOS()) { // Only override the UI's necessary for ColorChooser and // FileChooser: Set<Object> includes = new HashSet<Object>(); includes.add("ColorChooser"); includes.add("FileChooser"); includes.add("Component"); includes.add("Browser"); includes.add("Tree"); includes.add("SplitPane"); QuaquaManager.setIncludedUIs(includes); // set the Quaqua Look and Feel in the UIManager UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel"); System.setProperty("apple.laf.useScreenMenuBar", "true"); } else if (Base.isLinux()) { // For 0120, trying out the gtk+ look and feel as the default. // This is available in Java 1.4.2 and later, and it can't // possibly // be any worse than Metal. (Ocean might also work, but that's // for // Java 1.5, and we aren't going there yet) UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); } else { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } } catch (Exception e) { e.printStackTrace(); } // use native popups so they don't look so crappy on osx JPopupMenu.setDefaultLightWeightPopupEnabled(false); SwingUtilities.invokeLater( new Runnable() { public void run() { // build the editor object editor = new MainWindow(); // Get sizing preferences. This is an issue of contention; let's look at how // other programs decide how to size themselves. editor.restorePreferences(); // add shutdown hook to store preferences Runtime.getRuntime() .addShutdownHook( new Thread("Shutdown Hook") { private final MainWindow w = editor; public void run() { w.onShutdown(); } }); boolean autoconnect = Base.preferences.getBoolean("replicatorg.autoconnect", true); String machineName = preferences.get("machine.name", null); editor.loadMachine(machineName, autoconnect); // show the window editor.setVisible(true); UpdateChecker.checkLatestVersion(editor); } }); if (logger.isLoggable(Level.FINE)) { logger.fine( "OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " (" + System.getProperty("os.arch") + ")"); logger.fine( "JVM: " + System.getProperty("java.version") + " " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.version") + " " + System.getProperty("java.vendor") + ")"); } }
/** Remove a piece of code from the sketch and from the disk. */ public void deleteCode() { // make sure the user didn't hide the sketch folder ensureExistence(); // if read-only, give an error if (isReadOnly()) { // if the files are read-only, need to first do a "save as". Base.showMessage( "Sketch is Read-Only", "Some files are marked \"read-only\", so you'll\n" + "need to re-save the sketch in another location,\n" + "and try again."); return; } // confirm deletion with user, yes/no Object[] options = {"OK", "Cancel"}; String prompt = (currentIndex == 0) ? "Are you sure you want to delete this sketch?" : "Are you sure you want to delete \"" + current.name + flavorExtensionsShown[current.flavor] + "\"?"; int result = JOptionPane.showOptionDialog( editor, prompt, "Delete", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (result == JOptionPane.YES_OPTION) { if (currentIndex == 0) { // need to unset all the modified flags, otherwise tries // to do a save on the handleNew() // delete the entire sketch Base.removeDir(folder); // get the changes into the sketchbook menu // sketchbook.rebuildMenus(); // make a new sketch, and i think this will rebuild the sketch // menu editor.handleNewUnchecked(); } else { // delete the file if (!current.file.delete()) { Base.showMessage("Couldn't do it", "Could not delete \"" + current.name + "\"."); return; } // remove code from the list removeCode(current); // just set current tab to the main tab setCurrent(0); // update the tabs editor.header.repaint(); } } }