001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io.remotecontrol;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.Color;
007    import java.awt.Component;
008    import java.awt.Dimension;
009    import java.awt.Font;
010    import java.awt.GridBagLayout;
011    import java.awt.event.ActionEvent;
012    import java.util.Collection;
013    
014    import javax.swing.JPanel;
015    import javax.swing.JTable;
016    import javax.swing.table.DefaultTableModel;
017    import javax.swing.table.TableCellRenderer;
018    import javax.swing.table.TableModel;
019    
020    import org.openstreetmap.josm.Main;
021    import org.openstreetmap.josm.command.ChangePropertyCommand;
022    import org.openstreetmap.josm.data.SelectionChangedListener;
023    import org.openstreetmap.josm.data.osm.DataSet;
024    import org.openstreetmap.josm.data.osm.OsmPrimitive;
025    import org.openstreetmap.josm.gui.ExtendedDialog;
026    import org.openstreetmap.josm.tools.GBC;
027    
028    /**
029     * 
030     * @author master
031     * 
032     * Dialog to add tags as part of the remotecontrol
033     * Existing Keys get grey color and unchecked selectboxes so they will not overwrite the old Key-Value-Pairs by default.
034     * You can choose the tags you want to add by selectboxes. You can edit the tags before you apply them.
035     *
036     */
037    public class AddTagsDialog extends ExtendedDialog implements SelectionChangedListener {
038    
039    
040        private final JTable propertyTable;
041        private Collection<? extends OsmPrimitive> sel;
042        boolean[] existing;
043    
044        public AddTagsDialog(String[][] tags) {
045            super(Main.parent, tr("Add tags to selected objects"), new String[] { tr("Add tags"), tr("Cancel")},
046                    false,
047                    true);
048    
049            DataSet.addSelectionListener(this);
050    
051    
052            DefaultTableModel tm = new DefaultTableModel(new String[] {tr("Assume"), tr("Key"), tr("Value")}, tags.length) {
053                @Override
054                public Class getColumnClass(int c) {
055                    return getValueAt(0, c).getClass();
056                }
057    
058            };
059    
060            sel = Main.main.getCurrentDataSet().getSelected();
061            existing = new boolean[tags.length];
062    
063            for (int i = 0; i<tags.length; i++) {
064                existing[i] = false;
065                String key = tags[i][0];
066                Boolean b = Boolean.TRUE;
067                for (OsmPrimitive osm : sel) {
068                    if (osm.keySet().contains(key)) {
069                        b = Boolean.FALSE;
070                        existing[i]=true;
071                        break;
072                    }
073                }
074                tm.setValueAt(b, i, 0);
075                tm.setValueAt(tags[i][0], i, 1);
076                tm.setValueAt(tags[i][1], i, 2);
077            }
078    
079            propertyTable = new JTable(tm) {
080    
081                private static final long serialVersionUID = 1L;
082    
083                @Override
084                public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
085                    Component c = super.prepareRenderer(renderer, row, column);
086                    if (existing[row]) {
087                        c.setFont(c.getFont().deriveFont(Font.ITALIC));
088                        c.setForeground(new Color(100, 100, 100));
089                    } else {
090                        c.setFont(c.getFont().deriveFont(Font.PLAIN));
091                        c.setForeground(new Color(0, 0, 0));
092                    }
093                    return c;
094                }
095            };
096    
097            // a checkbox has a size of 15 px
098            propertyTable.getColumnModel().getColumn(0).setMaxWidth(15);
099            // get edit results if the table looses the focus, for example if a user clicks "add tags"
100            propertyTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
101    
102            // set the content of this AddTagsDialog consisting of the tableHeader and the table itself.
103            JPanel tablePanel = new JPanel();
104            tablePanel.setLayout(new GridBagLayout());
105            tablePanel.add(propertyTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
106            tablePanel.add(propertyTable, GBC.eol().fill(GBC.BOTH));
107            setContent(tablePanel);
108    
109            // set the default Dimensions and show the dialog
110            setPreferredSize(new Dimension(400,tablePanel.getPreferredSize().height+100));
111            showDialog();
112        }
113    
114        /**
115         * This method looks for existing tags in the current selection and sets the corresponding boolean in the boolean array existing[]
116         */
117        private void findExistingTags() {
118            TableModel tm = propertyTable.getModel();
119            for (int i=0; i<tm.getRowCount(); i++) {
120                String key = (String)tm.getValueAt(i, 1);
121                existing[i] = false;
122                for (OsmPrimitive osm : sel) {
123                    if (osm.keySet().contains(key)) {
124                        existing[i] = true;
125                        break;
126                    }
127                }
128            }
129            propertyTable.repaint();
130        }
131    
132        /**
133         * If you click the "Add tags" button build a ChangePropertyCommand for every key that has a checked checkbox to apply the key value pair to all selected osm objects.
134         * You get a entry for every key in the command queue.
135         */
136        @Override
137        protected void buttonAction(int buttonIndex, ActionEvent evt) {
138            if (buttonIndex == 0) {
139                TableModel tm = propertyTable.getModel();
140                for (int i=0; i<tm.getRowCount(); i++) {
141                    if ((Boolean)tm.getValueAt(i, 0)) {
142                        Main.main.undoRedo.add(new ChangePropertyCommand(sel, (String)tm.getValueAt(i, 1), (String)tm.getValueAt(i, 2)));
143                    }
144                }
145            }
146            setVisible(false);
147        }
148    
149        @Override
150        public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
151            sel = newSelection;
152            findExistingTags();
153        }
154    
155    }