Changeset 591 in josm for trunk/src/org


Ignore:
Timestamp:
2008-03-28T00:23:05+01:00 (17 years ago)
Author:
framm
Message:
  • Tagging presets now take existing tags into account and will not change them unless specifically asked for. This introduces a new "<different>" value for some fields that is used if you have more than 1 object selected and they do not have the same tag setting. If you don't touch the "<different>" then each object will keep its setting. Checkboxes now have three states (yes,no,unset) and if multiple objects are selected which do not have the same value in a checkbox field, there are even four states (yes,no,unset,different). Maybe they should be replaced by a dropdown. Closes #535, #517.
Location:
trunk/src/org/openstreetmap/josm/gui
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java

    r398 r591  
    1616import java.net.URL;
    1717import java.util.Collection;
     18import java.util.HashSet;
     19import java.util.LinkedHashMap;
    1820import java.util.LinkedList;
    1921import java.util.List;
     22import java.util.Set;
    2023import java.util.StringTokenizer;
    2124
     
    2326import javax.swing.Action;
    2427import javax.swing.ImageIcon;
    25 import javax.swing.JCheckBox;
    2628import javax.swing.JComboBox;
     29import javax.swing.JComponent;
    2730import javax.swing.JLabel;
    2831import javax.swing.JOptionPane;
     
    3538import org.openstreetmap.josm.command.SequenceCommand;
    3639import org.openstreetmap.josm.data.osm.OsmPrimitive;
     40import org.openstreetmap.josm.gui.QuadStateCheckBox;
    3741import org.openstreetmap.josm.tools.GBC;
    3842import org.openstreetmap.josm.tools.ImageProvider;
     
    5256        public static abstract class Item {
    5357                public boolean focus = false;
    54                 abstract void addToPanel(JPanel p);
     58                abstract void addToPanel(JPanel p, Collection<OsmPrimitive> sel);
    5559                abstract void addCommands(Collection<OsmPrimitive> sel, List<Command> cmds);
    5660                boolean requestFocusInWindow() {return false;}
    5761        }
    58 
     62       
     63        public static class Usage {
     64                Set<String> values;
     65        }
     66       
     67        public static final String DIFFERENT = tr("<different>");
     68       
     69        static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
     70                Usage returnValue = new Usage();
     71                returnValue.values = new HashSet<String>();
     72                for (OsmPrimitive s : sel) {
     73                        returnValue.values.add(s.get(key));
     74                }
     75                return returnValue;
     76        }
     77
     78        static Usage determineBooleanUsage(Collection<OsmPrimitive> sel, String key) {
     79
     80                Usage returnValue = new Usage();
     81                returnValue.values = new HashSet<String>();
     82                for (OsmPrimitive s : sel) {
     83                        String v = s.get(key);
     84                        if ("true".equalsIgnoreCase(v)) v = "true";
     85                        else if ("yes".equalsIgnoreCase(v)) v = "true";
     86                        else if ("1".equals(v)) v = "true";
     87                        else if ("false".equalsIgnoreCase(v)) v = "false";
     88                        else if ("no".equalsIgnoreCase(v)) v = "false";
     89                        else if ("0".equals(v)) v = "false";                   
     90                        returnValue.values.add(v);
     91                }
     92                return returnValue;
     93        }
     94       
    5995        public static class Text extends Item {
    6096                public String key;
    6197                public String text;
    6298                public String default_;
     99                public String originalValue;
    63100                public boolean delete_if_empty = false;
    64101
    65                 private JTextField value = new JTextField();
    66 
    67                 @Override public void addToPanel(JPanel p) {
    68                         value.setText(default_ == null ? "" : default_);
     102                private JComponent value;
     103               
     104                @Override public void addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
     105                       
     106                        // find out if our key is already used in the selection.
     107                        Usage usage = determineTextUsage(sel, key);
     108                       
     109                        if (usage.values.size() == 1) {
     110                                // all objects use the same value
     111                                value = new JTextField();
     112                                for (String s : usage.values) ((JTextField) value).setText(s);
     113                                originalValue = ((JTextField)value).getText();
     114                        } else {
     115                                // the objects have different values
     116                                value = new JComboBox(usage.values.toArray());
     117                                ((JComboBox)value).setEditable(true);
     118                    ((JComboBox)value).getEditor().setItem(DIFFERENT);
     119                    originalValue = DIFFERENT;
     120                        }
    69121                        p.add(new JLabel(text), GBC.std().insets(0,0,10,0));
    70122                        p.add(value, GBC.eol().fill(GBC.HORIZONTAL));
    71123                }
     124               
    72125                @Override public void addCommands(Collection<OsmPrimitive> sel, List<Command> cmds) {
    73                         String v = value.getText();
     126                       
     127                        // return if unchanged
     128                        String v = (value instanceof JComboBox) ?
     129                                ((JComboBox)value).getEditor().getItem().toString() :
     130                                ((JTextField)value).getText();
     131
     132                        if (v.equals(originalValue) || (originalValue == null && v.length() == 0)) return;
     133
    74134                        if (delete_if_empty && v.length() == 0)
    75135                                v = null;
     
    80140
    81141        public static class Check extends Item {
     142
    82143                public String key;
    83144                public String text;
    84                 public boolean default_ = false;
    85 
    86                 private JCheckBox check = new JCheckBox();
    87 
    88                 @Override public void addToPanel(JPanel p) {
    89                         check.setSelected(default_);
    90                         check.setText(text);
     145                public boolean default_ = false; // not used!
     146
     147                private QuadStateCheckBox check;
     148                private QuadStateCheckBox.State initialState;
     149               
     150                @Override public void addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
     151                       
     152                        // find out if our key is already used in the selection.
     153                        Usage usage = determineBooleanUsage(sel, key);
     154
     155                        String oneValue = null;
     156                        for (String s : usage.values) oneValue = s;
     157                        if (usage.values.size() < 2 && (oneValue == null || "true".equals(oneValue) || "false".equals(oneValue))) {
     158                                // all selected objects share the same value which is either true or false or unset,
     159                                // we can display a standard check box.
     160                                initialState = "true".equals(oneValue) ?
     161                                                        QuadStateCheckBox.State.SELECTED :
     162                                                        "false".equals(oneValue) ?
     163                                                        QuadStateCheckBox.State.NOT_SELECTED :
     164                                                        QuadStateCheckBox.State.UNSET;
     165                                check = new QuadStateCheckBox(text, initialState,
     166                                                new QuadStateCheckBox.State[] {
     167                                                QuadStateCheckBox.State.NOT_SELECTED,
     168                                                QuadStateCheckBox.State.SELECTED,
     169                                                QuadStateCheckBox.State.UNSET });
     170                        } else {
     171                                // the objects have different values, or one or more objects have something
     172                                // else than true/false. we display a quad-state check box
     173                                // in "partial" state.
     174                                initialState = QuadStateCheckBox.State.PARTIAL;
     175                                check = new QuadStateCheckBox(text, QuadStateCheckBox.State.PARTIAL,
     176                                                new QuadStateCheckBox.State[] {
     177                                                QuadStateCheckBox.State.NOT_SELECTED,
     178                                                QuadStateCheckBox.State.PARTIAL,
     179                                                QuadStateCheckBox.State.SELECTED,
     180                                                QuadStateCheckBox.State.UNSET });
     181                        }
    91182                        p.add(check, GBC.eol().fill(GBC.HORIZONTAL));
    92183                }
     184               
    93185                @Override public void addCommands(Collection<OsmPrimitive> sel, List<Command> cmds) {
    94                         cmds.add(new ChangePropertyCommand(sel, key, check.isSelected() ? "true" : null));
     186                        // if the user hasn't changed anything, don't create a command.
     187                        if (check.getState() == initialState) return;
     188                       
     189                        // otherwise change things according to the selected value.
     190                        cmds.add(new ChangePropertyCommand(sel, key,
     191                                        check.getState() == QuadStateCheckBox.State.SELECTED ? "true" :
     192                                        check.getState() == QuadStateCheckBox.State.NOT_SELECTED ? "false" :
     193                                        null));
    95194                }
    96195                @Override boolean requestFocusInWindow() {return check.requestFocusInWindow();}
     
    98197
    99198        public static class Combo extends Item {
     199               
    100200                public String key;
    101201                public String text;
     
    107207
    108208                private JComboBox combo;
    109 
    110                 @Override public void addToPanel(JPanel p) {
    111                         combo = new JComboBox((display_values != null ? display_values : values).split(","));
     209                private LinkedHashMap<String,String> lhm;
     210                private Usage usage;
     211                private String originalValue;
     212               
     213                @Override public void addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
     214                       
     215                        // find out if our key is already used in the selection.
     216                        usage = determineTextUsage(sel, key);
     217                       
     218                        String[] value_array = values.split(",");
     219                        String[] display_array = (display_values == null) ? value_array : display_values.split(",");
     220
     221                        lhm = new LinkedHashMap<String,String>();
     222                        if (usage.values.size() > 1) {
     223                                lhm.put(DIFFERENT, DIFFERENT);
     224                        }
     225                        for (int i=0; i<value_array.length; i++) {
     226                                lhm.put(value_array[i], display_array[i]);
     227                        }
     228                        for (String s : usage.values) {
     229                                if (!lhm.containsKey(s)) lhm.put(s, s);
     230                        }
     231                        if ((default_ != null) && (!lhm.containsKey(default_))) lhm.put(default_, default_);
     232                       
     233                        combo = new JComboBox(lhm.values().toArray());
    112234                        combo.setEditable(editable);
    113                         combo.setSelectedItem(default_);
     235                        if (usage.values.size() == 1) {
     236                                for (String s : usage.values) { combo.setSelectedItem(lhm.get(s)); originalValue=s; }
     237                        } else {
     238                                combo.setSelectedItem(DIFFERENT); originalValue=DIFFERENT;
     239                        }
    114240                        p.add(new JLabel(text), GBC.std().insets(0,0,10,0));
    115241                        p.add(combo, GBC.eol().fill(GBC.HORIZONTAL));
    116242                }
    117243                @Override public void addCommands(Collection<OsmPrimitive> sel, List<Command> cmds) {
    118                         String v = combo.getSelectedIndex() == -1 ? null : values.split(",")[combo.getSelectedIndex()];
    119                         String str = combo.isEditable()?combo.getEditor().getItem().toString() : v;
     244                        Object display = combo.getSelectedItem();
     245                        String value = null;
     246                        if (display != null)
     247                                for (String key : lhm.keySet()) {
     248                                        String k = lhm.get(key);
     249                                        if (k != null && k.equals(display)) value=key;
     250                                }
     251                        String str = combo.isEditable() ? combo.getEditor().getItem().toString() : value;
     252                       
     253                        // no change if same as before
     254                        if (str.equals(originalValue) || (originalValue == null && str.length() == 0)) return;
     255                       
    120256                        if (delete_if_empty && str != null && str.length() == 0)
    121257                                str = null;
     
    128264                public String text;
    129265
    130                 @Override public void addToPanel(JPanel p) {
     266                @Override public void addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
    131267                        p.add(new JLabel(text), GBC.eol());
    132268                }
     
    138274                public String value;
    139275
    140                 @Override public void addToPanel(JPanel p) {}
     276                @Override public void addToPanel(JPanel p, Collection<OsmPrimitive> sel) { }
    141277                @Override public void addCommands(Collection<OsmPrimitive> sel, List<Command> cmds) {
    142278                        cmds.add(new ChangePropertyCommand(sel, key, value != null && !value.equals("") ? value : null));
     
    181317
    182318        /**
    183          * Called from the XML parser to set the types, this preset affects
     319         * Called from the XML parser to set the types this preset affects
    184320         */
    185321        public void setType(String types) throws SAXException {
     
    262398        }
    263399
    264         public JPanel createPanel() {
     400        public JPanel createPanel(Collection<OsmPrimitive> selected) {
    265401                if (data == null)
    266402                        return null;
    267403                JPanel p = new JPanel(new GridBagLayout());
     404
    268405                for (Item i : data)
    269                         i.addToPanel(p);
     406                        i.addToPanel(p, selected);
    270407                return p;
    271408        }
     
    273410        public void actionPerformed(ActionEvent e) {
    274411                Collection<OsmPrimitive> sel = Main.ds.getSelected();
    275                 JPanel p = createPanel();
     412                JPanel p = createPanel(sel);
    276413                if (p == null)
    277414                        return;
Note: See TracChangeset for help on using the changeset viewer.