Ticket #7552: 7552_delta.patch

File 7552_delta.patch, 23.3 KB (added by simon04, 12 years ago)
  • data/defaultpresets.xml

    diff --git a/data/defaultpresets.xml b/data/defaultpresets.xml
    index d8a5172..ff22e70 100755
    a b combo: combo box, with multiple choices and possible to enter free form text  
    3838  values: comma separated list of values
    3939  display_values: comma separated list of values to be displayed instead of the
    4040                  database values, order and number must be equal to values
    41   short_description: comma separated list of texts to be displayed below each
    42                     display_value. (Only if it is not possible to describe
    43                     the entry in 2-3 words.) Instead of comma separeted list, you can
    44                     also write it in the following form:
    45                         <short_description>first description</short_description>
    46                                 ...
    47                         <short_description>last description</short_description>
     41  short_descriptions: comma separated list of texts to be displayed below each
     42                      display_value. (Only if it is not possible to describe
     43                      the entry in 2-3 words.) Instead of comma separeted list
     44  instead using values, display_values and short_descriptions, the following form is also supported:
     45    <list_item value="" display_value="' short_description="" icon=""/>
    4846  default: default string to display
    4947  delete_if_empty: true/false
    5048  use_last_as_default: true/false/force
    multiselect: list of values from which zero or more can be selected  
    5452  text: fixed label to display
    5553  delimiter: character that separates values (default: semicolon) - this
    5654             will also be used to separate selected values in the tag.
    57   values: delimiter-separated list of values (delimiter can be escaped with backslash)
    5855  rows: specify the number of rows to display (default -1)
     56  values: delimiter-separated list of values (delimiter can be escaped with backslash)
    5957  display_values: delimiter-separated list of values to be displayed instead of the
    6058                  database values, order and number must be equal to values
    61   short_description: delimiter-separated list of texts to be displayed below each
    62                     display_value. (Only if it is not possible to describe
    63                     the entry in 2-3 words.) Instead of a separated list, you can
    64                     also write it in the following form:
    65                         <short_description>first description</short_description>
    66                                 ...
    67                         <short_description>last description</short_description>
     59  short_descriptions: delimiter-separated list of texts to be displayed below each
     60                     display_value. (Only if it is not possible to describe
     61                     the entry in 2-3 words.) Instead of a separated list
     62  instead using values, display_values and short_descriptions, the following form is also supported:
     63    <list_item value="" display_value="' short_description="" icon=""/>
    6864  default: default string to display
    6965  delete_if_empty: true/false
    7066  use_last_as_default: true/false/force
    are supplied, then "values" will be treated as "display_values" and translated i  
    690686            <key key="highway" value="path" />
    691687            <optional>
    692688                <text key="name" text="Name" default="" delete_if_empty="true" />
    693                 <combo key="sac_scale" text="SAC Scale" values="hiking,mountain_hiking,demanding_mountain_hiking,alpine_hiking,demanding_alpine_hiking,difficult_alpine_hiking" default="" delete_if_empty="true" display_values="T1 - hiking trail,T2 - mountain hiking trail,T3 - difficult\, exposed hiking trail,T4 - difficult\, exposed\, steep alpine trail,T5 - difficult alpine trail with climbing,T6 - hazardous alpine trail with climbing">
    694                     <short_description>Trail well cleared. Area flat or slightly sloped, no fall hazard</short_description>
    695                     <short_description>Trail with continuous line and balanced ascent. Terrain partially steep, fall hazard possible</short_description>
    696                     <short_description>exposed sites may be secured with ropes or chains, possible need to use hands for balance. Partly exposed sites with fall hazard, scree, pathless jagged rocks</short_description>
    697                     <short_description>sometimes need for hand use to get ahead. Terrain quite exposed, precarious grassy acclivities, jagged rocks, facile snow-free glaciers.</short_description>
    698                     <short_description>single plainly climbing up to second grade. Exposed, demanding terrain, jagged rocks, few dangerous glacier and snow</short_description>
    699                     <short_description>climbing up to second grade. Often very exposed, precarious jagged rocks, glacier with danger to slip and fall</short_description>
     689                <combo key="sac_scale" text="SAC Scale">
     690                    <list_entry value="hiking" display_value="T1 - hiking trail" short_description="Trail well cleared. Area flat or slightly sloped, no fall hazard" />
     691                    <list_entry value="mountain_hiking" display_value="T2 - mountain hiking trail" short_description="Trail with continuous line and balanced ascent. Terrain partially steep, fall hazard possible" />
     692                    <list_entry value="demanding_mountain_hiking" display_value="T3 - difficult, exposed hiking trail" short_description="exposed sites may be secured with ropes or chains, possible need to use hands for balance. Partly exposed sites with fall hazard, scree, pathless jagged rocks" />
     693                    <list_entry value="alpine_hiking" display_value="T4 - difficult, exposed, steep alpine trail" short_description="sometimes need for hand use to get ahead. Terrain quite exposed, precarious grassy acclivities, jagged rocks, facile snow-free glaciers" />
     694                    <list_entry value="demanding_alpine_hiking" display_value="T5 - difficult alpine trail with climbing" short_description="single plainly climbing up to second grade. Exposed, demanding terrain, jagged rocks, few dangerous glacier and snow" />
     695                    <list_entry value="difficult_alpine_hiking" display_value="T6 - hazardous alpine trail with climbing" short_description="climbing up to second grade. Often very exposed, precarious jagged rocks, glacier with danger to slip and fall" />
    700696                </combo>
    701697                <combo key="mtb:scale" text="MTB Scale" values="0,1,2,3,4,5" default="" delete_if_empty="true" />
    702698                <combo key="surface" text="Surface" values="paved,unpaved,asphalt,concrete,metal,wood,paving_stones,cobblestone,gravel,pebblestone,compacted,grass_paver,grass,sand,ground" default="" delete_if_empty="true" />
  • data/tagging-preset.xsd

    diff --git a/data/tagging-preset.xsd b/data/tagging-preset.xsd
    index 64a0d4e..f4d17b8 100644
    a b  
    125125                <anyAttribute processContents="skip" />
    126126        </complexType>
    127127
     128        <complexType name="list_entry">
     129                <attribute name="value" type="string" use="required" />
     130                <attribute name="display_value" type="string" />
     131                <attribute name="short_description" type="string" />
     132                <attribute name="icon" type="string" />
     133        </complexType>
     134
    128135        <complexType name="combo">
    129136                <sequence>
    130                         <element name="short_description" type="string" minOccurs="0"
    131                                 maxOccurs="unbounded" />
     137                        <element name="list_entry" type="tns:list_entry" />
    132138                </sequence>
    133139                <attribute name="key" type="string" use="required" />
    134140                <attribute name="text" type="string" />
  • src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java

    diff --git a/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java b/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java
    index 86749ee..fa09340 100644
    a b import static org.openstreetmap.josm.tools.I18n.trn;  
    77
    88import java.awt.Component;
    99import java.awt.Dimension;
     10import java.awt.Font;
    1011import java.awt.GridBagLayout;
    1112import java.awt.Image;
    1213import java.awt.Insets;
    import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;  
    7172import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
    7273import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    7374import org.openstreetmap.josm.gui.util.GuiHelper;
    74 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    7575import org.openstreetmap.josm.io.MirroredInputStream;
    7676import org.openstreetmap.josm.tools.GBC;
    7777import org.openstreetmap.josm.tools.ImageProvider;
    7878import org.openstreetmap.josm.tools.UrlLabel;
     79import org.openstreetmap.josm.tools.Utils;
    7980import org.openstreetmap.josm.tools.XmlObjectParser;
    8081import org.openstreetmap.josm.tools.template_engine.ParseError;
    8182import org.openstreetmap.josm.tools.template_engine.TemplateEntry;
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    193194        return returnValue;
    194195    }
    195196
    196     protected static class PresetListEntry {
    197         String value;
    198         String display_value;
    199         String short_description;
     197    public static class PresetListEntry {
     198        public String value;
     199        public String display_value;
     200        public String short_description;
     201        public String icon;
     202        public String locale_display_value;
     203        public String locale_short_description;
    200204
    201205        public String getListDisplay() {
    202206            if (value.equals(DIFFERENT))
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    205209            if (value.equals(""))
    206210                return "&nbsp;";
    207211
    208             StringBuilder res = new StringBuilder("<b>");
    209             if (display_value != null) {
    210                 res.append(display_value);
    211             } else {
    212                 res.append(value);
    213             }
     212            final StringBuilder res = new StringBuilder("<b>");
     213            final String displ = Utils.firstNonNull(locale_display_value, tr(display_value), value);
     214            res.append(displ);
    214215            res.append("</b>");
    215             if (short_description != null) {
     216            final String descr = Utils.firstNonNull(locale_short_description, tr(short_description));
     217            if (descr != null) {
    216218                // wrap in table to restrict the text width
    217                 res.append("<br><table><td width='232'>(").append(short_description).append(")</td></table>");
     219                res.append("<div style=\"width:300px; padding:0 0 5px 5px\">").append(descr).append("</div>");
    218220            }
    219221            return res.toString();
    220222        }
    221223
    222         public PresetListEntry(String value) {
    223             this.value = value;
    224             this.display_value = value;
     224        public ImageIcon getIcon() {
     225            return icon == null ? null : ImageProvider.getIfAvailable(icon);
     226        }
     227
     228        public PresetListEntry() {
    225229        }
    226230
    227         public PresetListEntry(String value, String display_value) {
     231        public PresetListEntry(String value) {
    228232            this.value = value;
    229             this.display_value = display_value;
    230233        }
    231234
    232235        // toString is mainly used to initialize the Editor
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    234237        public String toString() {
    235238            if (value.equals(DIFFERENT))
    236239                return DIFFERENT;
    237             return display_value.replaceAll("<.*>", ""); // remove additional markup, e.g. <br>
     240            return display_value == null ? value : display_value.replaceAll("<.*>", ""); // remove additional markup, e.g. <br>
    238241        }
    239242    }
    240243
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    430433        public String use_last_as_default = "false";
    431434        public boolean required = false;
    432435
    433         protected List<String> short_description_list;
    434436        protected JComponent component;
    435         protected Map<String, PresetListEntry> lhm;
     437        protected Map<String, PresetListEntry> lhm = new LinkedHashMap<String, PresetListEntry>();
    436438        protected Usage usage;
    437439        protected Object originalValue;
    438440
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    444446
    445447            // find out if our key is already used in the selection.
    446448            usage = determineTextUsage(sel, key);
    447             String def = default_;
    448 
    449             char delChar = ';';
    450             if (!delimiter.isEmpty()) {
    451                 delChar = delimiter.charAt(0);
    452             }
    453 
    454             String[] value_array = splitEscaped(delChar, values);
    455449            String[] display_array;
    456             String[] short_descriptions_array = null;
    457450
    458             if (locale_display_values != null) {
    459                 display_array = splitEscaped(delChar, locale_display_values);
    460             } else if (display_values != null) {
    461                 display_array = splitEscaped(delChar, display_values);
     451            if (lhm.isEmpty()) {
     452                display_array = initListEntriesFromAttributes();
    462453            } else {
    463                 display_array = value_array;
     454                if (values != null) {
     455                    System.err.println(tr("Warning in tagging preset \"{0}-{1}\": "
     456                            + "Ignoring ''{2}'' attribute as ''{3}'' elements are given.",
     457                            key, text, "values", "list_entry"));
     458                }
     459                if (display_values != null || locale_display_values != null) {
     460                    System.err.println(tr("Warning in tagging preset \"{0}-{1}\": "
     461                            + "Ignoring ''{2}'' attribute as ''{3}'' elements are given.",
     462                            key, text, "display_values", "list_entry"));
     463                }
     464                if (short_descriptions != null || locale_short_descriptions != null) {
     465                    System.err.println(tr("Warning in tagging preset \"{0}-{1}\": "
     466                            + "Ignoring ''{2}'' attribute as ''{3}'' elements are given.",
     467                            key, text, "short_descriptions", "list_entry"));
     468                }
     469                display_array = new String[lhm.values().size()];
     470                int i = 0;
     471                for (PresetListEntry e : lhm.values()) {
     472                    display_array[i++] = e.display_value;
     473                }
    464474            }
    465475
    466             if (locale_short_descriptions != null) {
    467                 short_descriptions_array = splitEscaped(delChar, locale_short_descriptions);
    468             } else if (short_descriptions != null) {
    469                 short_descriptions_array = splitEscaped(delChar, short_descriptions);
    470             } else if (short_description_list != null) {
    471                 short_descriptions_array = short_description_list.toArray(new String[0]);
     476            if (locale_text == null) {
     477                if (text_context != null) {
     478                    locale_text = trc(text_context, fixPresetString(text));
     479                } else {
     480                    locale_text = tr(fixPresetString(text));
     481                }
    472482            }
     483            p.add(new JLabel(locale_text + ":"), GBC.std().insets(0, 0, 10, 0));
     484
     485            addToPanelAnchor(p, default_, display_array);
    473486
    474             if (!"false".equals(use_last_as_default) && def == null && lastValue.containsKey(key)) {
    475                 def = lastValue.get(key);
     487            return true;
     488
     489        }
     490
     491        private String[] initListEntriesFromAttributes() {
     492            char delChar = ';';
     493            if (!delimiter.isEmpty()) {
     494                delChar = delimiter.charAt(0);
    476495            }
    477496
     497            String[] value_array = splitEscaped(delChar, values);
     498
     499            final String displ = Utils.firstNonNull(locale_display_values, display_values);
     500            String[] display_array = displ == null ? value_array : splitEscaped(delChar, displ);
     501           
     502            final String descr = Utils.firstNonNull(locale_short_descriptions, short_descriptions);
     503            String[] short_descriptions_array = descr == null ? null : splitEscaped(delChar, descr);
     504
    478505            if (display_array.length != value_array.length) {
    479506                System.err.println(tr("Broken tagging preset \"{0}-{1}\" - number of items in ''display_values'' must be the same as in ''values''", key, text));
    480507                display_array = value_array;
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    485512                short_descriptions_array = null;
    486513            }
    487514
    488             lhm = new LinkedHashMap<String, PresetListEntry>();
    489515            if (!usage.hasUniqueValue() && !usage.unused()) {
    490516                lhm.put(DIFFERENT, new PresetListEntry(DIFFERENT));
    491517            }
    492518            for (int i = 0; i < value_array.length; i++) {
    493                 PresetListEntry e = new PresetListEntry(value_array[i]);
    494                 e.display_value = (locale_display_values == null)
    495                         ? (values_context == null ? tr(fixPresetString(display_array[i]))
    496                                 : trc(values_context, fixPresetString(display_array[i]))) : display_array[i];
    497                         if (short_descriptions_array != null) {
    498                             e.short_description = locale_short_descriptions == null ? tr(fixPresetString(short_descriptions_array[i]))
    499                                     : fixPresetString(short_descriptions_array[i]);
    500                         }
    501                         lhm.put(value_array[i], e);
    502             }
    503 
    504             if (locale_text == null) {
    505                 if (text_context != null) {
    506                     locale_text = trc(text_context, fixPresetString(text));
    507                 } else {
    508                     locale_text = tr(fixPresetString(text));
     519                final PresetListEntry e = new PresetListEntry(value_array[i]);
     520                e.locale_display_value = locale_display_values != null
     521                        ? display_array[i]
     522                        : trc(values_context, fixPresetString(display_array[i]));
     523                if (short_descriptions_array != null) {
     524                    e.locale_short_description = locale_short_descriptions != null
     525                            ? short_descriptions_array[i]
     526                            : tr(fixPresetString(short_descriptions_array[i]));
    509527                }
     528                lhm.put(value_array[i], e);
    510529            }
    511             p.add(new JLabel(locale_text + ":"), GBC.std().insets(0, 0, 10, 0));
    512 
    513             addToPanelAnchor(p, def, display_array);
    514 
    515             return true;
    516530
     531            return display_array;
    517532        }
    518533
    519534        protected String getDisplayIfNull(String display) {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    560575            changedTags.add(new Tag(key, value));
    561576        }
    562577
    563         public void setShort_description(String s) {
    564             if (short_description_list == null) {
    565                 short_description_list = new ArrayList<String>();
     578        public void addListEntry(PresetListEntry e) {
     579            lhm.put(e.value, e);
     580        }
     581
     582        public void addListEntries(Collection<PresetListEntry> e) {
     583            for (PresetListEntry i : e) {
     584                addListEntry(i);
    566585            }
    567             short_description_list.add(tr(s));
    568586        }
    569587
    570588        @Override
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    575593        protected ListCellRenderer getListCellRenderer() {
    576594            return new ListCellRenderer() {
    577595
    578                 HtmlPanel lbl = new HtmlPanel();
     596                JLabel lbl = new JLabel();
    579597                JComponent dummy = new JComponent() {
    580598                };
    581599
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    594612                    }
    595613
    596614                    PresetListEntry item = (PresetListEntry) value;
    597                     String s = item.getListDisplay();
    598                     lbl.setText(s);
     615                    lbl.setOpaque(true);
     616                    lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
     617                    lbl.setText("<html>" + item.getListDisplay() + "</html>");
     618                    lbl.setIcon(item.getIcon());
    599619                    lbl.setEnabled(list.isEnabled());
    600620                    // We do not want the editor to have the maximum height of all
    601621                    // entries. Return a dummy with bogus height.
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    11401160        parser.map("label", Label.class);
    11411161        parser.map("space", Space.class);
    11421162        parser.map("key", Key.class);
     1163        parser.map("list_entry", PresetListEntry.class);
    11431164        LinkedList<TaggingPreset> all = new LinkedList<TaggingPreset>();
    11441165        TaggingPresetMenu lastmenu = null;
    11451166        Roles lastrole = null;
     1167        List<PresetListEntry> listEntries = new LinkedList<PresetListEntry>();
    11461168
    11471169        if (validate) {
    11481170            parser.startWithValidation(in, "http://josm.openstreetmap.de/tagging-preset-1.0", "resource://data/tagging-preset.xsd");
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange  
    11761198                all.add(tp);
    11771199                lastrole = null;
    11781200            } else {
    1179                 if(all.size() != 0) {
    1180                     if(o instanceof Roles) {
    1181                         all.getLast().data.add((Item)o);
     1201                if (all.size() != 0) {
     1202                    if (o instanceof Roles) {
     1203                        all.getLast().data.add((Item) o);
    11821204                        lastrole = (Roles) o;
    1183                     }
    1184                     else if(o instanceof Role) {
    1185                         if(lastrole == null)
     1205                    } else if (o instanceof Role) {
     1206                        if (lastrole == null) {
    11861207                            throw new SAXException(tr("Preset role element without parent"));
     1208                        }
    11871209                        lastrole.roles.add((Role) o);
    1188                     }
    1189                     else {
    1190                         all.getLast().data.add((Item)o);
     1210                    } else if (o instanceof PresetListEntry) {
     1211                        listEntries.add((PresetListEntry) o);
     1212                    } else {
     1213                        all.getLast().data.add((Item) o);
     1214                        if (o instanceof ComboMultiSelect) {
     1215                            ((ComboMultiSelect) o).addListEntries(listEntries);
     1216                        }
     1217                        listEntries = new LinkedList<PresetListEntry>();
    11911218                        lastrole = null;
    11921219                    }
    11931220                } else
  • src/org/openstreetmap/josm/tools/Utils.java

    diff --git a/src/org/openstreetmap/josm/tools/Utils.java b/src/org/openstreetmap/josm/tools/Utils.java
    index 8c26f43..2ea3c7d 100644
    a b public class Utils {  
    6262        return null;
    6363    }
    6464
    65         public static <T> Collection<T> filter(Collection<? extends T> collection, Predicate<? super T> predicate) {
    66                 return new FilteredCollection<T>(collection, predicate);
    67         }
     65    public static <T> Collection<T> filter(Collection<? extends T> collection, Predicate<? super T> predicate) {
     66        return new FilteredCollection<T>(collection, predicate);
     67    }
     68
     69    public static <T> T firstNonNull(T... items) {
     70        for (T i : items) {
     71            if (i != null) {
     72                return i;
     73            }
     74        }
     75        return null;
     76    }
    6877
    6978    /**
    7079     * Filter a collection by (sub)class.