package cz.cuni.lf1.lge.ThunderSTORM; import cz.cuni.lf1.lge.ThunderSTORM.ImportExport.IImportExport; import cz.cuni.lf1.lge.ThunderSTORM.results.IJResultsTable; import cz.cuni.lf1.lge.ThunderSTORM.UI.GUI; import cz.cuni.lf1.lge.ThunderSTORM.UI.Help; import cz.cuni.lf1.lge.ThunderSTORM.UI.MacroParser; import cz.cuni.lf1.lge.ThunderSTORM.results.GenericTable; import cz.cuni.lf1.lge.ThunderSTORM.results.IJGroundTruthTable; import cz.cuni.lf1.lge.ThunderSTORM.results.MeasurementProtocol; import cz.cuni.lf1.lge.ThunderSTORM.util.GridBagHelper; import cz.cuni.lf1.lge.ThunderSTORM.util.PluginCommands; import cz.cuni.lf1.lge.ThunderSTORM.util.MacroUI.DialogStub; import cz.cuni.lf1.lge.ThunderSTORM.util.MacroUI.ParameterKey; import cz.cuni.lf1.lge.ThunderSTORM.util.MacroUI.ParameterTracker; import cz.cuni.lf1.lge.ThunderSTORM.util.MacroUI.validators.IntegerValidatorFactory; import cz.cuni.lf1.lge.ThunderSTORM.util.MacroUI.validators.StringValidatorFactory; import cz.cuni.lf1.lge.ThunderSTORM.util.MacroUI.validators.ValidatorException; import ij.IJ; import ij.WindowManager; import ij.plugin.PlugIn; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.filechooser.FileNameExtensionFilter; public class ImportExportPlugIn implements PlugIn { public static final String IMPORT = "import"; public static final String EXPORT = "export"; private List<IImportExport> modules = null; private String[] moduleNames = null; private String[] moduleExtensions = null; private String path = null; public ImportExportPlugIn() { super(); this.path = null; } public ImportExportPlugIn(String path) { super(); this.path = path; } @Override public void run(String command) { GUI.setLookAndFeel(); //Valid command strings: //"import;results" //"export;results" //"import;ground-truth" //"export;ground-truth" String[] commands = command.split(";"); if(commands.length != 2) { throw new IllegalArgumentException("Malformed argument for Import/Export plug-in!"); } // try { //get table GenericTable table; boolean groundTruth = IJGroundTruthTable.IDENTIFIER.equals(commands[1]); if(groundTruth) { table = IJGroundTruthTable.getGroundTruthTable(); } else { table = IJResultsTable.getResultsTable(); } setupModules(); if(EXPORT.equals(commands[0])) { runExport(table, groundTruth); } else if(IMPORT.equals(commands[0])) { runImport(table, groundTruth); } } catch(Exception ex) { IJ.handleException(ex); } } private void runImport(GenericTable table, boolean groundTruth) { ImportDialog dialog = new ImportDialog(IJ.getInstance(), groundTruth); if(MacroParser.isRanFromMacro()) { dialog.getParams().readMacroOptions(); dialog.getFileParams().readMacroOptions(); } else { if(dialog.showAndGetResult() != JOptionPane.OK_OPTION) { return; } } path = dialog.getFilePath(); boolean resetFirst = !dialog.append.getValue(); int startingFrame = dialog.startingFrame.getValue(); IImportExport importer = getModuleByName(dialog.getFileFormat()); table.forceHide(); if(resetFirst) table.reset(); if(groundTruth) { callImporter(importer, table, path, startingFrame); } else { // IJResultsTable IJResultsTable ijrt = (IJResultsTable) table; try { ijrt.setAnalyzedImage(WindowManager.getImage(dialog.rawImageStack.getValue())); } catch(ArrayIndexOutOfBoundsException ex) { if(resetFirst) { ijrt.setAnalyzedImage(null); } } setupMeasurementProtocol(dialog.detectMeasurementProtocol.getValue()); callImporter(importer, table, path, startingFrame); AnalysisPlugIn.setDefaultColumnsWidth(ijrt); ijrt.setLivePreview(dialog.showPreview.getValue()); ijrt.showPreview(); } table.forceShow(); } private void runExport(GenericTable table, boolean groundTruth) { String[] colNames = (String[]) table.getColumnNames().toArray(new String[0]); ExportDialog dialog = new ExportDialog(IJ.getInstance(), groundTruth, colNames); if(MacroParser.isRanFromMacro()) { dialog.getParams().readMacroOptions(); dialog.getFileParams().readMacroOptions(); } else { if(dialog.showAndGetResult() != JOptionPane.OK_OPTION) { return; } } // eliminate the need to list all columns when running from macro // - if nothing is mentioned, assume user wants to export everything if (MacroParser.isRanFromMacro()) { boolean all = true; for (int i = 0; i < dialog.exportColumns.length; i++) { if (dialog.exportColumns[i].getValue()) { all = false; break; } } if (all) { for (int i = 0; i < dialog.exportColumns.length; i++) { dialog.exportColumns[i].setValue(true); } } } List<String> columns = new ArrayList<String>(); for(int i = 0; i < colNames.length; i++) { if(dialog.exportColumns[i].getValue()) { columns.add(colNames[i]); } } path = dialog.getFilePath(); //save protocol if(!groundTruth && dialog.saveProtocol.getValue()) { IJResultsTable ijrt = (IJResultsTable) table; if(ijrt.getMeasurementProtocol() != null) { ijrt.getMeasurementProtocol().exportToFile(getProtocolFilePath(path)); } } //export IImportExport exporter = getModuleByName(dialog.getFileFormat()); callExporter(exporter, table, path, dialog.getFloatPrecision(), columns); } private void setupMeasurementProtocol(boolean detectMeasurementProtocolFile) { // Create an empty protocol first IJResultsTable.getResultsTable().setMeasurementProtocol(new MeasurementProtocol()); if (detectMeasurementProtocolFile) { // Automatically load protocol, if available -> this allows for (re)calculation of // fitting uncertainties and other values that depend on the data about analysis. File protoFile = new File(getProtocolFilePath(path)); if (protoFile.exists() && protoFile.isFile()) { // Parse the protocol and attach it to the results table. MeasurementProtocol protocol = MeasurementProtocol.importFromFile(getProtocolFilePath(path)); IJResultsTable.getResultsTable().setMeasurementProtocol(protocol); // Also, update the available camera settings! if (!protocol.cameraSettings.isEmpty()) { CameraSetupPlugIn.params.setNoGuiParametersAllowed(true); // allow setting parameters even before UI is initialized if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.EM_GAIN_ENABLED)) { CameraSetupPlugIn.setIsEmGain((Boolean) protocol.cameraSettings.get(CameraSetupPlugIn.EM_GAIN_ENABLED)); } if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.EM_GAIN)) { CameraSetupPlugIn.setGain((Double) protocol.cameraSettings.get(CameraSetupPlugIn.EM_GAIN)); } if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.BASELINE_OFFSET)) { CameraSetupPlugIn.setOffset((Double) protocol.cameraSettings.get(CameraSetupPlugIn.BASELINE_OFFSET)); } if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.READOUT_NOISE)) { CameraSetupPlugIn.setReadoutNoise((Double) protocol.cameraSettings.get(CameraSetupPlugIn.READOUT_NOISE)); } if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.PHOTONS_TO_ADU)) { CameraSetupPlugIn.setPhotons2ADU((Double) protocol.cameraSettings.get(CameraSetupPlugIn.PHOTONS_TO_ADU)); } if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.PIXEL_SIZE)) { CameraSetupPlugIn.setPixelSize((Double) protocol.cameraSettings.get(CameraSetupPlugIn.PIXEL_SIZE)); } if (protocol.cameraSettings.containsKey(CameraSetupPlugIn.QUANTUM_EFFICIENCY)) { CameraSetupPlugIn.setQuantumEfficiency((Double) protocol.cameraSettings.get(CameraSetupPlugIn.QUANTUM_EFFICIENCY)); } CameraSetupPlugIn.params.setNoGuiParametersAllowed(false); // back to the default setting } } else { IJ.log("Measurement protocol was not found (we will not be able to recalculate fitting uncertainties if requested)."); } } } private void setupModules() { modules = ModuleLoader.getModules(IImportExport.class); moduleNames = new String[modules.size()]; moduleExtensions = new String[modules.size()]; for(int i = 0; i < moduleNames.length; i++) { moduleNames[i] = modules.get(i).getName(); moduleExtensions[i] = modules.get(i).getSuffix(); } } private String getProtocolFilePath(String fpath) { int dotpos = fpath.lastIndexOf('.'); if(dotpos < 0) { return fpath + "-protocol.txt"; } else { return fpath.substring(0, dotpos) + "-protocol.txt"; } } private void callExporter(IImportExport exporter, GenericTable table, String fpath, int floatPrecision, List<String> columns) { IJ.showStatus("ThunderSTORM is exporting your results..."); IJ.showProgress(0.0); try { exporter.exportToFile(fpath, floatPrecision, table, columns); IJ.showStatus("ThunderSTORM has exported your results."); } catch(IOException ex) { IJ.showStatus(""); IJ.showMessage("Exception", ex.getMessage()); } catch(Exception ex) { IJ.showStatus(""); IJ.handleException(ex); } IJ.showProgress(1.0); } private void callImporter(IImportExport importer, GenericTable table, String fpath, int startingFrame) { IJ.showStatus("ThunderSTORM is importing your file..."); IJ.showProgress(0.0); try { table.setOriginalState(); importer.importFromFile(fpath, table, startingFrame); table.convertAllColumnsToAnalogUnits(); IJ.showStatus("ThunderSTORM has imported your file."); } catch(IOException ex) { IJ.showStatus(""); IJ.showMessage("Exception", ex.getMessage()); } catch(Exception ex) { IJ.showStatus(""); IJ.handleException(ex); } IJ.showProgress(1.0); } public IImportExport getModuleByName(String name) { for(int i = 0; i < moduleNames.length; i++) { if(moduleNames[i].equals(name)) { return modules.get(i); } } throw new RuntimeException("No module found for name " + name + "."); } //---------------GUI----------------------- abstract class IODialog extends DialogStub { public ParameterTracker fileParams; public IODialog(ParameterTracker params, ParameterTracker fileParams, Window owner, String title) { super(params, owner, title); this.fileParams = fileParams; } @Override protected JPanel createButtonsPanel() { JPanel buttons = new JPanel(new GridBagLayout()); GridBagConstraints glueConstraints = new GridBagConstraints(); glueConstraints.fill = GridBagConstraints.HORIZONTAL; glueConstraints.weightx = 1; JButton okButton = createOKButton(); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { fileParams.readDialogOptions(); dispose(); result = JOptionPane.OK_OPTION; fileParams.recordMacroOptions(); if (fileParams.isPrefsSavingEnabled()) { fileParams.savePrefs(); } } catch (ValidatorException ex) { handleValidationException(ex); } } }); JButton defaultsButton = createDefaultsButton(); defaultsButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fileParams.resetToDefaults(true); } }); buttons.add(defaultsButton); buttons.add(Box.createHorizontalGlue(), glueConstraints); buttons.add(Help.createHelpButton(ImportExportPlugIn.class)); buttons.add(okButton); buttons.add(createCancelButton()); return buttons; } ParameterTracker getFileParams() { return fileParams; } } class ImportDialog extends IODialog { ParameterKey.String fileFormat; ParameterKey.String filePath; ParameterKey.Boolean detectMeasurementProtocol; ParameterKey.Integer startingFrame; ParameterKey.Boolean showPreview; ParameterKey.Boolean append; ParameterKey.String rawImageStack; private boolean groundTruth; public ImportDialog(Window owner, boolean groundTruth) { super(new ParameterTracker("thunderstorm.io"), new ParameterTracker("thunderstorm.io." + (groundTruth ? "gt" : "res")), owner, "Import" + (groundTruth ? " ground-truth" : "")); assert moduleNames != null && moduleNames.length > 0; fileFormat = fileParams.createStringField("fileFormat", StringValidatorFactory.isMember(moduleNames), moduleNames[0]); filePath = fileParams.createStringField("filePath", StringValidatorFactory.fileExists(), ""); startingFrame = params.createIntField("startingFrame", IntegerValidatorFactory.positiveNonZero(), 1); append = params.createBooleanField("append", null, false); this.groundTruth = groundTruth; if(!groundTruth) { detectMeasurementProtocol = fileParams.createBooleanField("detectMeasurementProtocol", null, true); showPreview = params.createBooleanField("livePreview", null, true); rawImageStack = params.createStringField("rawImageStack", StringValidatorFactory.openImages(true), ""); } } ParameterTracker getParams() { return params; } @Override protected void layoutComponents() { JTextField startingFrameTextField = new JTextField(20); JPanel cameraPanel = new JPanel(new BorderLayout()); cameraPanel.setBorder(new TitledBorder("Camera")); JButton cameraSetup = new JButton("Camera setup"); cameraSetup.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { MacroParser.runNestedWithRecording(PluginCommands.CAMERA_SETUP.getValue(), null); } }); cameraPanel.add(cameraSetup); add(cameraPanel, GridBagHelper.twoCols()); JPanel filePanel = new JPanel(new GridBagLayout()); filePanel.setBorder(new TitledBorder("Input File")); JComboBox<String> fileFormatCBox = new JComboBox<String>(moduleNames); JTextField filePathTextField = new JTextField(20); filePathTextField.getDocument().addDocumentListener(createDocListener(filePathTextField, fileFormatCBox)); fileFormatCBox.addItemListener(createItemListener(filePathTextField, fileFormatCBox)); JButton browseButton = createBrowseButton(filePathTextField, true, new FileNameExtensionFilter(createFilterString(moduleExtensions), moduleExtensions)); fileFormat.registerComponent(fileFormatCBox); filePath.registerComponent(filePathTextField); JPanel filePathPanel = new JPanel(new BorderLayout()); filePathPanel.add(filePathTextField); filePathPanel.add(browseButton, BorderLayout.EAST); filePathPanel.setPreferredSize(startingFrameTextField.getPreferredSize()); filePanel.add(new JLabel("File format:"), GridBagHelper.leftCol()); filePanel.add(fileFormatCBox, GridBagHelper.rightCol()); filePanel.add(new JLabel("File path:"), GridBagHelper.leftCol()); filePanel.add(filePathPanel, GridBagHelper.rightCol()); if(!groundTruth) { JCheckBox detectMeasurementProtocolCheckBox = new JCheckBox(); detectMeasurementProtocol.registerComponent(detectMeasurementProtocolCheckBox); filePanel.add(new JLabel("Try to load measurement protocol:"), GridBagHelper.leftCol()); filePanel.add(detectMeasurementProtocolCheckBox, GridBagHelper.rightCol()); } add(filePanel, GridBagHelper.twoCols()); JPanel concatenationPanel = new JPanel(new GridBagLayout()); concatenationPanel.setBorder(new TitledBorder("Results concatenation")); JCheckBox appendCheckBox = new JCheckBox(); startingFrame.registerComponent(startingFrameTextField); append.registerComponent(appendCheckBox); concatenationPanel.add(new JLabel("Append to current table:"), GridBagHelper.leftCol()); concatenationPanel.add(appendCheckBox, GridBagHelper.rightCol()); concatenationPanel.add(new JLabel("Starting frame number:"), GridBagHelper.leftCol()); concatenationPanel.add(startingFrameTextField, GridBagHelper.rightCol()); add(concatenationPanel, GridBagHelper.twoCols()); if(!groundTruth) { JCheckBox showPreviewCheckBox = new JCheckBox(); JComboBox<String> rawImageComboBox = createOpenImagesComboBox(true); rawImageComboBox.setPreferredSize(startingFrameTextField.getPreferredSize()); showPreview.registerComponent(showPreviewCheckBox); rawImageStack.registerComponent(rawImageComboBox); JPanel previewPanel = new JPanel(new GridBagLayout()); previewPanel.setBorder(new TitledBorder("Visualization")); previewPanel.add(new JLabel("Live preview:"), GridBagHelper.leftCol()); previewPanel.add(showPreviewCheckBox, GridBagHelper.rightCol()); previewPanel.add(new JLabel("Raw image sequence for overlay:"), GridBagHelper.leftCol()); previewPanel.add(rawImageComboBox, GridBagHelper.rightCol()); add(previewPanel, GridBagHelper.twoCols()); } add(Box.createVerticalStrut(10), GridBagHelper.twoCols()); add(createButtonsPanel(), GridBagHelper.twoCols()); params.loadPrefs(); fileParams.loadPrefs(); if(path != null && !path.isEmpty()) { filePath.setValue(path); } getRootPane().setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); pack(); setLocationRelativeTo(null); setModal(true); } public String getFilePath() { return filePath.getValue(); } public String getFileFormat() { return fileFormat.getValue(); } } class ExportDialog extends IODialog { ParameterKey.String fileFormat; ParameterKey.String filePath; ParameterKey.Integer floatPrecision; ParameterKey.Boolean[] exportColumns; ParameterKey.Boolean saveProtocol; private boolean groundTruth; private String[] columnHeaders; public ExportDialog(Window owner, boolean groundTruth, String[] columnHeaders) { super(new ParameterTracker("thunderstorm.io"), new ParameterTracker("thunderstorm.io." + (groundTruth ? "gt" : "res")), owner, "Export" + (groundTruth ? " ground-truth" : "")); assert moduleNames != null && moduleNames.length > 0; this.columnHeaders = columnHeaders; this.groundTruth = groundTruth; fileFormat = fileParams.createStringField("fileFormat", StringValidatorFactory.isMember(moduleNames), moduleNames[0]); filePath = fileParams.createStringField("filePath", null, ""); floatPrecision = fileParams.createIntField("floatPrecision", IntegerValidatorFactory.positive(), 5); exportColumns = new ParameterKey.Boolean[columnHeaders.length]; for(int i = 0; i < columnHeaders.length; i++) { exportColumns[i] = params.createBooleanField(columnHeaders[i], null, i != 0); } if(!groundTruth) { saveProtocol = params.createBooleanField("saveProtocol", null, true); } } ParameterTracker getParams() { return params; } @Override protected void layoutComponents() { JPanel pane = new JPanel(); pane.setLayout(new GridBagLayout()); GridBagConstraints componentConstraints = new GridBagConstraints(); componentConstraints.gridx = 0; componentConstraints.fill = GridBagConstraints.BOTH; componentConstraints.weightx = 1; JPanel filePanel = new JPanel(new GridBagLayout()); filePanel.setBorder(new TitledBorder("Output File")); JComboBox<String> fileFormatCBox = new JComboBox<String>(moduleNames); JTextField filePathTextField = new JTextField(20); filePathTextField.getDocument().addDocumentListener(createDocListener(filePathTextField, fileFormatCBox)); fileFormatCBox.addItemListener(createItemListener(filePathTextField, fileFormatCBox)); JButton browseButton = createBrowseButton(filePathTextField, true, new FileNameExtensionFilter(createFilterString(moduleExtensions), moduleExtensions)); JTextField floatPrecisionTextField = new JTextField(5); fileFormat.registerComponent(fileFormatCBox); filePath.registerComponent(filePathTextField); floatPrecision.registerComponent(floatPrecisionTextField); JPanel filePathPanel = new JPanel(new BorderLayout()); filePathPanel.setPreferredSize(filePathTextField.getPreferredSize()); filePathPanel.add(filePathTextField); filePathPanel.add(browseButton, BorderLayout.EAST); filePanel.add(new JLabel("File format:"), GridBagHelper.leftCol()); filePanel.add(fileFormatCBox, GridBagHelper.rightCol()); filePanel.add(new JLabel("File path:"), GridBagHelper.leftCol()); filePanel.add(filePathPanel, GridBagHelper.rightCol()); filePanel.add(new JLabel("Float precision:"), GridBagHelper.leftCol()); filePanel.add(floatPrecisionTextField, GridBagHelper.rightCol()); pane.add(filePanel, componentConstraints); if(!groundTruth) { JPanel protocolPanel = new JPanel(new GridBagLayout()); protocolPanel.setBorder(new TitledBorder("Protocol")); protocolPanel.add(Box.createHorizontalStrut(filePathTextField.getPreferredSize().width / 2), GridBagHelper.leftCol()); protocolPanel.add(Box.createHorizontalStrut(filePathTextField.getPreferredSize().width), GridBagHelper.rightCol()); JCheckBox saveProtocolCheckBox = new JCheckBox(); saveProtocol.registerComponent(saveProtocolCheckBox); protocolPanel.add(new JLabel("Save measurement protocol:"), GridBagHelper.leftCol()); protocolPanel.add(saveProtocolCheckBox, GridBagHelper.rightCol()); pane.add(protocolPanel, componentConstraints); } JPanel columnsPanel = new JPanel(new GridBagLayout()); columnsPanel.setBorder(new TitledBorder("Columns to export")); columnsPanel.add(Box.createHorizontalStrut(0), GridBagHelper.leftCol()); columnsPanel.add(Box.createHorizontalStrut(filePathTextField.getPreferredSize().width), GridBagHelper.rightCol()); for(int i = 0; i < columnHeaders.length; i++) { columnsPanel.add(new JLabel(columnHeaders[i]), GridBagHelper.leftCol()); JCheckBox colCheckBox = new JCheckBox(); exportColumns[i].registerComponent(colCheckBox); columnsPanel.add(colCheckBox, GridBagHelper.rightCol()); } pane.add(columnsPanel, componentConstraints); pane.add(Box.createVerticalStrut(10), componentConstraints); pane.add(createButtonsPanel(), componentConstraints); pane.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20)); JScrollPane scrollPane = new JScrollPane(pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setBorder(BorderFactory.createEmptyBorder()); add(scrollPane); params.loadPrefs(); fileParams.loadPrefs(); int maxScreenHeight = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().height; if(getHeight() > maxScreenHeight) { setSize(getWidth(), maxScreenHeight); } } @Override public int showAndGetResult() { setLocationRelativeTo(null); setModal(true); setResizable(true); layoutComponents(); pack(); setVisible(true); return result; } public String getFilePath() { return filePath.getValue(); } public String getFileFormat() { return fileFormat.getValue(); } public int getFloatPrecision() { return floatPrecision.getValue(); } } private String createFilterString(String[] moduleExtensions) { StringBuilder sb = new StringBuilder(); sb.append("Known formats("); for(String ext : moduleExtensions) { sb.append(ext); sb.append(","); } sb.deleteCharAt(sb.length() - 1); sb.append(")"); return sb.toString(); } private ItemListener createItemListener(final JTextField filePathTextField, final JComboBox<String> fileFormatCBox) { return new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { final String fp = filePathTextField.getText(); if(!fp.isEmpty()) { if(fp.endsWith("\\") || fp.endsWith("/")) { filePathTextField.setText(fp + "results." + moduleExtensions[fileFormatCBox.getSelectedIndex()]); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { int dotpos = fp.lastIndexOf('.'); if(dotpos > 0) { filePathTextField.setText(fp.substring(0, dotpos + 1) + moduleExtensions[fileFormatCBox.getSelectedIndex()]); } } }); } } } }; } private DocumentListener createDocListener(final JTextField filePathTextField, final JComboBox<String> fileFormatCBox) { return new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { handle(); } @Override public void removeUpdate(DocumentEvent e) { handle(); } @Override public void changedUpdate(DocumentEvent e) { } private void handle() { String fname = new File(filePathTextField.getText()).getName().trim(); if(fname.isEmpty()) { return; } int dotpos = fname.lastIndexOf('.'); if(dotpos >= 0) { String type = fname.substring(dotpos + 1).trim(); for(int i = 0; i < moduleExtensions.length; i++) { if(type.equals(moduleExtensions[i])) { //found correct suffix, adjust type combobox and return fileFormatCBox.setSelectedIndex(i); return; } } } else { //no suffix found if(!filePathTextField.isFocusOwner()) { //user is not writting text at the moment SwingUtilities.invokeLater(new Runnable() { @Override public void run() { String selectedTypeSuffix = moduleExtensions[fileFormatCBox.getSelectedIndex()]; filePathTextField.setText(filePathTextField.getText() + "." + selectedTypeSuffix); } }); } } } }; } }