source: josm/trunk/src/org/openstreetmap/josm/gui/io/LayerNameAndFilePathTableCell.java@ 6912

Last change on this file since 6912 was 6912, checked in by Don-vip, 10 years ago

Refactor duplicated code

File size: 8.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.Font;
10import java.awt.GridBagLayout;
11import java.awt.event.ActionEvent;
12import java.awt.event.FocusAdapter;
13import java.awt.event.FocusEvent;
14import java.io.File;
15import java.util.EventObject;
16
17import javax.swing.AbstractAction;
18import javax.swing.BorderFactory;
19import javax.swing.JButton;
20import javax.swing.JLabel;
21import javax.swing.JPanel;
22import javax.swing.JTable;
23import javax.swing.event.CellEditorListener;
24import javax.swing.table.TableCellEditor;
25import javax.swing.table.TableCellRenderer;
26
27import org.openstreetmap.josm.actions.SaveActionBase;
28import org.openstreetmap.josm.gui.util.CellEditorSupport;
29import org.openstreetmap.josm.gui.widgets.JosmTextField;
30import org.openstreetmap.josm.tools.GBC;
31
32class LayerNameAndFilePathTableCell extends JPanel implements TableCellRenderer, TableCellEditor {
33 private static final Color colorError = new Color(255,197,197);
34 private static final String separator = System.getProperty("file.separator");
35 private static final String ellipsis = "…" + separator;
36
37 private final JLabel lblLayerName = new JLabel();
38 private final JLabel lblFilename = new JLabel("");
39 private final JosmTextField tfFilename = new JosmTextField();
40 private final JButton btnFileChooser = new JButton(new LaunchFileChooserAction());
41
42 private static final GBC defaultCellStyle = GBC.eol().fill(GBC.HORIZONTAL).insets(2, 0, 2, 0);
43
44 private final CellEditorSupport cellEditorSupport = new CellEditorSupport(this);
45 private File value;
46
47 /** constructor that sets the default on each element **/
48 public LayerNameAndFilePathTableCell() {
49 setLayout(new GridBagLayout());
50
51 lblLayerName.setPreferredSize(new Dimension(lblLayerName.getPreferredSize().width, 19));
52 lblLayerName.setFont(lblLayerName.getFont().deriveFont(Font.BOLD));
53
54 lblFilename.setPreferredSize(new Dimension(lblFilename.getPreferredSize().width, 19));
55 lblFilename.setOpaque(true);
56
57 tfFilename.setToolTipText(tr("Either edit the path manually in the text field or click the \"...\" button to open a file chooser."));
58 tfFilename.setPreferredSize(new Dimension(tfFilename.getPreferredSize().width, 19));
59 tfFilename.addFocusListener(
60 new FocusAdapter() {
61 @Override
62 public void focusGained(FocusEvent e) {
63 tfFilename.selectAll();
64 }
65 }
66 );
67 // hide border
68 tfFilename.setBorder(BorderFactory.createLineBorder(getBackground()));
69
70 btnFileChooser.setPreferredSize(new Dimension(20, 19));
71 btnFileChooser.setOpaque(true);
72 }
73
74 /** renderer used while not editing the file path **/
75 @Override
76 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
77 boolean hasFocus, int row, int column) {
78 removeAll();
79 SaveLayerInfo info = (SaveLayerInfo)value;
80 StringBuilder sb = new StringBuilder();
81 sb.append("<html>");
82 sb.append(addLblLayerName(info));
83 sb.append("<br>");
84 add(btnFileChooser, GBC.std());
85 sb.append(addLblFilename(info));
86
87 sb.append("</html>");
88 setToolTipText(sb.toString());
89 return this;
90 }
91
92 @Override
93 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
94 removeAll();
95 SaveLayerInfo info = (SaveLayerInfo)value;
96 value = info.getFile();
97 tfFilename.setText(value == null ? "" : value.toString());
98
99 StringBuilder sb = new StringBuilder();
100 sb.append("<html>");
101 sb.append(addLblLayerName(info));
102 sb.append("<br/>");
103
104 add(btnFileChooser, GBC.std());
105 add(tfFilename, GBC.eol().fill(GBC.HORIZONTAL).insets(1, 0, 0, 0));
106 tfFilename.selectAll();
107
108 sb.append(tfFilename.getToolTipText());
109 sb.append("</html>");
110 setToolTipText(sb.toString());
111 return this;
112 }
113
114 private static boolean canWrite(File f) {
115 if (f == null) return false;
116 if (f.isDirectory()) return false;
117 if (f.exists() && f.canWrite()) return true;
118 if (!f.exists() && f.getParentFile() != null && f.getParentFile().canWrite())
119 return true;
120 return false;
121 }
122
123 /** adds layer name label to (this) using the given info. Returns tooltip that
124 * should be added to the panel **/
125 private String addLblLayerName(SaveLayerInfo info) {
126 lblLayerName.setIcon(info.getLayer().getIcon());
127 lblLayerName.setText(info.getName());
128 add(lblLayerName, defaultCellStyle);
129 return tr("The bold text is the name of the layer.");
130 }
131
132 /** adds filename label to (this) using the given info. Returns tooltip that
133 * should be added to the panel */
134 private String addLblFilename(SaveLayerInfo info) {
135 String tooltip = "";
136 boolean error = false;
137 if (info.getFile() == null) {
138 error = info.isDoSaveToFile();
139 lblFilename.setText(tr("Click here to choose save path"));
140 lblFilename.setFont(lblFilename.getFont().deriveFont(Font.ITALIC));
141 tooltip = tr("Layer ''{0}'' is not backed by a file", info.getName());
142 } else {
143 String t = info.getFile().getPath();
144 lblFilename.setText(makePathFit(t));
145 tooltip = info.getFile().getAbsolutePath();
146 if (info.isDoSaveToFile() && !canWrite(info.getFile())) {
147 error = true;
148 tooltip = tr("File ''{0}'' is not writable. Please enter another file name.", info.getFile().getPath());
149 }
150 }
151
152 lblFilename.setBackground(error ? colorError : getBackground());
153 btnFileChooser.setBackground(error ? colorError : getBackground());
154
155 add(lblFilename, defaultCellStyle);
156 return tr("Click cell to change the file path.") + "<br/>" + tooltip;
157 }
158
159 /** makes the given path fit lblFilename, appends ellipsis on the left if it doesn’t fit.
160 * Idea: /home/user/josm → …/user/josm → …/josm; and take the first one that fits */
161 private String makePathFit(String t) {
162 boolean hasEllipsis = false;
163 while(t != null && !t.isEmpty()) {
164 int txtwidth = lblFilename.getFontMetrics(lblFilename.getFont()).stringWidth(t);
165 if(txtwidth < lblFilename.getWidth() || t.lastIndexOf(separator) < ellipsis.length()) {
166 break;
167 }
168 // remove ellipsis, if present
169 t = hasEllipsis ? t.substring(ellipsis.length()) : t;
170 // cut next block, and re-add ellipsis
171 t = ellipsis + t.substring(t.indexOf(separator) + 1);
172 hasEllipsis = true;
173 }
174 return t;
175 }
176
177 @Override
178 public void addCellEditorListener(CellEditorListener l) {
179 cellEditorSupport.addCellEditorListener(l);
180 }
181
182 @Override
183 public void cancelCellEditing() {
184 cellEditorSupport.fireEditingCanceled();
185 }
186
187 @Override
188 public Object getCellEditorValue() {
189 return value;
190 }
191
192 @Override
193 public boolean isCellEditable(EventObject anEvent) {
194 return true;
195 }
196
197 @Override
198 public void removeCellEditorListener(CellEditorListener l) {
199 cellEditorSupport.removeCellEditorListener(l);
200 }
201
202 @Override
203 public boolean shouldSelectCell(EventObject anEvent) {
204 return true;
205 }
206
207 @Override
208 public boolean stopCellEditing() {
209 if (tfFilename.getText() == null || tfFilename.getText().trim().isEmpty()) {
210 value = null;
211 } else {
212 value = new File(tfFilename.getText());
213 }
214 cellEditorSupport.fireEditingStopped();
215 return true;
216 }
217
218 private class LaunchFileChooserAction extends AbstractAction {
219 public LaunchFileChooserAction() {
220 putValue(NAME, "...");
221 putValue(SHORT_DESCRIPTION, tr("Launch a file chooser to select a file"));
222 }
223
224 @Override
225 public void actionPerformed(ActionEvent e) {
226 File f = SaveActionBase.createAndOpenSaveFileChooser(tr("Select filename"), "osm");
227 if (f != null) {
228 tfFilename.setText(f.toString());
229 stopCellEditing();
230 }
231 }
232 }
233}
Note: See TracBrowser for help on using the repository browser.