001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.tagging;
003
004 import java.awt.BorderLayout;
005 import java.awt.GridBagConstraints;
006 import java.awt.GridBagLayout;
007 import java.awt.Insets;
008 import java.util.EnumSet;
009
010 import javax.swing.BoxLayout;
011 import javax.swing.JButton;
012 import javax.swing.JPanel;
013 import javax.swing.JScrollPane;
014 import javax.swing.event.TableModelEvent;
015 import javax.swing.event.TableModelListener;
016
017 import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel;
018 import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel.PresetHandler;
019 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
020 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
021 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
022 import org.openstreetmap.josm.tools.CheckParameterUtil;
023
024 /**
025 * TagEditorPanel is a {@link JPanel} which can be embedded as UI component in
026 * UIs. It provides a spreadsheet like tabular control for editing tag names
027 * and tag values. Two action buttons are placed on the left, one for adding
028 * a new tag and one for deleting the currently selected tags.
029 *
030 */
031 public class TagEditorPanel extends JPanel {
032 /** the tag editor model */
033 private TagEditorModel model;
034 /** the tag table */
035 private TagTable tagTable;
036
037 private PresetListPanel presetListPanel;
038 private final PresetHandler presetHandler;
039
040 private AutoCompletionManager autocomplete;
041 private AutoCompletionList acList;
042
043 /**
044 * builds the panel with the table for editing tags
045 *
046 * @return the panel
047 */
048 protected JPanel buildTagTableEditorPanel() {
049 JPanel pnl = new JPanel();
050 tagTable = new TagTable(model);
051 pnl.setLayout(new BorderLayout());
052 pnl.add(new JScrollPane(tagTable), BorderLayout.CENTER);
053 if (presetHandler != null) {
054 presetListPanel = new PresetListPanel();
055 pnl.add(presetListPanel, BorderLayout.NORTH);
056 }
057 return pnl;
058 }
059
060 /**
061 * builds the panel with the button row
062 *
063 * @return the panel
064 */
065 protected JPanel buildButtonsPanel() {
066 JPanel pnl = new JPanel();
067 pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
068
069 // add action
070 //
071 JButton btn;
072 pnl.add(btn = new JButton(tagTable.getAddAction()));
073 btn.setMargin(new Insets(0,0,0,0));
074 tagTable.addComponentNotStoppingCellEditing(btn);
075
076 // delete action
077 pnl.add(btn = new JButton(tagTable.getDeleteAction()));
078 btn.setMargin(new Insets(0,0,0,0));
079 tagTable.addComponentNotStoppingCellEditing(btn);
080 return pnl;
081 }
082
083 /**
084 * builds the GUI
085 */
086 protected void build() {
087 setLayout(new GridBagLayout());
088 JPanel tablePanel = buildTagTableEditorPanel();
089 JPanel buttonPanel = buildButtonsPanel();
090
091 GridBagConstraints gc = new GridBagConstraints();
092
093 // -- buttons panel
094 //
095 gc.fill = GridBagConstraints.VERTICAL;
096 gc.weightx = 0.0;
097 gc.weighty = 1.0;
098 gc.anchor = GridBagConstraints.NORTHWEST;
099 add(buttonPanel,gc);
100
101 // -- the panel with the editor table
102 //
103 gc.gridx = 1;
104 gc.fill = GridBagConstraints.BOTH;
105 gc.weightx = 1.0;
106 gc.weighty = 1.0;
107 gc.anchor = GridBagConstraints.CENTER;
108 add(tablePanel,gc);
109
110 if (presetHandler != null) {
111 model.addTableModelListener(new TableModelListener() {
112 @Override
113 public void tableChanged(TableModelEvent e) {
114 updatePresets();
115 }
116 });
117 }
118 }
119
120 /**
121 * Creates a new tag editor panel. The editor model is created
122 * internally and can be retrieved with {@link #getModel()}.
123 */
124 public TagEditorPanel(PresetHandler presetHandler) {
125 this(null, presetHandler);
126 }
127
128 /**
129 * Creates a new tag editor panel with a supplied model. If
130 * {@code model} is null, a new model is created.
131 *
132 * @param model the tag editor model
133 */
134 public TagEditorPanel(TagEditorModel model, PresetHandler presetHandler) {
135 this.model = model;
136 this.presetHandler = presetHandler;
137 if (this.model == null) {
138 this.model = new TagEditorModel();
139 }
140 build();
141 }
142
143 /**
144 * Replies the tag editor model used by this panel.
145 *
146 * @return the tag editor model used by this panel
147 */
148 public TagEditorModel getModel() {
149 return model;
150 }
151
152 /**
153 * Initializes the auto completion infrastructure used in this
154 * tag editor panel. {@code layer} is the data layer from whose data set
155 * tag values are proposed as auto completion items.
156 *
157 * @param layer the data layer. Must not be null.
158 * @throws IllegalArgumentException thrown if {@code layer} is null
159 */
160 public void initAutoCompletion(OsmDataLayer layer) throws IllegalArgumentException{
161 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
162
163 autocomplete = layer.data.getAutoCompletionManager();
164 acList = new AutoCompletionList();
165
166 TagCellEditor editor = ((TagCellEditor) tagTable.getColumnModel().getColumn(0).getCellEditor());
167 editor.setAutoCompletionManager(autocomplete);
168 editor.setAutoCompletionList(acList);
169 editor = ((TagCellEditor) tagTable.getColumnModel().getColumn(1).getCellEditor());
170 editor.setAutoCompletionManager(autocomplete);
171 editor.setAutoCompletionList(acList);
172 }
173
174 @Override
175 public void setEnabled(boolean enabled) {
176 tagTable.setEnabled(enabled);
177 super.setEnabled(enabled);
178 }
179
180 private void updatePresets() {
181 presetListPanel.updatePresets(
182 EnumSet.of(TaggingPreset.PresetType.RELATION),
183 model.getTags(), presetHandler);
184 validate();
185 }
186 }