001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.gui.io; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.awt.Component; 007 import java.awt.GridBagConstraints; 008 import java.awt.GridBagLayout; 009 import java.awt.event.ActionEvent; 010 import java.awt.event.FocusAdapter; 011 import java.awt.event.FocusEvent; 012 import java.io.File; 013 import java.util.EventObject; 014 import java.util.concurrent.CopyOnWriteArrayList; 015 016 import javax.swing.AbstractAction; 017 import javax.swing.JButton; 018 import javax.swing.JPanel; 019 import javax.swing.JTable; 020 import javax.swing.JTextField; 021 import javax.swing.event.CellEditorListener; 022 import javax.swing.event.ChangeEvent; 023 import javax.swing.table.TableCellEditor; 024 025 import org.openstreetmap.josm.actions.SaveActionBase; 026 027 /** 028 * This is a {@link TableCellEditor} for filenames. It provides a text input field and 029 * a button for launchinig a {@link JFileChooser}. 030 * 031 * 032 */ 033 class FilenameCellEditor extends JPanel implements TableCellEditor { 034 private JTextField tfFileName; 035 private CopyOnWriteArrayList<CellEditorListener> listeners; 036 private File value; 037 038 /** 039 * build the GUI 040 */ 041 protected void build() { 042 setLayout(new GridBagLayout()); 043 GridBagConstraints gc = new GridBagConstraints(); 044 gc.gridx = 0; 045 gc.gridy = 0; 046 gc.fill = GridBagConstraints.BOTH; 047 gc.weightx = 1.0; 048 gc.weighty = 1.0; 049 add(tfFileName = new JTextField(), gc); 050 051 gc.gridx = 1; 052 gc.gridy = 0; 053 gc.fill = GridBagConstraints.BOTH; 054 gc.weightx = 0.0; 055 gc.weighty = 1.0; 056 add(new JButton(new LaunchFileChooserAction())); 057 058 tfFileName.addFocusListener( 059 new FocusAdapter() { 060 @Override 061 public void focusGained(FocusEvent e) { 062 tfFileName.selectAll(); 063 } 064 } 065 ); 066 } 067 068 public FilenameCellEditor() { 069 listeners = new CopyOnWriteArrayList<CellEditorListener>(); 070 build(); 071 } 072 073 public void addCellEditorListener(CellEditorListener l) { 074 if (l != null) { 075 listeners.addIfAbsent(l); 076 } 077 } 078 079 protected void fireEditingCanceled() { 080 for (CellEditorListener l: listeners) { 081 l.editingCanceled(new ChangeEvent(this)); 082 } 083 } 084 085 protected void fireEditingStopped() { 086 for (CellEditorListener l: listeners) { 087 l.editingStopped(new ChangeEvent(this)); 088 } 089 } 090 091 public void cancelCellEditing() { 092 fireEditingCanceled(); 093 } 094 095 public Object getCellEditorValue() { 096 return value; 097 } 098 099 public boolean isCellEditable(EventObject anEvent) { 100 return true; 101 } 102 103 public void removeCellEditorListener(CellEditorListener l) { 104 listeners.remove(l); 105 } 106 107 public boolean shouldSelectCell(EventObject anEvent) { 108 return true; 109 } 110 111 public boolean stopCellEditing() { 112 if (tfFileName.getText() == null || tfFileName.getText().trim().equals("")) { 113 value = null; 114 } else { 115 value = new File(tfFileName.getText()); 116 } 117 fireEditingStopped(); 118 return true; 119 } 120 121 public void setInitialValue(File initialValue) { 122 this.value = initialValue; 123 if (initialValue == null) { 124 this.tfFileName.setText(""); 125 } else { 126 this.tfFileName.setText(initialValue.toString()); 127 } 128 } 129 130 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 131 SaveLayerInfo info = (SaveLayerInfo)value; 132 setInitialValue(info.getFile()); 133 tfFileName.selectAll(); 134 return this; 135 } 136 137 class LaunchFileChooserAction extends AbstractAction { 138 public LaunchFileChooserAction() { 139 putValue(NAME, "..."); 140 putValue(SHORT_DESCRIPTION, tr("Launch a file chooser to select a file")); 141 } 142 143 public void actionPerformed(ActionEvent e) { 144 File f = SaveActionBase.createAndOpenSaveFileChooser(tr("Select filename"), "osm"); 145 if (f != null) { 146 FilenameCellEditor.this.tfFileName.setText(f.toString()); 147 FilenameCellEditor.this.tfFileName.selectAll(); 148 } 149 } 150 } 151 }