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