source: josm/trunk/src/org/openstreetmap/josm/gui/tagging/TagEditorPanel.java

Last change on this file was 18173, checked in by Don-vip, 3 years ago

fix #20690 - fix #21240 - Refactoring of UploadDialog, HistoryComboBox and AutoCompletingComboBox (patch by marcello)

  • Property svn:eol-style set to native
File size: 7.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.tagging;
3
4import java.awt.BorderLayout;
5import java.awt.Component;
6import java.awt.GridBagConstraints;
7import java.awt.GridBagLayout;
8import java.awt.Insets;
9import java.awt.event.FocusAdapter;
10import java.awt.event.FocusEvent;
11import java.util.Collections;
12
13import javax.swing.AbstractAction;
14import javax.swing.BoxLayout;
15import javax.swing.JButton;
16import javax.swing.JComponent;
17import javax.swing.JPanel;
18import javax.swing.JScrollPane;
19
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.gui.dialogs.properties.HelpAction;
22import org.openstreetmap.josm.gui.dialogs.properties.HelpTagAction;
23import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel;
24import org.openstreetmap.josm.gui.layer.OsmDataLayer;
25import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
26import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
27import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetHandler;
28import org.openstreetmap.josm.spi.preferences.Config;
29import org.openstreetmap.josm.tools.CheckParameterUtil;
30
31/**
32 * TagEditorPanel is a {@link JPanel} which can be embedded as UI component in
33 * UIs. It provides a spreadsheet like tabular control for editing tag names
34 * and tag values. Two action buttons are placed on the left, one for adding
35 * a new tag and one for deleting the currently selected tags.
36 * @since 2040
37 */
38public class TagEditorPanel extends JPanel {
39 /** the tag editor model */
40 private TagEditorModel model;
41 /** the tag table */
42 private final TagTable tagTable;
43
44 private PresetListPanel presetListPanel;
45 private final transient TaggingPresetHandler presetHandler;
46
47 /**
48 * builds the panel with the table for editing tags
49 *
50 * @return the panel
51 */
52 protected JPanel buildTagTableEditorPanel() {
53 JPanel pnl = new JPanel(new BorderLayout());
54 pnl.add(new JScrollPane(tagTable), BorderLayout.CENTER);
55 if (presetHandler != null) {
56 presetListPanel = new PresetListPanel();
57 if (Config.getPref().getBoolean("relation.editor.presets.visible", true)) {
58 pnl.add(presetListPanel, BorderLayout.NORTH);
59 }
60 }
61 return pnl;
62 }
63
64 /**
65 * Sets the next component to request focus after navigation (with tab or enter).
66 * @param nextFocusComponent next component to request focus after navigation (with tab or enter)
67 * @see TagTable#setNextFocusComponent
68 */
69 public void setNextFocusComponent(Component nextFocusComponent) {
70 tagTable.setNextFocusComponent(nextFocusComponent);
71 }
72
73 /**
74 * builds the panel with the button row
75 *
76 * @return the panel
77 */
78 protected JPanel buildButtonsPanel() {
79 JPanel pnl = new JPanel();
80 pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
81
82 buildButton(pnl, tagTable.getAddAction());
83 buildButton(pnl, tagTable.getDeleteAction());
84 buildButton(pnl, tagTable.getPasteAction());
85
86 return pnl;
87 }
88
89 private void buildButton(JPanel pnl, AbstractAction action) {
90 JButton btn = new JButton(action);
91 pnl.add(btn);
92 btn.setMargin(new Insets(0, 0, 0, 0));
93 tagTable.addComponentNotStoppingCellEditing(btn);
94 }
95
96 /**
97 * Returns the paste action.
98 * @return the paste action
99 */
100 public AbstractAction getPasteAction() {
101 return tagTable.getPasteAction();
102 }
103
104 /**
105 * builds the GUI
106 */
107 protected final void build() {
108 setLayout(new GridBagLayout());
109 JPanel tablePanel = buildTagTableEditorPanel();
110 JPanel buttonPanel = buildButtonsPanel();
111
112 GridBagConstraints gc = new GridBagConstraints();
113
114 // -- buttons panel
115 //
116 gc.fill = GridBagConstraints.VERTICAL;
117 gc.weightx = 0.0;
118 gc.weighty = 1.0;
119 gc.anchor = GridBagConstraints.NORTHWEST;
120 add(buttonPanel, gc);
121
122 // -- the panel with the editor table
123 //
124 gc.gridx = 1;
125 gc.fill = GridBagConstraints.BOTH;
126 gc.weightx = 1.0;
127 gc.weighty = 1.0;
128 gc.anchor = GridBagConstraints.CENTER;
129 add(tablePanel, gc);
130
131 if (presetHandler != null) {
132 model.addTableModelListener(e -> updatePresets());
133 }
134
135 addFocusListener(new FocusAdapter() {
136 @Override
137 public void focusGained(FocusEvent e) {
138 tagTable.requestFocusInCell(0, 0);
139 }
140 });
141 }
142
143 /**
144 * Creates a new tag editor panel. The editor model is created
145 * internally and can be retrieved with {@link #getModel()}.
146 * @param primitive primitive to consider
147 * @param presetHandler tagging preset handler
148 */
149 public TagEditorPanel(OsmPrimitive primitive, TaggingPresetHandler presetHandler) {
150 this(new TagEditorModel().forPrimitive(primitive), presetHandler, 0);
151 }
152
153 /**
154 * Creates a new tag editor panel with a supplied model. If {@code model} is null, a new model is created.
155 *
156 * @param model the tag editor model
157 * @param presetHandler tagging preset handler
158 * @param maxCharacters maximum number of characters allowed, 0 for unlimited
159 */
160 public TagEditorPanel(TagEditorModel model, TaggingPresetHandler presetHandler, final int maxCharacters) {
161 this.model = model;
162 this.presetHandler = presetHandler;
163 if (this.model == null) {
164 this.model = new TagEditorModel();
165 }
166 this.tagTable = new TagTable(this.model, maxCharacters);
167
168 setupKeyboardShortcuts();
169 build();
170 }
171
172 private void setupKeyboardShortcuts() {
173 // F1 button = custom help action
174 final HelpAction helpTagAction = new HelpTagAction(tagTable,
175 viewRow -> this.model.get(tagTable.convertRowIndexToModel(viewRow)).getName(),
176 viewRow -> Collections.singletonMap(this.model.get(tagTable.convertRowIndexToModel(viewRow)).getValue(), 1));
177 getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(HelpAction.getKeyStroke(), "onHelp");
178 getActionMap().put("onHelp", helpTagAction);
179 }
180
181 /**
182 * Replies the tag editor model used by this panel.
183 *
184 * @return the tag editor model used by this panel
185 */
186 public TagEditorModel getModel() {
187 return model;
188 }
189
190 /**
191 * Initializes the auto completion infrastructure used in this
192 * tag editor panel. {@code layer} is the data layer from whose data set
193 * tag values are proposed as auto completion items.
194 *
195 * @param layer the data layer. Must not be null.
196 * @throws IllegalArgumentException if {@code layer} is null
197 */
198 public void initAutoCompletion(OsmDataLayer layer) {
199 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
200
201 AutoCompletionManager autocomplete = AutoCompletionManager.of(layer.data);
202 AutoCompletionList acList = new AutoCompletionList();
203
204 TagCellEditor editor = (TagCellEditor) tagTable.getColumnModel().getColumn(0).getCellEditor();
205 editor.setAutoCompletionManager(autocomplete);
206 editor.setAutoCompletionList(acList);
207 editor = (TagCellEditor) tagTable.getColumnModel().getColumn(1).getCellEditor();
208 editor.setAutoCompletionManager(autocomplete);
209 editor.setAutoCompletionList(acList);
210 }
211
212 @Override
213 public void setEnabled(boolean enabled) {
214 tagTable.setEnabled(enabled);
215 super.setEnabled(enabled);
216 }
217
218 private void updatePresets() {
219 presetListPanel.updatePresets(
220 model.getTaggingPresetTypes(),
221 model.getTags(), presetHandler);
222 validate();
223 }
224
225 /**
226 * Save all outstanding edits to the model.
227 * @see org.openstreetmap.josm.gui.io.UploadDialog#saveEdits
228 * @since 18173
229 */
230 public void saveEdits() {
231 tagTable.endCellEditing();
232 }
233}
Note: See TracBrowser for help on using the repository browser.