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; }
/** @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 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"); } } }