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