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    }