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