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 }